wip: add account management page
2个文件已删除
10个文件已添加
11个文件已修改
New file |
| | |
| | | import { MockMethod } from 'vite-plugin-mock'; |
| | | import { resultPageSuccess } from '../_util'; |
| | | |
| | | const list = (() => { |
| | | const result: any[] = []; |
| | | for (let index = 0; index < 20; index++) { |
| | | result.push({ |
| | | id: `${index}`, |
| | | account: '@first', |
| | | email: '@email', |
| | | nickname: '@cname()', |
| | | role: '@first', |
| | | updateTime: '@datetime', |
| | | remark: '@cword(0,20)', |
| | | }); |
| | | } |
| | | return result; |
| | | })(); |
| | | |
| | | export default [ |
| | | { |
| | | url: '/api/system/getAccountList', |
| | | timeout: 100, |
| | | method: 'get', |
| | | response: ({ query }) => { |
| | | const { page = 1, pageSize = 20 } = query; |
| | | return resultPageSuccess(page, pageSize, list); |
| | | }, |
| | | }, |
| | | ] as MockMethod[]; |
| | |
| | | export default [ |
| | | { |
| | | url: '/api/table/getDemoList', |
| | | timeout: 1000, |
| | | timeout: 100, |
| | | method: 'get', |
| | | response: ({ query }) => { |
| | | const { page = 1, pageSize = 20 } = query; |
New file |
| | |
| | | import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel'; |
| | | |
| | | export type Params = BasicPageParams & { |
| | | account?: string; |
| | | nickname?: string; |
| | | }; |
| | | |
| | | export interface DemoListItem { |
| | | id: string; |
| | | account: string; |
| | | email: string; |
| | | nickname: string; |
| | | role: number; |
| | | updateTime: string; |
| | | remark: string; |
| | | } |
| | | |
| | | /** |
| | | * @description: Request list return value |
| | | */ |
| | | export type DemoListGetResultModel = BasicFetchResult<DemoListItem>; |
New file |
| | |
| | | import { Params, DemoListGetResultModel } from './model/systemModel'; |
| | | import { defHttp } from '/@/utils/http/axios'; |
| | | |
| | | enum Api { |
| | | // The address does not exist |
| | | AccountList = '/system/getAccountList', |
| | | } |
| | | |
| | | export const getAccountList = (params: Params) => |
| | | defHttp.get<DemoListGetResultModel>({ url: Api.AccountList, params }); |
| | |
| | | |
| | | .@{prefix-cls} { |
| | | &-form-container { |
| | | width: 100%; |
| | | padding: 16px; |
| | | |
| | | .ant-form { |
| | |
| | | |
| | | // |
| | | .ant-table { |
| | | // width: 100%; |
| | | // overflow-x: hidden; |
| | | width: 100%; |
| | | overflow-x: hidden; |
| | | // border: none; |
| | | |
| | | &-title { |
| | |
| | | // overflow-y: hidden !important; |
| | | // } |
| | | |
| | | // .ant-table-fixed { |
| | | // border-bottom: none; |
| | | // } |
| | | // .ant-table-fixed { |
| | | // border-bottom: none; |
| | | // } |
| | | // } |
| | | |
| | | // .ant-table-bordered .ant-table-thead > tr:not(:last-child) > th, |
| | | // .ant-table-tbody > tr > td { |
| | | // word-break: break-word; |
| | | // border-color: @border-color !important; |
| | | // // border-color: @border-color !important; |
| | | // } |
| | | |
| | | .ant-table-footer { |
New file |
| | |
| | | export default { |
| | | moduleName: 'System management', |
| | | |
| | | account: 'Account management', |
| | | }; |
New file |
| | |
| | | export default { |
| | | moduleName: '系统管理', |
| | | |
| | | account: '账号管理', |
| | | }; |
New file |
| | |
| | | import type { MenuModule } from '/@/router/types'; |
| | | import { t } from '/@/hooks/web/useI18n'; |
| | | |
| | | const menu: MenuModule = { |
| | | orderNo: 2000, |
| | | menu: { |
| | | name: t('routes.demo.system.moduleName'), |
| | | path: '/system', |
| | | children: [ |
| | | { |
| | | path: 'account', |
| | | name: t('routes.demo.system.account'), |
| | | }, |
| | | ], |
| | | }, |
| | | }; |
| | | export default menu; |
| | |
| | | component: LAYOUT, |
| | | redirect: '/dashboard/workbench', |
| | | meta: { |
| | | icon: 'bx:bx-home', |
| | | icon: 'ion:grid-outline', |
| | | title: t('routes.dashboard.dashboard'), |
| | | }, |
| | | children: [ |
| | |
| | | component: LAYOUT, |
| | | redirect: '/charts/apexChart', |
| | | meta: { |
| | | icon: 'vaadin:spline-area-chart', |
| | | icon: 'ion:bar-chart-outline', |
| | | title: t('routes.demo.charts.charts'), |
| | | }, |
| | | children: [ |
| | |
| | | component: LAYOUT, |
| | | redirect: '/comp/basic', |
| | | meta: { |
| | | icon: 'ic:outline-settings-input-component', |
| | | icon: 'ion:layers-outline', |
| | | title: t('routes.demo.comp.comp'), |
| | | }, |
| | | |
| | |
| | | component: LAYOUT, |
| | | redirect: '/feat/icon', |
| | | meta: { |
| | | icon: 'ic:outline-featured-play-list', |
| | | icon: 'ion:git-compare-outline', |
| | | title: t('routes.demo.feat.feat'), |
| | | }, |
| | | children: [ |
| | |
| | | component: LAYOUT, |
| | | redirect: '/frame/doc', |
| | | meta: { |
| | | icon: 'mdi:page-next-outline', |
| | | icon: 'ion:tv-outline', |
| | | title: t('routes.demo.iframe.frame'), |
| | | }, |
| | | |
| | |
| | | component: LAYOUT, |
| | | redirect: '/level/menu1/menu1-1/menu1-1-1', |
| | | meta: { |
| | | icon: 'carbon:user-role', |
| | | icon: 'ion:menu-outline', |
| | | title: t('routes.demo.level.level'), |
| | | }, |
| | | |
| | |
| | | component: LAYOUT, |
| | | redirect: '/page-demo/exception', |
| | | meta: { |
| | | icon: 'mdi:page-next-outline', |
| | | icon: 'ion:aperture-outline', |
| | | title: t('routes.demo.page.page'), |
| | | }, |
| | | children: [ |
| | |
| | | component: LAYOUT, |
| | | redirect: '/permission/front/page', |
| | | meta: { |
| | | icon: 'carbon:user-role', |
| | | icon: 'ion:key-outline', |
| | | title: t('routes.demo.permission.permission'), |
| | | }, |
| | | |
New file |
| | |
| | | import type { AppRouteModule } from '/@/router/types'; |
| | | |
| | | import { LAYOUT } from '/@/router/constant'; |
| | | import { t } from '/@/hooks/web/useI18n'; |
| | | |
| | | const system: AppRouteModule = { |
| | | path: '/system', |
| | | name: 'System', |
| | | component: LAYOUT, |
| | | redirect: '/system/account', |
| | | meta: { |
| | | icon: 'ion:settings-outline', |
| | | title: t('routes.demo.system.moduleName'), |
| | | }, |
| | | children: [ |
| | | { |
| | | path: 'account', |
| | | name: 'Account', |
| | | meta: { |
| | | title: t('routes.demo.system.account'), |
| | | }, |
| | | component: () => import('/@/views/demo/system/account/index.vue'), |
| | | }, |
| | | ], |
| | | }; |
| | | |
| | | export default system; |
| | |
| | | component: LAYOUT, |
| | | redirect: '/home/welcome', |
| | | meta: { |
| | | icon: 'bx:bx-home', |
| | | icon: 'ion:home-outline', |
| | | title: t('routes.dashboard.welcome'), |
| | | }, |
| | | children: [ |
New file |
| | |
| | | <template> |
| | | <BasicModal v-bind="$attrs" @register="registerModal" :title="getTitle" @ok="handleSubmit"> |
| | | <BasicForm @register="registerForm" /> |
| | | </BasicModal> |
| | | </template> |
| | | <script lang="ts"> |
| | | import { defineComponent, ref, computed, unref } from 'vue'; |
| | | import { BasicModal, useModalInner } from '/@/components/Modal'; |
| | | import { BasicForm, useForm } from '/@/components/Form/index'; |
| | | import { accountFormSchema } from './account.data'; |
| | | export default defineComponent({ |
| | | name: 'AccountModal', |
| | | components: { BasicModal, BasicForm }, |
| | | setup() { |
| | | const isUpdate = ref(true); |
| | | |
| | | const [registerForm, { setFieldsValue, validate }] = useForm({ |
| | | labelWidth: 100, |
| | | schemas: accountFormSchema, |
| | | showActionButtonGroup: false, |
| | | actionColOptions: { |
| | | span: 23, |
| | | }, |
| | | }); |
| | | |
| | | const [registerModal, { setModalProps }] = useModalInner((data) => { |
| | | isUpdate.value = !!data?.isUpdate; |
| | | |
| | | if (unref(isUpdate)) { |
| | | setFieldsValue({ |
| | | ...data.record, |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | const getTitle = computed(() => (!unref(isUpdate) ? '新增账号' : '编辑账号')); |
| | | |
| | | async function handleSubmit() { |
| | | try { |
| | | const values = await validate(); |
| | | setModalProps({ confirmLoading: true }); |
| | | // TODO custom api |
| | | console.log(values); |
| | | } finally { |
| | | setModalProps({ confirmLoading: true }); |
| | | } |
| | | } |
| | | |
| | | return { registerModal, registerForm, getTitle, handleSubmit }; |
| | | }, |
| | | }); |
| | | </script> |
New file |
| | |
| | | import { BasicColumn } from '/@/components/Table'; |
| | | import { FormSchema } from '/@/components/Table'; |
| | | |
| | | export const columns: BasicColumn[] = [ |
| | | { |
| | | title: 'ID', |
| | | dataIndex: 'id', |
| | | width: 80, |
| | | }, |
| | | { |
| | | title: '用户名', |
| | | dataIndex: 'account', |
| | | width: 120, |
| | | }, |
| | | { |
| | | title: '昵称', |
| | | dataIndex: 'nickname', |
| | | width: 120, |
| | | }, |
| | | { |
| | | title: '邮箱', |
| | | dataIndex: 'email', |
| | | width: 200, |
| | | }, |
| | | { |
| | | title: '更新时间', |
| | | dataIndex: 'updateTime', |
| | | width: 180, |
| | | }, |
| | | { |
| | | title: '角色', |
| | | dataIndex: 'role', |
| | | width: 200, |
| | | }, |
| | | { |
| | | title: '备注', |
| | | dataIndex: 'remark', |
| | | width: 200, |
| | | }, |
| | | ]; |
| | | |
| | | export const searchFormSchema: FormSchema[] = [ |
| | | { |
| | | field: 'account', |
| | | label: '用户名', |
| | | component: 'Input', |
| | | colProps: { span: 8 }, |
| | | }, |
| | | { |
| | | field: 'nickname', |
| | | label: '昵称', |
| | | component: 'Input', |
| | | colProps: { span: 8 }, |
| | | }, |
| | | ]; |
| | | |
| | | export const accountFormSchema: FormSchema[] = [ |
| | | { |
| | | field: 'account', |
| | | label: '用户名', |
| | | component: 'Input', |
| | | required: true, |
| | | }, |
| | | { |
| | | field: 'nickname', |
| | | label: '昵称', |
| | | component: 'Input', |
| | | required: true, |
| | | }, |
| | | { |
| | | label: '邮箱', |
| | | field: 'email', |
| | | component: 'Input', |
| | | required: true, |
| | | }, |
| | | // TODO |
| | | { |
| | | label: '角色', |
| | | field: 'role', |
| | | component: 'Input', |
| | | required: true, |
| | | }, |
| | | { |
| | | label: '备注', |
| | | field: 'remark', |
| | | component: 'InputTextArea', |
| | | }, |
| | | ]; |
New file |
| | |
| | | <template> |
| | | <div :class="[prefixCls]"> |
| | | <BasicTable @register="registerTable"> |
| | | <template #toolbar> |
| | | <a-button type="primary" @click="handleCreateAccount"> 新增账号 </a-button> |
| | | </template> |
| | | <template #action="{ record }"> |
| | | <TableAction |
| | | :actions="[ |
| | | { |
| | | label: '编辑', |
| | | onClick: handleEdit.bind(null, record), |
| | | }, |
| | | { |
| | | label: '删除', |
| | | color: 'error', |
| | | popConfirm: { |
| | | title: '是否确认删除', |
| | | confirm: handleDelete.bind(null, record), |
| | | }, |
| | | }, |
| | | ]" |
| | | /> |
| | | </template> |
| | | </BasicTable> |
| | | <AccountModal @register="registerModal" /> |
| | | </div> |
| | | </template> |
| | | <script lang="ts"> |
| | | import { defineComponent } from 'vue'; |
| | | |
| | | import { useDesign } from '/@/hooks/web/useDesign'; |
| | | import { BasicTable, useTable, TableAction } from '/@/components/Table'; |
| | | import { getAccountList } from '/@/api/demo/system'; |
| | | |
| | | import { useModal } from '/@/components/Modal'; |
| | | import AccountModal from './AccountModal.vue'; |
| | | |
| | | import { columns, searchFormSchema } from './account.data'; |
| | | |
| | | export default defineComponent({ |
| | | name: 'AccountManagement', |
| | | components: { BasicTable, AccountModal, TableAction }, |
| | | setup() { |
| | | const { prefixCls } = useDesign('account-management'); |
| | | |
| | | const [registerModal, { openModal }] = useModal(); |
| | | const [registerTable] = useTable({ |
| | | title: '账号列表', |
| | | api: getAccountList, |
| | | columns, |
| | | formConfig: { |
| | | labelWidth: 120, |
| | | schemas: searchFormSchema, |
| | | }, |
| | | useSearchForm: true, |
| | | showTableSetting: true, |
| | | actionColumn: { |
| | | width: 160, |
| | | title: '操作', |
| | | dataIndex: 'action', |
| | | slots: { customRender: 'action' }, |
| | | }, |
| | | }); |
| | | |
| | | function handleCreateAccount() { |
| | | openModal(true, { |
| | | isUpdate: false, |
| | | }); |
| | | } |
| | | |
| | | function handleEdit(record: Recordable) { |
| | | openModal(true, { |
| | | record, |
| | | isUpdate: true, |
| | | }); |
| | | } |
| | | |
| | | function handleDelete(record: Recordable) { |
| | | console.log(record); |
| | | } |
| | | |
| | | return { |
| | | prefixCls, |
| | | registerTable, |
| | | registerModal, |
| | | handleCreateAccount, |
| | | handleEdit, |
| | | handleDelete, |
| | | }; |
| | | }, |
| | | }); |
| | | </script> |
| | | <style lang="less" scoped> |
| | | @prefix-cls: ~'@{namespace}-account-management'; |
| | | |
| | | .@{prefix-cls} { |
| | | display: flex; |
| | | } |
| | | </style> |