feat: 合并Gin_Vue

This commit is contained in:
TsMask
2023-10-16 17:12:24 +08:00
parent 771320a839
commit 743568861d
77 changed files with 734 additions and 1870 deletions

View File

@@ -1,185 +0,0 @@
<script setup lang="ts">
import { reactive } from 'vue';
import { message } from 'ant-design-vue/lib';
import { FileType } from 'ant-design-vue/lib/upload/interface';
import { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface';
import { ResultType } from '@/plugins/http-fetch';
const emit = defineEmits(['close', 'update:visible']);
const props = defineProps({
/**窗口标题 */
title: {
type: String,
default: '标题',
},
/**是否弹出显示,必传 */
visible: {
type: Boolean,
required: true,
},
/**文件上传函数方法,必传 */
uploadFileMethod: {
type: Function,
required: true,
},
/**下载模板函数方法 */
downloadTemplateMethod: {
type: Function,
default: undefined,
},
/**显示更新已存在数据勾选项 */
showUpdateSupport: {
type: Boolean,
default: false,
},
/**允许上传的文件拓展类型,默认 xls、xlsx */
fileExt: {
type: Array<string>,
default: ['xls', 'xlsx'],
},
/**上传文件大小单位MB默认 10 */
fileSize: {
type: Number,
default: 10,
},
});
/**上传状态 */
let updateState = reactive({
/**是否更新已经存在的数据 */
updateSupport: false,
/**是否上传中 */
loading: false,
/**是否已上传文件 */
isUpload: false,
/**上传结果信息 */
msg: '',
});
/**重置上传状态 */
function fnResetUpdateState() {
updateState = Object.assign(updateState, {
updateSupport: false,
loading: false,
isUpload: false,
msg: '',
});
}
/**上传前检查或转换压缩 */
function fnBeforeUpload(file: FileType) {
if (updateState.loading) return false;
const isAllowType = props.fileExt.some(v => file.name.endsWith(v));
if (!isAllowType) {
message.error(`只支持上传文件格式 ${props.fileExt.join('、')}`, 3);
}
const isLtM = file.size / 1024 / 1024 < props.fileSize;
if (!isLtM) {
message.error(`上传文件大小必须小于 ${props.fileSize}MB`, 3);
}
return isAllowType && isLtM;
}
/**上传请求发出 */
function fnUpload(up: UploadRequestOption) {
if (typeof props.uploadFileMethod !== 'function') return;
const hide = message.loading('正在上传并解析数据...', 0);
updateState.loading = true;
let formData = new FormData();
formData.append('file', up.file);
formData.append('updateSupport', `${updateState.updateSupport}`);
props
.uploadFileMethod(formData)
.then((res: ResultType) => {
updateState.loading = false;
updateState.isUpload = true;
updateState.msg = res.msg?.replaceAll(/<br\/>+/g, '\r');
})
.catch((err: { code: number; msg: string }) => {
message.error(`上传失败 ${err.msg}`);
})
.finally(() => {
hide();
});
}
/**弹框确认按钮事件 */
function fnModalOk() {
emit('update:visible', false);
emit('close', updateState.isUpload);
fnResetUpdateState();
}
/**弹框取消按钮事件 */
function fnModalCancel() {
emit('update:visible', false);
emit('close', updateState.isUpload);
fnResetUpdateState();
}
</script>
<template>
<a-modal
width="500px"
:title="props.title"
:visible="props.visible"
:keyboard="false"
:mask-closable="false"
@ok="fnModalOk"
@cancel="fnModalCancel"
>
<a-space :size="8" direction="vertical" style="width: 100%">
<a-upload-dragger
:disabled="updateState.loading"
name="file"
:max-count="1"
:show-upload-list="false"
:before-upload="fnBeforeUpload"
:custom-request="fnUpload"
>
<p class="ant-upload-drag-icon">
<inbox-outlined></inbox-outlined>
</p>
<p class="ant-upload-text">点击选择或将文件拖入边框区域进行上传</p>
<p class="ant-upload-hint">
仅允许导入
{{ props.fileExt.join('、') }}
格式文件上传文件大小
{{ props.fileSize }}
MB
</p>
</a-upload-dragger>
<a-row :gutter="18" justify="space-between" align="middle">
<a-col :span="12">
<a-checkbox
v-model:checked="updateState.updateSupport"
v-if="showUpdateSupport"
>
是否更新已经存在的数据
</a-checkbox>
</a-col>
<a-col :span="6">
<a-button
type="link"
title="下载模板"
@click="downloadTemplateMethod()"
v-if="downloadTemplateMethod"
>
下载模板
</a-button>
</a-col>
</a-row>
<a-textarea
:disabled="true"
:hidden="updateState.msg.length < 1"
:value="updateState.msg"
:auto-size="{ minRows: 2, maxRows: 8 }"
/>
</a-space>
</a-modal>
</template>
<style lang="less" scoped>
.table :deep(.ant-pagination) {
padding: 0 24px;
}
</style>

View File

@@ -6,7 +6,7 @@ import { message, Modal, Form } from 'ant-design-vue/lib';
import { SizeType } from 'ant-design-vue/lib/config-provider';
import { MenuInfo } from 'ant-design-vue/lib/menu/src/interface';
import { ColumnsType } from 'ant-design-vue/lib/table';
import UploadXlsxImport from './components/UploadXlsxImport.vue';
import UploadModal from '@/components/UploadModal/index.vue';
import {
importData,
importTemplate,
@@ -32,7 +32,6 @@ import {
import useDictStore from '@/store/modules/dict';
import useUserStore from '@/store/modules/user';
import { DataNode } from 'ant-design-vue/lib/tree';
import { hasPermissions } from '@/plugins/auth-user';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
const { getDict } = useDictStore();
const route = useRoute();
@@ -60,6 +59,8 @@ let queryParams = reactive({
userName: '',
/**手机号 */
phonenumber: '',
/**部门ID */
deptId: '',
/**用户状态 */
status: undefined,
/**记录开始时间 */
@@ -77,6 +78,7 @@ function fnQueryReset() {
queryParams = Object.assign(queryParams, {
userName: '',
phonenumber: '',
deptId: '',
status: undefined,
beginTime: '',
endTime: '',
@@ -119,37 +121,43 @@ let tableState: TabeStateType = reactive({
let tableColumns: ColumnsType = [
{
title: '用户编号',
dataIndex: 'id',
dataIndex: 'userId',
align: 'center',
},
{
title: '登录账号',
dataIndex: 'accountId',
dataIndex: 'userName',
align: 'center',
},
{
title: '用户',
dataIndex: 'name',
title: '用户昵称',
dataIndex: 'nickName',
align: 'center',
},
{
title: '手机号码',
dataIndex: 'phone',
dataIndex: 'phonenumber',
align: 'center',
},
{
title: '用户类型',
dataIndex: 'groupName',
key: 'groupName',
title: '部门名称',
dataIndex: 'deptId',
key: 'deptId',
align: 'center',
},
{
title: '创建时间',
dataIndex: 'createTime',
title: '登录地址',
dataIndex: 'loginIp',
key: 'loginIp',
align: 'center',
},
{
title: '登录时间',
dataIndex: 'loginDate',
align: 'center',
customRender(opt) {
if (!opt.value) return '';
return parseDateToStr(opt.value);
if (+opt.value <= 0) return '';
return parseDateToStr(+opt.value);
},
},
{
@@ -160,7 +168,7 @@ let tableColumns: ColumnsType = [
},
{
title: '操作',
key: 'id',
key: 'userId',
align: 'center',
},
];
@@ -209,12 +217,15 @@ function fnTableSelectedRowKeys(keys: (string | number)[]) {
}
type OptionsType = {
/**岗位选择列表 */
posts: Record<string, any>[];
/**角色选择列表 */
roles: Record<string, any>[];
};
/**初始用户选择列表 */
let options: OptionsType = {
posts: [],
roles: [],
};
@@ -261,6 +272,7 @@ let modalState: ModalStateType = reactive({
},
confirmLoading: false,
options: {
posts: [],
roles: [],
},
});
@@ -328,7 +340,13 @@ function fnModalVisibleByVive(userId: string | number) {
Reflect.set(m, 'disabled', disabled);
return m;
});
const posts = res.data.posts.map((m: Record<string, any>) => {
const disabled = m.status === '0';
Reflect.set(m, 'disabled', disabled);
return m;
});
modalState.options.roles = roles;
modalState.options.posts = posts;
const { user, roleIds, postIds } = res.data;
modalState.from = Object.assign(modalState.from, user);
modalState.from.roleIds = roleIds;
@@ -352,6 +370,7 @@ function fnModalVisibleByEdit(userId?: string | number) {
modalStateFrom.resetFields();
if (options.roles.length > 0) {
modalState.options.roles = options.roles;
modalState.options.posts = options.posts;
modalState.title = '添加用户信息';
modalState.visibleByEdit = true;
} else {
@@ -368,8 +387,15 @@ function fnModalVisibleByEdit(userId?: string | number) {
Reflect.set(m, 'disabled', disabled);
return m;
});
const posts = res.data.posts.map((m: Record<string, any>) => {
const disabled = m.status === '0';
Reflect.set(m, 'disabled', disabled);
return m;
});
options.roles = roles;
options.posts = posts;
modalState.options.roles = roles;
modalState.options.posts = posts;
const { user, roleIds, postIds } = res.data;
modalState.from = Object.assign(modalState.from, user);
modalState.from.roleIds = roleIds;
@@ -394,7 +420,13 @@ function fnModalVisibleByEdit(userId?: string | number) {
Reflect.set(m, 'disabled', disabled);
return m;
});
const posts = res.data.posts.map((m: Record<string, any>) => {
const disabled = m.status === '0';
Reflect.set(m, 'disabled', disabled);
return m;
});
modalState.options.roles = roles;
modalState.options.posts = posts;
const { user, roleIds, postIds } = res.data;
modalState.from = Object.assign(modalState.from, user);
modalState.from.roleIds = roleIds;
@@ -463,6 +495,7 @@ function fnModalCancel() {
modalState.visibleByResetPwd = false;
modalStateFrom.resetFields();
modalState.options.roles = [];
modalState.options.posts = [];
}
/**
@@ -613,41 +646,67 @@ function fnExportList() {
}
/**对话框表格信息导入对象信息状态类型 */
type ModalUploadXlsxImportStateType = {
type ModalUploadImportStateType = {
/**是否显示 */
visible: boolean;
/**标题 */
title: string;
/**是否上传中 */
loading: boolean;
/**是否更新已经存在的数据 */
updateSupport: boolean;
/**上传结果信息 */
msg: string;
/**导入模板下载触发 */
templateDownload: boolean;
};
/**对话框表格信息导入对象信息状态 */
let modalUploadXlsxImportState: ModalUploadXlsxImportStateType = reactive({
let uploadImportState: ModalUploadImportStateType = reactive({
visible: false,
title: '用户导入',
loading: false,
updateSupport: false,
msg: '',
templateDownload: false,
});
/**
* 对话框表格信息导入确认执行函数
* @param isUpload 是否已上传文件
*/
function fnModalUploadXlsxImportClose(isUpload: boolean) {
if (isUpload) {
fnGetList();
}
}
/**对话框表格信息导入弹出窗口 */
function fnModalUploadXlsxImportOpen() {
modalUploadXlsxImportState.visible = true;
function fnModalUploadImportOpen() {
uploadImportState.updateSupport = false;
uploadImportState.msg = '';
uploadImportState.visible = true;
}
/**列表导入模板 */
function fnModalUploadXlsxImportExportTemplate() {
if (modalUploadXlsxImportState.templateDownload) return;
modalUploadXlsxImportState.templateDownload = true;
/**对话框表格信息导入关闭窗口 */
function fnModalUploadImportClose() {
uploadImportState.visible = false;
}
/**对话框表格信息导入上传 */
function fnModalUploadImportUpload(file: File) {
const hide = message.loading('正在上传并解析数据...', 0);
uploadImportState.loading = true;
let formData = new FormData();
formData.append('file', file);
formData.append('updateSupport', `${uploadImportState.updateSupport}`);
importData(formData)
.then(res => {
uploadImportState.msg = res.msg?.replaceAll(/<br\/>+/g, '\r');
})
.catch((err: { code: number; msg: string }) => {
message.error(`上传失败 ${err.msg}`);
})
.finally(() => {
hide();
uploadImportState.loading = false;
});
}
/**对话框表格信息导入模板 */
function fnModalUploadImportExportTemplate() {
if (uploadImportState.templateDownload) return;
uploadImportState.templateDownload = true;
const hide = message.loading('正在下载...', 0);
importTemplate()
.then(res => {
@@ -666,7 +725,7 @@ function fnModalUploadXlsxImportExportTemplate() {
})
.finally(() => {
hide();
modalUploadXlsxImportState.templateDownload = false;
uploadImportState.templateDownload = false;
});
}
@@ -739,25 +798,25 @@ onMounted(() => {
<!-- 表格搜索栏 -->
<a-form :model="queryParams" name="queryParams" layout="horizontal">
<a-row :gutter="16">
<a-col :lg="6" :md="12" :xs="24">
<a-form-item label="登录账号" name="userName">
<a-input
v-model:value="queryParams.userName"
allow-clear
:maxlength="30"
placeholder="请输入登录账号"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="4" :md="12" :xs="24">
<a-form-item label="用户状态" name="status">
<a-select
v-model:value="queryParams.status"
allow-clear
placeholder="请选择"
:options="dict.sysNormalDisable"
<a-col :lg="18" :md="12" :xs="24">
<a-form-item label="部门名称" name="deptId">
<a-tree-select
v-model:value="queryParams.deptId"
placeholder="部门名称"
show-search
tree-default-expand-all
:tree-data="deptTreeData"
:field-names="{
children: 'children',
label: 'label',
value: 'id',
}"
tree-node-label-prop="label"
tree-node-filter-prop="label"
style="width: 100%"
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
>
</a-select>
</a-tree-select>
</a-form-item>
</a-col>
<a-col :lg="6" :md="12" :xs="24">
@@ -775,6 +834,51 @@ onMounted(() => {
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :lg="6" :md="12" :xs="24">
<a-form-item label="登录账号" name="userName">
<a-input
v-model:value="queryParams.userName"
allow-clear
:maxlength="30"
placeholder="请输入登录账号"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="6" :md="12" :xs="24">
<a-form-item label="手机号码" name="phonenumber">
<a-input
v-model:value="queryParams.phonenumber"
allow-clear
:maxlength="11"
placeholder="请输入手机号码"
></a-input>
</a-form-item>
</a-col>
<a-col :lg="4" :md="12" :xs="24">
<a-form-item label="用户状态" name="status">
<a-select
v-model:value="queryParams.status"
allow-clear
placeholder="请选择"
:options="dict.sysNormalDisable"
>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="8" :md="12" :xs="24">
<a-form-item label="登录时间" name="queryRangePicker">
<a-range-picker
v-model:value="queryRangePicker"
allow-clear
bordered
value-format="YYYY-MM-DD"
:placeholder="['登录开始', '登录结束']"
style="width: 100%"
></a-range-picker>
</a-form-item>
</a-col>
</a-row>
</a-form>
</a-card>
@@ -800,9 +904,9 @@ onMounted(() => {
<template #icon><DeleteOutlined /></template>
删除
</a-button>
<!-- <a-button
<a-button
type="dashed"
@click.prevent="fnModalUploadXlsxImportOpen()"
@click.prevent="fnModalUploadImportOpen()"
v-perms:has="['system:user:import']"
>
<template #icon><ImportOutlined /></template>
@@ -815,7 +919,7 @@ onMounted(() => {
>
<template #icon><ExportOutlined /></template>
导出
</a-button> -->
</a-button>
</a-space>
</template>
@@ -846,9 +950,9 @@ onMounted(() => {
<template #icon><ReloadOutlined /></template>
</a-button>
</a-tooltip>
<a-tooltip>
<a-tooltip placement="topRight">
<template #title>密度</template>
<a-dropdown trigger="click">
<a-dropdown placement="bottomRight" trigger="click">
<a-button type="text">
<template #icon><ColumnHeightOutlined /></template>
</a-button>
@@ -870,7 +974,7 @@ onMounted(() => {
<!-- 表格列表 -->
<a-table
class="table"
row-key="id"
row-key="userId"
:columns="tableColumns"
:loading="tableState.loading"
:data-source="tableState.data"
@@ -885,10 +989,10 @@ onMounted(() => {
}"
>
<template #bodyCell="{ column, record }">
<!-- <template v-if="column.key === 'deptId'">
<template v-if="column.key === 'deptId'">
{{ record.dept?.deptName }}
</template> -->
<!-- <template v-if="column.key === 'status'">
</template>
<template v-if="column.key === 'status'">
<a-switch
v-if="record.userId !== '1'"
v-perms:has="['system:user:edit']"
@@ -905,14 +1009,14 @@ onMounted(() => {
:options="dict.sysNormalDisable"
:value="record.status"
/>
</template> -->
<template v-if="column.key === 'id'">
<a-space :size="8" align="center" v-if="record.id !== '1'">
</template>
<template v-if="column.key === 'userId'">
<a-space :size="8" align="center" v-if="record.userId !== '1'">
<a-tooltip>
<template #title>查看详情</template>
<a-button
type="link"
@click.prevent="fnModalVisibleByVive(record.id)"
@click.prevent="fnModalVisibleByVive(record.userId)"
v-perms:has="['system:user:query']"
>
<template #icon><ProfileOutlined /></template>
@@ -922,7 +1026,7 @@ onMounted(() => {
<template #title>编辑</template>
<a-button
type="link"
@click.prevent="fnModalVisibleByEdit(record.id)"
@click.prevent="fnModalVisibleByEdit(record.userId)"
v-perms:has="['system:user:edit']"
>
<template #icon><FormOutlined /></template>
@@ -932,13 +1036,13 @@ onMounted(() => {
<template #title>删除</template>
<a-button
type="link"
@click.prevent="fnRecordDelete(record.id)"
@click.prevent="fnRecordDelete(record.userId)"
v-perms:has="['system:user:remove']"
>
<template #icon><DeleteOutlined /></template>
</a-button>
</a-tooltip>
<!-- <a-tooltip>
<a-tooltip>
<template #title>重置密码</template>
<a-button
type="link"
@@ -947,7 +1051,7 @@ onMounted(() => {
>
<template #icon><SecurityScanOutlined /></template>
</a-button>
</a-tooltip> -->
</a-tooltip>
</a-space>
</template>
</template>
@@ -1064,7 +1168,21 @@ onMounted(() => {
</a-form-item>
<a-row :gutter="16">
<a-col :lg="24" :md="24" :xs="24">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="用户岗位" name="postIds">
<a-select
:value="modalState.from.postIds"
disabled
mode="multiple"
placeholder="请选择用户岗位"
option-label-prop="postName"
:options="modalState.options.posts"
:field-names="{ label: 'postName', value: 'postId' }"
>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="用户角色" name="roleIds">
<a-select
:value="modalState.from.roleIds"
@@ -1230,7 +1348,23 @@ onMounted(() => {
</a-form-item>
<a-row :gutter="16">
<a-col :lg="24" :md="24" :xs="24">
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="用户岗位" name="postIds">
<a-select
v-model:value="modalState.from.postIds"
allow-clear
mode="multiple"
placeholder="请选择用户岗位"
show-search
option-filter-prop="postName"
option-label-prop="postName"
:options="modalState.options.posts"
:field-names="{ label: 'postName', value: 'postId' }"
>
</a-select>
</a-form-item>
</a-col>
<a-col :lg="12" :md="12" :xs="24">
<a-form-item label="用户角色" name="roleIds">
<a-select
v-model:value="modalState.from.roleIds"
@@ -1307,14 +1441,40 @@ onMounted(() => {
</a-modal>
<!-- 上传导入表格数据文件框 -->
<!-- <UploadXlsxImport
:title="modalUploadXlsxImportState.title"
v-model:visible="modalUploadXlsxImportState.visible"
:show-update-support="true"
:upload-file-method="importData"
:download-template-method="fnModalUploadXlsxImportExportTemplate"
@close="fnModalUploadXlsxImportClose"
/> -->
<UploadModal
:title="uploadImportState.title"
:loading="uploadImportState.loading"
@upload="fnModalUploadImportUpload"
@close="fnModalUploadImportClose"
v-model:visible="uploadImportState.visible"
:ext="['.xls', '.xlsx']"
:size="10"
>
<template #default>
<a-row :gutter="18" justify="space-between" align="middle">
<a-col :span="12">
<a-checkbox v-model:checked="uploadImportState.updateSupport">
是否更新已经存在的数据
</a-checkbox>
</a-col>
<a-col :span="6">
<a-button
type="link"
title="下载模板"
@click.prevent="fnModalUploadImportExportTemplate"
>
下载模板
</a-button>
</a-col>
</a-row>
<a-textarea
:disabled="true"
:hidden="!uploadImportState.msg"
:value="uploadImportState.msg"
:auto-size="{ minRows: 2, maxRows: 8 }"
/>
</template>
</UploadModal>
</PageContainer>
</template>