feat: platform 接入天梯登陆的 依赖
This commit is contained in:
parent
dd69823a00
commit
47c9ec1aba
@ -54,7 +54,8 @@
|
||||
"vue-types": "~5.1.3",
|
||||
"vue-virtual-scroller": "2.0.0-beta.8",
|
||||
"wujie": "^1.0.25",
|
||||
"xlsx": "~0.18.5"
|
||||
"xlsx": "~0.18.5",
|
||||
"@sy/unified-login": "1.0.29"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "~19.5.0",
|
||||
|
@ -1,41 +1,30 @@
|
||||
import axios from 'axios';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import router from '@/router';
|
||||
// import { useUserStore } from '@/store/modules/user';
|
||||
// import router from '@/router';
|
||||
import appClient from '@/io/tianti';
|
||||
|
||||
console.log('appClient', appClient);
|
||||
|
||||
// axios拦截器
|
||||
const { reqInterceptor, resInterceptor } = appClient.getInterceptor();
|
||||
console.log('reqInterceptor', reqInterceptor);
|
||||
console.log('resInterceptor', resInterceptor);
|
||||
|
||||
const baseApiUrl = import.meta.env.VITE_BASE_API_URL;
|
||||
|
||||
// 创建独立实例
|
||||
const instance = axios.create({
|
||||
baseURL: baseApiUrl, // 基础URL直接放在实例配置中
|
||||
baseURL: baseApiUrl,
|
||||
});
|
||||
|
||||
// 请求拦截器改为使用实例
|
||||
instance.interceptors.request.use(
|
||||
(config) => {
|
||||
// 可在此处添加统一请求头等配置
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
},
|
||||
(config) => config,
|
||||
(error) => Promise.reject(error),
|
||||
);
|
||||
instance.interceptors.request.use(reqInterceptor.fulfilled, reqInterceptor.rejected);
|
||||
|
||||
// 响应拦截器改为使用实例
|
||||
instance.interceptors.response.use(
|
||||
(response) => {
|
||||
// 如果响应数据中 code 为 -1,清空登录状态并跳转到登录页
|
||||
if (response?.data?.code === -1) {
|
||||
const userStore = useUserStore();
|
||||
userStore.clearLoginStatus(); // 清空用户信息
|
||||
router.push('/login'); // 直接使用路由实例
|
||||
console.error('请求失败:', response.data.msg);
|
||||
}
|
||||
return response;
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
// 响应拦截器
|
||||
instance.interceptors.response.use(resInterceptor.fulfilled, resInterceptor.rejected);
|
||||
|
||||
// 导出实例
|
||||
export default instance;
|
||||
|
12
apps/platform/src/io/tianti.ts
Normal file
12
apps/platform/src/io/tianti.ts
Normal file
@ -0,0 +1,12 @@
|
||||
// @ts-ignore
|
||||
import AxiosAppClient from '@sy/unified-login/es/app-client/axios';
|
||||
|
||||
export type Env = 'dev' | 'test' | 'pre' | 'prod';
|
||||
|
||||
const appClient = new AxiosAppClient({
|
||||
appKey: 'y-code', // 应用标识,不同项目不能一样
|
||||
env: 'prod', // dev:本地开发;test:测试;pre:预发布;prod:正式
|
||||
devBaseUrl: `https://localhost:${import.meta.env.VITE_PORT}`, // 应用开发环境地址
|
||||
});
|
||||
|
||||
export default appClient;
|
@ -33,10 +33,15 @@
|
||||
</Menu.Item> -->
|
||||
<Menu.Divider />
|
||||
<Menu.Item>
|
||||
<div @click.prevent="doLogout">
|
||||
<div @click.prevent="tianti.logout">
|
||||
<poweroff-outlined /> {{ $t('layout.header.dropdownItemLoginOut') }}
|
||||
</div>
|
||||
</Menu.Item>
|
||||
<Menu.Item v-if="isDevEnv">
|
||||
<div @click.prevent="tianti.openDev">
|
||||
{{ $t('layout.header.openDev') }}
|
||||
</div>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</template>
|
||||
</Dropdown>
|
||||
@ -49,6 +54,8 @@
|
||||
<script lang="tsx" setup>
|
||||
import { computed, type CSSProperties } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import tianti from '@/io/tianti';
|
||||
|
||||
import {
|
||||
QuestionCircleOutlined,
|
||||
MenuFoldOutlined,
|
||||
@ -71,6 +78,8 @@
|
||||
import { LOGIN_NAME } from '@/router/constant';
|
||||
import { useLayoutSettingStore } from '@/store/modules/layoutSetting';
|
||||
|
||||
const isDevEnv = import.meta.env.VITE_NODE_ENV === 'development';
|
||||
|
||||
defineProps({
|
||||
collapsed: {
|
||||
type: Boolean,
|
||||
|
@ -1,20 +1,20 @@
|
||||
{
|
||||
"footer": { "onlinePreview": "在线预览", "onlineDocument": "在线文档" },
|
||||
"footer": {
|
||||
"onlinePreview": "在线预览",
|
||||
"onlineDocument": "在线文档"
|
||||
},
|
||||
"header": {
|
||||
"dropdownItemDoc": "文档",
|
||||
"dropdownItemLoginOut": "退出系统",
|
||||
|
||||
"openDev": "打开开发环境",
|
||||
"tooltipErrorLog": "错误日志",
|
||||
"tooltipLock": "锁定屏幕",
|
||||
"tooltipNotify": "消息通知",
|
||||
|
||||
"tooltipEntryFull": "全屏",
|
||||
"tooltipExitFull": "退出全屏",
|
||||
|
||||
"lockScreenPassword": "锁屏密码",
|
||||
"lockScreen": "锁定屏幕",
|
||||
"lockScreenBtn": "锁定",
|
||||
|
||||
"home": "首页"
|
||||
},
|
||||
"multipleTab": {
|
||||
@ -38,20 +38,15 @@
|
||||
"menuTypeMixSidebar": "左侧菜单混合模式",
|
||||
"menuTypeMix": "顶部菜单混合模式",
|
||||
"menuTypeTopMenu": "顶部菜单模式",
|
||||
|
||||
"on": "开",
|
||||
"off": "关",
|
||||
"minute": "分钟",
|
||||
|
||||
"operatingTitle": "操作成功",
|
||||
"operatingContent": "复制成功,请到 src/settings/projectSetting.ts 中修改配置!",
|
||||
"resetSuccess": "重置成功!",
|
||||
|
||||
"copyBtn": "拷贝",
|
||||
"clearBtn": "清空缓存并返回登录页",
|
||||
|
||||
"drawerTitle": "项目配置",
|
||||
|
||||
"darkMode": "主题",
|
||||
"navMode": "导航栏模式",
|
||||
"interfaceFunction": "界面功能",
|
||||
@ -59,11 +54,9 @@
|
||||
"animation": "动画",
|
||||
"splitMenu": "分割菜单",
|
||||
"closeMixSidebarOnChange": "切换页面关闭菜单",
|
||||
|
||||
"sysTheme": "系统主题",
|
||||
"headerTheme": "顶栏主题",
|
||||
"sidebarTheme": "菜单主题",
|
||||
|
||||
"menuDrag": "侧边菜单拖拽",
|
||||
"menuSearch": "菜单搜索",
|
||||
"menuAccordion": "侧边菜单手风琴模式",
|
||||
@ -73,7 +66,6 @@
|
||||
"menuCollapseButton": "菜单折叠按钮",
|
||||
"contentMode": "内容区域宽度",
|
||||
"expandedMenuWidth": "菜单展开宽度",
|
||||
|
||||
"breadcrumb": "面包屑",
|
||||
"breadcrumbIcon": "面包屑图标",
|
||||
"tabs": "标签页",
|
||||
@ -87,22 +79,17 @@
|
||||
"fullContent": "全屏内容",
|
||||
"grayMode": "灰色模式",
|
||||
"colorWeak": "色弱模式",
|
||||
|
||||
"progress": "顶部进度条",
|
||||
"switchLoading": "切换loading",
|
||||
"switchAnimation": "切换动画",
|
||||
"animationType": "动画类型",
|
||||
|
||||
"autoScreenLock": "自动锁屏",
|
||||
"notAutoScreenLock": "不自动锁屏",
|
||||
|
||||
"fixedHeader": "固定header",
|
||||
"fixedSideBar": "固定Sidebar",
|
||||
|
||||
"mixSidebarTrigger": "混合菜单触发方式",
|
||||
"triggerHover": "悬停",
|
||||
"triggerClick": "点击",
|
||||
|
||||
"mixSidebarFixed": "固定展开菜单"
|
||||
}
|
||||
}
|
@ -13,6 +13,10 @@ import { setupStore } from '@/store';
|
||||
import { setupI18n } from '@/locales';
|
||||
import { setupAntd, setupAssets, setupGlobalMethods } from '@/plugins';
|
||||
|
||||
import tianti from '@/io/tianti';
|
||||
|
||||
tianti.checkQuery();
|
||||
|
||||
dayjs.extend(customParseFormat);
|
||||
dayjs.extend(utc);
|
||||
dayjs.extend(timezone);
|
||||
|
@ -13,60 +13,27 @@ const routes: Array<RouteRecordRaw> = [
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'list',
|
||||
name: `${moduleName}-list`,
|
||||
path: 'login',
|
||||
name: `${moduleName}-login`,
|
||||
meta: {
|
||||
title: '用户列表',
|
||||
title: '登录',
|
||||
icon: 'ant-design:unordered-list-outlined',
|
||||
keepAlive: true,
|
||||
hideInMenu: false,
|
||||
},
|
||||
component: () => import('@/views/user/list.vue'),
|
||||
},
|
||||
{
|
||||
path: 'add',
|
||||
name: `${moduleName}-add`,
|
||||
meta: {
|
||||
title: '新增用户',
|
||||
icon: 'ant-design:user-add-outlined',
|
||||
hideInMenu: true,
|
||||
activeMenu: `${moduleName}-list`,
|
||||
},
|
||||
component: () => import('@/views/user/add.vue'),
|
||||
},
|
||||
{
|
||||
path: 'edit/:id',
|
||||
name: `${moduleName}-edit`,
|
||||
meta: {
|
||||
title: '编辑用户',
|
||||
icon: 'ant-design:edit-outlined',
|
||||
hideInMenu: true,
|
||||
activeMenu: `${moduleName}-list`,
|
||||
},
|
||||
component: () => import('@/views/user/edit.vue'),
|
||||
},
|
||||
{
|
||||
path: 'detail/:id',
|
||||
name: `${moduleName}-detail`,
|
||||
meta: {
|
||||
title: '用户详情',
|
||||
icon: 'ant-design:profile-outlined',
|
||||
hideInMenu: true,
|
||||
activeMenu: `${moduleName}-list`,
|
||||
},
|
||||
component: () => import('@/views/user/detail.vue'),
|
||||
},
|
||||
{
|
||||
path: 'change-password/:id',
|
||||
name: `${moduleName}-change-password`,
|
||||
meta: {
|
||||
title: '修改密码',
|
||||
icon: 'ant-design:lock-outlined',
|
||||
hideInMenu: true,
|
||||
activeMenu: `${moduleName}-list`,
|
||||
},
|
||||
component: () => import('@/views/user/change-password.vue'),
|
||||
component: () => import('@/views/login/index.vue'),
|
||||
},
|
||||
// {
|
||||
// path: 'list',
|
||||
// name: `${moduleName}-list`,
|
||||
// meta: {
|
||||
// title: '用户列表',
|
||||
// icon: 'ant-design:unordered-list-outlined',
|
||||
// keepAlive: true,
|
||||
// hideInMenu: false,
|
||||
// },
|
||||
// component: () => import('@/views/user/list.vue'),
|
||||
// },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
28
apps/platform/src/views/error/403.vue
Normal file
28
apps/platform/src/views/error/403.vue
Normal file
@ -0,0 +1,28 @@
|
||||
<script lang="jsx">
|
||||
import { defineComponent } from 'vue';
|
||||
import OneClickAuth from '@sy/unified-login/one-click-auth.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ForbiddenPage',
|
||||
|
||||
setup() {
|
||||
return () => {
|
||||
return (
|
||||
<div class="forbidden-page">
|
||||
<OneClickAuth env="dev" appMark={30} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.forbidden-page {
|
||||
display: flex;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
@ -2,7 +2,13 @@
|
||||
<div>1</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
<script setup lang="ts">
|
||||
import { getProjectList } from '@/io';
|
||||
|
||||
getProjectList().then((res) => {
|
||||
console.log('res', res);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.login-box {
|
||||
|
@ -1,60 +0,0 @@
|
||||
<template>
|
||||
<div class="add-user">
|
||||
<a-card :bordered="false">
|
||||
<a-form layout="vertical" :model="userForm" @submit="handleAddUser">
|
||||
<a-form-item label="用户名">
|
||||
<a-input
|
||||
v-model:value="userForm.username"
|
||||
placeholder="请输入用户名"
|
||||
allow-clear
|
||||
style="max-width: 400px"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="密码">
|
||||
<a-input
|
||||
v-model:value="userForm.password"
|
||||
placeholder="请输入密码"
|
||||
type="password"
|
||||
allow-clear
|
||||
style="max-width: 400px"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-space>
|
||||
<a-button type="primary" html-type="submit">新增用户</a-button>
|
||||
<a-button @click="goBack">取消</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useTabsViewStore } from '@/store/modules/tabsView';
|
||||
const { closeCurrentTab } = useTabsViewStore();
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
||||
// 用户表单数据
|
||||
const userForm = reactive({
|
||||
username: '',
|
||||
password: '',
|
||||
});
|
||||
|
||||
// 新增用户
|
||||
const handleAddUser = async () => {
|
||||
// TODO: 调用新增用户接口
|
||||
message.success('用户新增成功');
|
||||
goBack();
|
||||
};
|
||||
|
||||
const goBack = () => {
|
||||
router.back();
|
||||
closeCurrentTab(route);
|
||||
};
|
||||
</script>
|
@ -1,66 +0,0 @@
|
||||
<template>
|
||||
<div class="change-password">
|
||||
<a-card :bordered="false">
|
||||
<a-form layout="vertical" :model="passwordForm" @submit="handleChangePassword">
|
||||
<a-form-item label="新密码">
|
||||
<a-input
|
||||
v-model:value="passwordForm.newPassword"
|
||||
placeholder="请输入新密码"
|
||||
type="password"
|
||||
allow-clear
|
||||
style="max-width: 400px"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="确认密码">
|
||||
<a-input
|
||||
v-model:value="passwordForm.confirmPassword"
|
||||
placeholder="请确认新密码"
|
||||
type="password"
|
||||
allow-clear
|
||||
style="max-width: 400px"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-space>
|
||||
<a-button type="primary" html-type="submit">修改密码</a-button>
|
||||
<a-button type="default" @click="goBack">取消</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { reactive } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useTabsViewStore } from '@/store/modules/tabsView';
|
||||
const { closeCurrentTab } = useTabsViewStore();
|
||||
|
||||
const router = useRouter();
|
||||
console.log('router', router);
|
||||
const route = useRoute();
|
||||
|
||||
// 密码表单数据
|
||||
const passwordForm = reactive({
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
});
|
||||
|
||||
// 修改密码
|
||||
const handleChangePassword = async () => {
|
||||
if (passwordForm.newPassword !== passwordForm.confirmPassword) {
|
||||
message.error('两次输入的密码不一致');
|
||||
return;
|
||||
}
|
||||
// TODO: 调用修改密码接口
|
||||
message.success('密码修改成功');
|
||||
goBack();
|
||||
};
|
||||
|
||||
const goBack = () => {
|
||||
router.back();
|
||||
closeCurrentTab(route);
|
||||
};
|
||||
</script>
|
@ -1,94 +0,0 @@
|
||||
<template>
|
||||
<div class="user-detail">
|
||||
<a-card title="用户详情" :bordered="false">
|
||||
<!-- 基本信息 -->
|
||||
<a-descriptions bordered>
|
||||
<a-descriptions-item label="用户名">
|
||||
{{ userInfo.username }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="昵称">
|
||||
{{ userInfo.nickname }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="手机号">
|
||||
{{ userInfo.phone }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="邮箱">
|
||||
{{ userInfo.email }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="状态">
|
||||
<a-tag :color="userInfo.status === 1 ? 'green' : 'red'">
|
||||
{{ userInfo.status === 1 ? '启用' : '禁用' }}
|
||||
</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="创建时间">
|
||||
{{ userInfo.createTime }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="operation-buttons" style="margin-top: 24px">
|
||||
<a-button type="primary" @click="handleEdit">编辑</a-button>
|
||||
<a-button style="margin-left: 8px" @click="goBack">返回</a-button>
|
||||
</div>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useTabsViewStore } from '@/store/modules/tabsView';
|
||||
const { closeCurrentTab } = useTabsViewStore();
|
||||
|
||||
const userInfo = ref({
|
||||
username: 'mockUser',
|
||||
nickname: 'mockNickname',
|
||||
phone: '1234567890',
|
||||
email: 'mock@example.com',
|
||||
status: 1,
|
||||
createTime: '2023-01-01 12:00:00',
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
onMounted(() => {
|
||||
getUserDetail();
|
||||
});
|
||||
|
||||
// 获取用户详情
|
||||
async function getUserDetail() {
|
||||
try {
|
||||
const userId = route.params.id;
|
||||
// 这里替换成实际的 API 调用
|
||||
const response = await $api.user.getDetail(userId);
|
||||
userInfo.value = response.data;
|
||||
} catch (err) {
|
||||
console.error('err', err);
|
||||
$message.error('获取用户详情失败');
|
||||
}
|
||||
}
|
||||
|
||||
// 编辑用户
|
||||
function handleEdit() {
|
||||
const userId = route.params.id;
|
||||
router.push(`/user/edit/${userId}`);
|
||||
}
|
||||
|
||||
// 返回上一页并关闭当前标签
|
||||
function goBack() {
|
||||
router.back();
|
||||
closeCurrentTab(route);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.user-detail {
|
||||
padding: 24px;
|
||||
background: #fff;
|
||||
|
||||
.operation-buttons {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,106 +0,0 @@
|
||||
<template>
|
||||
<div class="user-edit">
|
||||
<a-card :bordered="false">
|
||||
<a-form layout="vertical" :model="userForm" @submit="handleSave">
|
||||
<a-form-item label="用户名">
|
||||
<a-input
|
||||
v-model:value="userForm.username"
|
||||
placeholder="请输入用户名"
|
||||
allow-clear
|
||||
style="max-width: 400px"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="昵称">
|
||||
<a-input
|
||||
v-model:value="userForm.nickname"
|
||||
placeholder="请输入昵称"
|
||||
allow-clear
|
||||
style="max-width: 400px"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="手机号">
|
||||
<a-input
|
||||
v-model:value="userForm.phone"
|
||||
placeholder="请输入手机号"
|
||||
allow-clear
|
||||
style="max-width: 400px"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="邮箱">
|
||||
<a-input
|
||||
v-model:value="userForm.email"
|
||||
placeholder="请输入邮箱"
|
||||
allow-clear
|
||||
style="max-width: 400px"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态">
|
||||
<a-select v-model:value="userForm.status" style="max-width: 400px">
|
||||
<a-select-option :value="1">启用</a-select-option>
|
||||
<a-select-option :value="0">禁用</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-space>
|
||||
<a-button type="primary" html-type="submit">保存</a-button>
|
||||
<a-button @click="goBack">取消</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useTabsViewStore } from '@/store/modules/tabsView';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const { closeCurrentTab } = useTabsViewStore();
|
||||
|
||||
// 用户信息表单数据
|
||||
const userForm = ref({
|
||||
username: '',
|
||||
nickname: '',
|
||||
phone: '',
|
||||
email: '',
|
||||
status: 1,
|
||||
});
|
||||
|
||||
// 保存用户信息
|
||||
const handleSave = async () => {
|
||||
// TODO: 调用保存接口
|
||||
message.success('保存成功');
|
||||
goBack();
|
||||
};
|
||||
|
||||
// 取消编辑
|
||||
const goBack = () => {
|
||||
router.back(); // 假设返回用户列表页面
|
||||
closeCurrentTab(route); // 关闭当前标签页
|
||||
};
|
||||
|
||||
// 初始化用户信息(可以通过接口获取)
|
||||
const initUserData = async (userId: string) => {
|
||||
// TODO: 调用接口获取用户信息
|
||||
// const res = await getUserInfo(userId);
|
||||
|
||||
// 添加 mock 数据
|
||||
userForm.value = {
|
||||
username: 'mockUser',
|
||||
nickname: 'mockNickname',
|
||||
phone: '1234567890',
|
||||
email: 'mock@example.com',
|
||||
status: 1,
|
||||
};
|
||||
};
|
||||
|
||||
// 获取用户ID并初始化数据
|
||||
const userId = route.params.id; // 假设路由中有用户ID
|
||||
if (userId) {
|
||||
initUserData(userId);
|
||||
}
|
||||
</script>
|
@ -1,219 +0,0 @@
|
||||
<template>
|
||||
<div class="user-list">
|
||||
<a-card :bordered="false">
|
||||
<!-- 搜索区域 -->
|
||||
<a-form layout="inline" :model="searchForm" @submit="handleSearch">
|
||||
<a-form-item label="用户名" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
|
||||
<a-input v-model:value="searchForm.username" placeholder="请输入用户名" allow-clear />
|
||||
</a-form-item>
|
||||
<a-form-item label="手机号" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }">
|
||||
<a-input v-model:value="searchForm.phone" placeholder="请输入手机号" allow-clear />
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-space>
|
||||
<a-button type="primary" html-type="submit">查询</a-button>
|
||||
<a-button @click="resetSearch">重置</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
|
||||
<!-- 操作按钮区域 -->
|
||||
<div class="table-operations">
|
||||
<a-space>
|
||||
<a-button type="primary" @click="handleAdd">
|
||||
<template #icon>
|
||||
<plus-outlined />
|
||||
</template>
|
||||
新增用户
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
|
||||
<!-- 表格区域 -->
|
||||
<a-table
|
||||
:columns="columns"
|
||||
:data-source="tableData"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
:row-selection="{ selectedRowKeys, onChange: onSelectChange }"
|
||||
row-key="id"
|
||||
@change="handleTableChange"
|
||||
>
|
||||
<!-- 状态列 -->
|
||||
<template #status="{ text }">
|
||||
<a-tag :color="text ? 'success' : 'error'">
|
||||
{{ text ? '启用' : '禁用' }}
|
||||
</a-tag>
|
||||
</template>
|
||||
|
||||
<!-- 操作列 -->
|
||||
<template #action="{ record }">
|
||||
<a-space>
|
||||
<a-button type="link" @click="handleEdit(record)">编辑</a-button>
|
||||
<a-button type="link" @click="handleDetail(record)">详情</a-button>
|
||||
<a-button type="link" @click="handleChangePassword(record)">修改密码</a-button>
|
||||
<a-popconfirm title="确定要删除这条记录吗?" @confirm="handleDelete(record)">
|
||||
<a-button type="link" danger>删除</a-button>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { PlusOutlined } from '@ant-design/icons-vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
// 搜索表单数据
|
||||
const searchForm = reactive({
|
||||
username: '',
|
||||
phone: '',
|
||||
});
|
||||
|
||||
// 表格列配置
|
||||
const columns = [
|
||||
{
|
||||
title: '用户名',
|
||||
dataIndex: 'username',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '昵称',
|
||||
dataIndex: 'nickname',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '手机号',
|
||||
dataIndex: 'phone',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
width: 100,
|
||||
slots: { customRender: 'status' },
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
width: 280,
|
||||
slots: { customRender: 'action' },
|
||||
},
|
||||
];
|
||||
|
||||
// 表格数据
|
||||
const loading = ref(false);
|
||||
const tableData = ref<any[]>([]);
|
||||
const selectedRowKeys = ref<string[]>([]);
|
||||
const pagination = reactive({
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0,
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
});
|
||||
|
||||
// 获取表格数据
|
||||
const getTableData = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
// TODO: 调用接口获取数据
|
||||
// const res = await getUserList({
|
||||
// ...searchForm,
|
||||
// page: pagination.current,
|
||||
// pageSize: pagination.pageSize,
|
||||
// });
|
||||
// tableData.value = res.data.list;
|
||||
// pagination.total = res.data.total;
|
||||
|
||||
// 模拟数据
|
||||
tableData.value = Array.from({ length: 10 }).map((_, index) => ({
|
||||
id: index + 1,
|
||||
username: `user${index + 1}`,
|
||||
nickname: `用户${index + 1}`,
|
||||
phone: '13800138000',
|
||||
email: `user${index + 1}@example.com`,
|
||||
status: index % 2,
|
||||
createTime: '2024-03-20 12:00:00',
|
||||
}));
|
||||
pagination.total = 100;
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 表格选择改变
|
||||
const onSelectChange = (keys: string[]) => {
|
||||
selectedRowKeys.value = keys;
|
||||
};
|
||||
|
||||
// 表格分页、排序、筛选变化
|
||||
const handleTableChange = (pag: any) => {
|
||||
pagination.current = pag.current;
|
||||
pagination.pageSize = pag.pageSize;
|
||||
getTableData();
|
||||
};
|
||||
|
||||
// 搜索
|
||||
const handleSearch = () => {
|
||||
pagination.current = 1;
|
||||
getTableData();
|
||||
};
|
||||
|
||||
// 重置搜索
|
||||
const resetSearch = () => {
|
||||
searchForm.username = '';
|
||||
searchForm.phone = '';
|
||||
handleSearch();
|
||||
};
|
||||
|
||||
// 新增用户
|
||||
const handleAdd = () => {
|
||||
router.push('/user/add');
|
||||
};
|
||||
|
||||
// 编辑用户
|
||||
const handleEdit = (record: any) => {
|
||||
router.push(`/user/edit/${record.id}`);
|
||||
};
|
||||
|
||||
// 查看详情
|
||||
const handleDetail = (record: any) => {
|
||||
router.push(`/user/detail/${record.id}`);
|
||||
};
|
||||
|
||||
// 修改密码
|
||||
const handleChangePassword = (record: any) => {
|
||||
router.push(`/user/change-password/${record.id}`);
|
||||
};
|
||||
|
||||
// 删除用户
|
||||
const handleDelete = async (record: any) => {
|
||||
// TODO: 调用删除接口
|
||||
message.success('删除成功');
|
||||
getTableData();
|
||||
};
|
||||
|
||||
// 初始化
|
||||
getTableData();
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.user-list {
|
||||
.table-operations {
|
||||
margin: 16px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@ -183,6 +183,9 @@ importers:
|
||||
'@iframe-resizer/parent':
|
||||
specifier: ^5.3.3
|
||||
version: 5.3.3
|
||||
'@sy/unified-login':
|
||||
specifier: 1.0.29
|
||||
version: 1.0.29(vue@3.5.13(typescript@5.6.3))
|
||||
'@sy/y-code-renderer-adapter':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/render-adapter
|
||||
@ -3119,6 +3122,11 @@ packages:
|
||||
'@sxzz/popperjs-es@2.11.7':
|
||||
resolution: {integrity: sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==}
|
||||
|
||||
'@sy/unified-login@1.0.29':
|
||||
resolution: {integrity: sha512-ihYgOX8mrrDcXjsxO0C40647F7DbMs3mBMBn0deAV2tIfCEJRMMtryP8Fi4T5UDfEXVpRHoSFNW4zpTIbsL4Vw==}
|
||||
peerDependencies:
|
||||
vue: ^2.0.0 || >=3.0.0
|
||||
|
||||
'@sy/y-code-chart@1.2.7':
|
||||
resolution: {integrity: sha512-87/au4OoafTQSqwAAJhB8XpzwTlpu1u42VqYPG28JDarUOva/12eEyAU5i+e7e3t1pV+JSqP+Q/4HIhQw61q9w==}
|
||||
|
||||
@ -13090,6 +13098,10 @@ snapshots:
|
||||
|
||||
'@sxzz/popperjs-es@2.11.7': {}
|
||||
|
||||
'@sy/unified-login@1.0.29(vue@3.5.13(typescript@5.6.3))':
|
||||
dependencies:
|
||||
vue: 3.5.13(typescript@5.6.3)
|
||||
|
||||
'@sy/y-code-chart@1.2.7(vue@3.5.13(typescript@5.3.3))':
|
||||
dependencies:
|
||||
'@antv/g2plot': 2.4.32
|
||||
|
Loading…
x
Reference in New Issue
Block a user