|
|
@@ -0,0 +1,260 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import UserEdit from '@/components/UserEdit.vue';
|
|
|
+import UserPassword from '@/components/UserPassword.vue';
|
|
|
+import UserPreview from '@/components/UserPreview.vue';
|
|
|
+import { type UserModel, type UserQuery } from '@/model/system.model';
|
|
|
+
|
|
|
+import { branchMethod, deleteUserMethod, usersMethod } from '@/request/api/system.api';
|
|
|
+import { usePagination, useRequest } from 'alova/client';
|
|
|
+import { notification } from 'ant-design-vue';
|
|
|
+
|
|
|
+import {
|
|
|
+ VxeButton,
|
|
|
+ type VxeFormListeners,
|
|
|
+ type VxeFormProps,
|
|
|
+ type VxeGridInstance,
|
|
|
+ type VxeGridListeners,
|
|
|
+ type VxeGridProps,
|
|
|
+ VxeUI,
|
|
|
+} from 'vxe-pc-ui';
|
|
|
+
|
|
|
+
|
|
|
+const { data: branch, loading: branchLoading } = useRequest(branchMethod);
|
|
|
+
|
|
|
+const model = shallowRef<UserQuery>();
|
|
|
+const searchFormProps = reactive<VxeFormProps<UserQuery>>({
|
|
|
+ titleWidth: 100,
|
|
|
+ titleAlign: 'right',
|
|
|
+ titleColon: true,
|
|
|
+ data: {},
|
|
|
+ items: [
|
|
|
+ { field: 'userName', title: '系统账号', span: 6, itemRender: { name: 'VxeInput' } },
|
|
|
+ { field: 'nickName', title: '姓名', span: 6, itemRender: { name: 'VxeInput' } },
|
|
|
+ { field: '工号', title: '工号', span: 6, itemRender: { name: 'VxeInput' } },
|
|
|
+ { field: 'phonenumber', title: '手机号码', span: 6, itemRender: { name: 'VxeInput' } },
|
|
|
+ {
|
|
|
+ field: 'deptId', title: '医院 / 科室', span: 6, itemRender: {
|
|
|
+ name: 'VxeTreeSelect',
|
|
|
+ props: {
|
|
|
+ loading: computed(() => branchLoading.value),
|
|
|
+ options: computed(() => branch.value),
|
|
|
+ optionProps: { value: 'id' },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ span: 6, itemRender: {
|
|
|
+ name: 'VxeButtonGroup',
|
|
|
+ options: [
|
|
|
+ { type: 'submit', content: '查询', status: 'primary' },
|
|
|
+ { type: 'reset', content: '清空' },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+});
|
|
|
+const searchFormEmits: VxeFormListeners<UserQuery> = {
|
|
|
+ submit({ data }) { model.value = { ...data }; },
|
|
|
+ reset({ data }) { model.value = { ...data }; },
|
|
|
+};
|
|
|
+
|
|
|
+const gridRef = ref<VxeGridInstance<UserModel>>();
|
|
|
+const gridOptions = reactive<VxeGridProps<UserModel>>({
|
|
|
+ id: 'user-list',
|
|
|
+ border: true,
|
|
|
+ showOverflow: true,
|
|
|
+ height: 'auto',
|
|
|
+ scrollY: { enabled: true, gt: 0 },
|
|
|
+ toolbarConfig: {
|
|
|
+ custom: true,
|
|
|
+ zoom: true,
|
|
|
+ slots: {
|
|
|
+ buttons: 'handle',
|
|
|
+ tools: 'toolbar-extra',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ columnConfig: {
|
|
|
+ resizable: true,
|
|
|
+ },
|
|
|
+ customConfig: {
|
|
|
+ storage: true,
|
|
|
+ },
|
|
|
+ columns: [
|
|
|
+ { type: 'seq', width: 70, fixed: 'left' },
|
|
|
+ { field: 'userName', title: '系统账号', minWidth: 160 },
|
|
|
+ { field: 'nickName', title: '姓名', minWidth: 160 },
|
|
|
+ { field: 'dept.deptName', title: '医院 / 科室', minWidth: 160 },
|
|
|
+ { field: '工号', title: '工号', minWidth: 160 },
|
|
|
+ { field: 'phonenumber', title: '手机号码', minWidth: 160 },
|
|
|
+ {
|
|
|
+ field: 'roles', title: '角色', minWidth: 160, formatter: ({ cellValue, row }) => {
|
|
|
+ return row.roles?.join('/') ?? '';
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '操作',
|
|
|
+ width: 200,
|
|
|
+ cellRender: {
|
|
|
+ name: 'VxeButtonGroup',
|
|
|
+ props: {
|
|
|
+ mode: 'text',
|
|
|
+ },
|
|
|
+ options: [
|
|
|
+ { content: '修改', name: 'editUser' },
|
|
|
+ { content: '删除', status: 'error', name: 'deleteUser' },
|
|
|
+ ],
|
|
|
+ events: {
|
|
|
+ click({ row, rowIndex }, { name }) {
|
|
|
+ let method;
|
|
|
+ if ( name === 'editUser' ) { method = editUser; } else if ( name === 'deleteUser' ) { method = deleteUser; }
|
|
|
+ method?.(row, rowIndex);
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ params: {
|
|
|
+ cellClick: false,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ data: [],
|
|
|
+});
|
|
|
+const gridEvents: VxeGridListeners = {
|
|
|
+ cellClick: ({ row, rowIndex, column }) => {
|
|
|
+ if ( column.params?.cellClick === false ) return;
|
|
|
+ previewUser(row, rowIndex);
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+const { loading, page, pageSize, total, onSuccess, replace, refresh, remove } = usePagination(
|
|
|
+ (page, size) => usersMethod(page, size, model.value), {
|
|
|
+ initialData: { data: [], total: 0 },
|
|
|
+ initialPage: 1,
|
|
|
+ initialPageSize: 100,
|
|
|
+ watchingStates: [ model ],
|
|
|
+ immediate: false,
|
|
|
+ },
|
|
|
+);
|
|
|
+onSuccess(({ data: { data } }) => {
|
|
|
+ gridRef.value?.loadData(data);
|
|
|
+});
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ model.value = toRaw(searchFormProps.data);
|
|
|
+});
|
|
|
+
|
|
|
+function deleteUser(model: UserModel, index: number) {
|
|
|
+ const { userName } = model;
|
|
|
+ VxeUI.modal.confirm({
|
|
|
+ title: `删除用户`,
|
|
|
+ content: `确认要删除 ${ userName } 用户吗?`,
|
|
|
+ showClose: false,
|
|
|
+ onConfirm() {
|
|
|
+ deleteUserMethod(model).then(() => {
|
|
|
+ notification.success({
|
|
|
+ message: `删除用户: ${ userName }`,
|
|
|
+ description: '操作成功',
|
|
|
+ });
|
|
|
+ refresh(page.value);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function editUser(model?: UserModel, index?: number) {
|
|
|
+ VxeUI.modal.open({
|
|
|
+ title: model?.userId ? `修改用户` : `新增用户`,
|
|
|
+ escClosable: true,
|
|
|
+ destroyOnClose: true,
|
|
|
+ id: `user-edit-modal`,
|
|
|
+ remember: true,
|
|
|
+ storage: true,
|
|
|
+ slots: {
|
|
|
+ default() {
|
|
|
+ return h(UserEdit, <any> {
|
|
|
+ data: model, onSubmit(data?: UserModel) {
|
|
|
+ refresh(page.value);
|
|
|
+ VxeUI.modal.close(`user-edit-modal`);
|
|
|
+ },
|
|
|
+ });
|
|
|
+ },
|
|
|
+ },
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function previewUser(model: UserModel, index?: number) {
|
|
|
+ VxeUI.drawer.open({
|
|
|
+ title: `用户信息`,
|
|
|
+ maskClosable: true,
|
|
|
+ escClosable: true,
|
|
|
+ slots: {
|
|
|
+ default() {
|
|
|
+ return h(UserPreview, <any> { data: model });
|
|
|
+ },
|
|
|
+ corner() {
|
|
|
+ return h(VxeButton, {
|
|
|
+ content: '修改登录密码', size: 'mini', onClick() {
|
|
|
+ updateUserPassword(model, index);
|
|
|
+ },
|
|
|
+ });
|
|
|
+ },
|
|
|
+ },
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function updateUserPassword(model: UserModel, index?: number) {
|
|
|
+ const { userName } = model;
|
|
|
+ VxeUI.modal.open({
|
|
|
+ title: `重置 ${ userName } 登录密码`,
|
|
|
+ escClosable: true,
|
|
|
+ destroyOnClose: true,
|
|
|
+ id: `user-edit-password-modal`,
|
|
|
+ remember: true,
|
|
|
+ storage: true,
|
|
|
+ mask: false,
|
|
|
+ slots: {
|
|
|
+ default() {
|
|
|
+ return h(UserPassword, <any> {
|
|
|
+ data: model, onSubmit(data?: UserModel) {
|
|
|
+ notification.success({
|
|
|
+ message: `重置用户: ${ userName } 的登录密码`,
|
|
|
+ description: '操作成功',
|
|
|
+ });
|
|
|
+ VxeUI.modal.close(`user-edit-password-modal`);
|
|
|
+ },
|
|
|
+ });
|
|
|
+ },
|
|
|
+ },
|
|
|
+ });
|
|
|
+}
|
|
|
+</script>
|
|
|
+<template>
|
|
|
+ <div class="page-container flex flex-col">
|
|
|
+ <header class="flex-none">
|
|
|
+ <vxe-form v-bind="searchFormProps" v-on="searchFormEmits" />
|
|
|
+ </header>
|
|
|
+ <main class="flex-auto overflow-hidden">
|
|
|
+ <vxe-grid ref="gridRef" v-bind="gridOptions" v-on="gridEvents" :loading="loading">
|
|
|
+ <template #handle>
|
|
|
+ <vxe-button status="primary" @click="editUser()">新增</vxe-button>
|
|
|
+ </template>
|
|
|
+ <template #toolbar-extra>
|
|
|
+ <vxe-button style="margin-right: 12px;" icon="vxe-icon-repeat" circle @click="refresh(page)"></vxe-button>
|
|
|
+ </template>
|
|
|
+ </vxe-grid>
|
|
|
+ </main>
|
|
|
+ <footer class="flex-none">
|
|
|
+ <vxe-pager
|
|
|
+ v-model:current-page="page"
|
|
|
+ v-model:page-size="pageSize"
|
|
|
+ :total="total"
|
|
|
+ :layouts="['Home', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'End', 'Sizes', 'FullJump', 'Total']"
|
|
|
+ />
|
|
|
+ </footer>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<style scoped lang="scss">
|
|
|
+.page-container {
|
|
|
+ padding: 0 24px;
|
|
|
+ max-height: var(--page-main-container);
|
|
|
+}
|
|
|
+</style>
|