19 changed files with 1205 additions and 87 deletions
@ -0,0 +1,15 @@ |
|||
import { request } from '@/utils/request'; |
|||
|
|||
/** |
|||
* @description 附件上传 |
|||
* @param {} data |
|||
* @returns |
|||
*/ |
|||
export function commonUpload(data) { |
|||
return request({ |
|||
url: `/file/upload`, |
|||
method: 'post', |
|||
data, |
|||
timeout: 30000, |
|||
}); |
|||
} |
@ -0,0 +1,3 @@ |
|||
declare namespace API { |
|||
|
|||
} |
@ -0,0 +1,25 @@ |
|||
export function downloadByData(data: BlobPart, filename: string, mime?: string, bom?: BlobPart) { |
|||
const blobData = typeof bom !== 'undefined' ? [bom, data] : [data]; |
|||
const blob = new Blob(blobData, { type: mime || 'application/vnd.ms-excel' }); |
|||
|
|||
const blobURL = window.URL.createObjectURL(blob); |
|||
const tempLink = document.createElement('a'); |
|||
tempLink.style.display = 'none'; |
|||
tempLink.href = blobURL; |
|||
tempLink.setAttribute('download', filename); |
|||
if (typeof tempLink.download === 'undefined') { |
|||
tempLink.setAttribute('target', '_blank'); |
|||
} |
|||
document.body.appendChild(tempLink); |
|||
tempLink.click(); |
|||
document.body.removeChild(tempLink); |
|||
window.URL.revokeObjectURL(blobURL); |
|||
} |
|||
|
|||
export function getFileExtension(filename: string): string | null { |
|||
const dotIndex = filename.lastIndexOf('.'); |
|||
if (dotIndex === -1) { |
|||
return null; // 文件名中不存在扩展名
|
|||
} |
|||
return filename.slice(dotIndex + 1).toLowerCase(); |
|||
} |
@ -1,14 +1,32 @@ |
|||
export const sexTypeList:any = [ |
|||
export const stateTypeList: any = [ |
|||
// Init(0,"初始化"),
|
|||
// Back(1,"退回"),
|
|||
// Develop(2,"开发"),
|
|||
// Test(3,"测试"),
|
|||
// End(4,"结束"),
|
|||
{ |
|||
label: '男', |
|||
label: '初始化', |
|||
value: 0, |
|||
color: '#f50', |
|||
}, |
|||
{ |
|||
label: '退回', |
|||
value: 1, |
|||
color: '#2db7f5', |
|||
}, |
|||
{ |
|||
label: '女', |
|||
label: '开发', |
|||
value: 2, |
|||
color: '#87d068', |
|||
}, |
|||
{ |
|||
label: '未知', |
|||
label: '测试', |
|||
value: 3, |
|||
color: '#108ee9', |
|||
}, |
|||
{ |
|||
label: '结束', |
|||
value: 4, |
|||
color: '#f50', |
|||
}, |
|||
]; |
|||
|
@ -1,21 +0,0 @@ |
|||
import type { FormSchema } from '@/components/core/schema-form/'; |
|||
|
|||
export const issueSchemas: FormSchema<API.CreateIssueParams>[] = [ |
|||
{ |
|||
field: 'title', |
|||
component: 'Input', |
|||
label: '账号', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
rules: [{ required: true }], |
|||
}, |
|||
{ |
|||
field: 'content', |
|||
label: '内容', |
|||
slot: 'content', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
}, |
|||
]; |
@ -0,0 +1,171 @@ |
|||
import type { FormSchema } from '@/components/core/schema-form/'; |
|||
import { TableListItem } from './columns'; |
|||
import { commonUpload } from '@/api/upload'; |
|||
import { message, Button } from 'ant-design-vue'; |
|||
import { getFileExtension } from '@/utils/fileUtils'; |
|||
import { UploadOutlined } from '@ant-design/icons-vue'; |
|||
import { stateTypeList } from './data'; |
|||
import { url } from 'inspector'; |
|||
import component from '@/locales/lang/en-US/component'; |
|||
// 编辑页字段
|
|||
export const getEditFormSchema: ( |
|||
row?: Partial<TableListItem>, |
|||
isDetail?: boolean, |
|||
) => FormSchema[] = (record = {}, isDetail = false) => { |
|||
return [ |
|||
{ |
|||
field: 'title', |
|||
component: 'Input', |
|||
label: '问题标题', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
rules: [{ required: true }], |
|||
}, |
|||
|
|||
{ |
|||
field: 'billcode', |
|||
component: 'Input', |
|||
label: '问题号', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
}, |
|||
{ |
|||
field: 'customer', |
|||
component: 'Input', |
|||
label: '客户', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
}, |
|||
{ |
|||
field: 'product', |
|||
component: 'Input', |
|||
label: '产品', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
}, |
|||
{ |
|||
field: 'agent', |
|||
component: 'Input', |
|||
label: '代理商', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
}, |
|||
{ |
|||
field: 'attribute', |
|||
component: 'Input', |
|||
label: '问题属性', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
}, |
|||
{ |
|||
field: 'serviceNumber', |
|||
component: 'Input', |
|||
label: '服务号', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
}, |
|||
{ |
|||
field: 'contacts', |
|||
component: 'Input', |
|||
label: '联系人', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
}, |
|||
{ |
|||
field: 'contactsEmail', |
|||
component: 'Input', |
|||
label: '联系人邮箱', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
}, |
|||
{ |
|||
field: 'contactsMobile', |
|||
component: 'Input', |
|||
label: '联系人手机号', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
}, |
|||
{ |
|||
field: 'state', |
|||
component: 'Select', |
|||
label: '状态', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
componentProps: { |
|||
options: stateTypeList, |
|||
}, |
|||
rules: [{ required: true, type: 'number' }], |
|||
}, |
|||
{ |
|||
field: 'description', |
|||
component: 'InputTextArea', |
|||
componentProps: { |
|||
rows: 4, |
|||
placeholder: '请输入问题描述', |
|||
}, |
|||
label: '问题描述', |
|||
colProps: { |
|||
span: 24, |
|||
}, |
|||
rules: [{ required: true }], |
|||
}, |
|||
{ |
|||
label: '描述附件', |
|||
field: 'fileList', |
|||
component: 'Upload', |
|||
componentProps: { |
|||
disabled: isDetail, |
|||
customRequest: async (data) => { |
|||
console.log('data: ', data); |
|||
const formData = new FormData(); |
|||
formData.append('file', data.file); |
|||
const res = await commonUpload(formData); |
|||
console.log('res: ', res); |
|||
data?.onSuccess && data?.onSuccess(res, data.file as any); |
|||
}, |
|||
beforeUpload: (file) => { |
|||
console.log('file: ', file); |
|||
|
|||
// 限制允许上传的文件类型
|
|||
const allowedTypes = ['xlsx', 'xls', 'doc', 'docx', 'pdf']; |
|||
|
|||
// 检查文件类型
|
|||
const fileType = getFileExtension(file.name) || 'unknown'; |
|||
if (!allowedTypes.includes(fileType)) { |
|||
// 文件类型不在允许列表中,拒绝上传
|
|||
// 可以在这里展示错误信息
|
|||
message.warning('文件类型不正确'); |
|||
return false; |
|||
} |
|||
|
|||
// 其他验证逻辑...
|
|||
|
|||
// 允许上传
|
|||
return true; |
|||
}, |
|||
}, |
|||
componentSlots: { |
|||
default: () => ( |
|||
<Button> |
|||
<UploadOutlined /> 点击上传 |
|||
</Button> |
|||
), |
|||
}, |
|||
colProps: { |
|||
span: 24, |
|||
}, |
|||
rules: [{ required: false }], |
|||
}, |
|||
] as any; |
|||
}; |
@ -0,0 +1,363 @@ |
|||
import { debounce } from 'lodash-es'; |
|||
import type { TableColumn } from '@/components/core/dynamic-table'; |
|||
import { formatToDateTime } from '@/utils/dateUtil'; |
|||
import { updateUser } from '@/api/user'; |
|||
import { h } from 'vue'; |
|||
import { Switch } from 'ant-design-vue'; |
|||
import { sexTypeList } from './data'; |
|||
export type TableListItem = API.UserInfoType; |
|||
export type TableColumnItem = TableColumn<TableListItem>; |
|||
// 数据项类型
|
|||
// export type ListItemType = typeof tableData[number];
|
|||
// 使用TableColumn<ListItemType> 将会限制dataIndex的类型,但换来的是dataIndex有类型提示
|
|||
export const baseColumns: TableColumnItem[] = [ |
|||
{ |
|||
title: '账号', |
|||
align: 'center', |
|||
dataIndex: 'account', |
|||
// sorter: true,
|
|||
width: 150, |
|||
resizable: true, |
|||
formItemProps: { |
|||
defaultValue: '', |
|||
required: false, |
|||
}, |
|||
}, |
|||
{ |
|||
title: '姓名', |
|||
align: 'center', |
|||
dataIndex: 'username', |
|||
width: 150, |
|||
resizable: true, |
|||
formItemProps: { |
|||
defaultValue: '', |
|||
required: false, |
|||
}, |
|||
}, |
|||
{ |
|||
title: '手机号码', |
|||
align: 'center', |
|||
dataIndex: 'mobile', |
|||
width: 150, |
|||
formItemProps: { |
|||
defaultValue: '', |
|||
required: false, |
|||
}, |
|||
}, |
|||
|
|||
{ |
|||
title: '性别', |
|||
align: 'center', |
|||
dataIndex: 'sex', |
|||
width: 100, |
|||
hideInSearch: true, |
|||
formItemProps: { |
|||
defaultValue: '', |
|||
required: false, |
|||
component: 'Select', |
|||
label: '性别', |
|||
componentProps: { |
|||
mode: 'single', |
|||
request: async () => { |
|||
// const data = await getSexList();
|
|||
return sexTypeList; |
|||
}, |
|||
}, |
|||
}, |
|||
customRender: ({ record }) => { |
|||
const text = sexTypeList.find((e) => e.value === record.sex)?.label; |
|||
return <div>{text}</div>; |
|||
}, |
|||
}, |
|||
{ |
|||
title: '帐号状态', |
|||
align: 'center', |
|||
width: 100, |
|||
dataIndex: 'state', |
|||
hideInSearch: true, |
|||
formItemProps: { |
|||
component: 'Select', |
|||
componentProps: { |
|||
options: [ |
|||
{ |
|||
label: '启用', |
|||
value: 1, |
|||
}, |
|||
{ |
|||
label: '禁用', |
|||
value: 0, |
|||
}, |
|||
], |
|||
}, |
|||
}, |
|||
customRender: ({ record }) => { |
|||
const onChange = (checked: boolean) => { |
|||
console.log('checked: ', checked); |
|||
record.pendingStatus = true; |
|||
const newState = checked ? 1 : 0; |
|||
record.state = newState; |
|||
updateUser(record) |
|||
.then(() => { |
|||
record.state = newState; |
|||
}) |
|||
.catch(() => {}) |
|||
.finally(() => { |
|||
record.pendingStatus = false; |
|||
}); |
|||
}; |
|||
// return (
|
|||
// <a-switch
|
|||
// v-model:checked={record.state}
|
|||
// v-model:loading={record.pendingStatus}
|
|||
// onChange={onChange}
|
|||
// ></a-switch>
|
|||
// );
|
|||
// 渲染函数写法
|
|||
return h(Switch, { |
|||
checked: record.state === 1 ? true : false, |
|||
loading: record.pendingStatus, |
|||
onChange, |
|||
}); |
|||
}, |
|||
}, |
|||
{ |
|||
title: '是否管理员', |
|||
align: 'center', |
|||
width: 100, |
|||
dataIndex: 'isAdmin', |
|||
hideInSearch: true, |
|||
formItemProps: { |
|||
component: 'Select', |
|||
componentProps: { |
|||
options: [ |
|||
{ |
|||
label: '是', |
|||
value: 1, |
|||
}, |
|||
{ |
|||
label: '否', |
|||
value: 0, |
|||
}, |
|||
], |
|||
}, |
|||
}, |
|||
customRender: ({ record }) => { |
|||
const onChange = (checked: boolean) => { |
|||
console.log('checked: ', checked); |
|||
record.pendingStatus = true; |
|||
const newState = checked ? 1 : 0; |
|||
record.isAdmin = newState; |
|||
updateUser(record) |
|||
.then(() => { |
|||
record.isAdmin = newState; |
|||
}) |
|||
.catch(() => {}) |
|||
.finally(() => { |
|||
record.pendingStatus = false; |
|||
}); |
|||
}; |
|||
// return (
|
|||
// <a-switch
|
|||
// v-model:checked={record.state}
|
|||
// v-model:loading={record.pendingStatus}
|
|||
// onChange={onChange}
|
|||
// ></a-switch>
|
|||
// );
|
|||
// 渲染函数写法
|
|||
return h(Switch, { |
|||
checked: record.isAdmin === 1 ? true : false, |
|||
loading: record.pendingStatus, |
|||
onChange, |
|||
}); |
|||
}, |
|||
}, |
|||
{ |
|||
title: '创建时间', |
|||
align: 'center', |
|||
width: 200, |
|||
dataIndex: 'createTime', |
|||
formItemProps: { |
|||
defaultValue: '', |
|||
required: false, |
|||
component: 'RangePicker', |
|||
}, |
|||
}, |
|||
]; |
|||
|
|||
export const getBaseColumns = (tableInstance) => { |
|||
return [ |
|||
{ |
|||
title: '账号', |
|||
align: 'center', |
|||
dataIndex: 'account', |
|||
// sorter: true,
|
|||
width: 150, |
|||
resizable: true, |
|||
formItemProps: { |
|||
defaultValue: '', |
|||
required: false, |
|||
}, |
|||
}, |
|||
{ |
|||
title: '姓名', |
|||
align: 'center', |
|||
dataIndex: 'username', |
|||
width: 150, |
|||
resizable: true, |
|||
formItemProps: { |
|||
defaultValue: '', |
|||
required: false, |
|||
}, |
|||
}, |
|||
{ |
|||
title: '手机号码', |
|||
align: 'center', |
|||
dataIndex: 'mobile', |
|||
width: 150, |
|||
formItemProps: { |
|||
defaultValue: '', |
|||
required: false, |
|||
}, |
|||
}, |
|||
|
|||
{ |
|||
title: '性别', |
|||
align: 'center', |
|||
dataIndex: 'sex', |
|||
width: 100, |
|||
hideInSearch: true, |
|||
formItemProps: { |
|||
defaultValue: '', |
|||
required: false, |
|||
component: 'Select', |
|||
label: '性别', |
|||
componentProps: { |
|||
mode: 'single', |
|||
request: async () => { |
|||
// const data = await getSexList();
|
|||
return sexTypeList; |
|||
}, |
|||
}, |
|||
}, |
|||
customRender: ({ record }) => { |
|||
const text = sexTypeList.find((e) => e.value === record.sex)?.label; |
|||
return <div>{text}</div>; |
|||
}, |
|||
}, |
|||
{ |
|||
title: '帐号状态', |
|||
align: 'center', |
|||
width: 100, |
|||
dataIndex: 'state', |
|||
hideInSearch: true, |
|||
formItemProps: { |
|||
component: 'Select', |
|||
componentProps: { |
|||
options: [ |
|||
{ |
|||
label: '启用', |
|||
value: 1, |
|||
}, |
|||
{ |
|||
label: '禁用', |
|||
value: 0, |
|||
}, |
|||
], |
|||
}, |
|||
}, |
|||
customRender: ({ record }) => { |
|||
const onChange = (checked: boolean) => { |
|||
console.log('checked: ', checked); |
|||
record.pendingStatus = true; |
|||
const newState = checked ? 1 : 0; |
|||
record.state = newState; |
|||
updateUser(record) |
|||
.then(() => { |
|||
record.state = newState; |
|||
}) |
|||
.catch(() => {}) |
|||
.finally(() => { |
|||
record.pendingStatus = false; |
|||
tableInstance && tableInstance?.reload(); |
|||
}); |
|||
}; |
|||
// return (
|
|||
// <a-switch
|
|||
// v-model:checked={record.state}
|
|||
// v-model:loading={record.pendingStatus}
|
|||
// onChange={onChange}
|
|||
// ></a-switch>
|
|||
// );
|
|||
// 渲染函数写法
|
|||
return h(Switch, { |
|||
checked: record.state === 1 ? true : false, |
|||
loading: record.pendingStatus, |
|||
onChange, |
|||
}); |
|||
}, |
|||
}, |
|||
{ |
|||
title: '是否管理员', |
|||
align: 'center', |
|||
width: 100, |
|||
dataIndex: 'isAdmin', |
|||
hideInSearch: true, |
|||
formItemProps: { |
|||
component: 'Select', |
|||
componentProps: { |
|||
options: [ |
|||
{ |
|||
label: '是', |
|||
value: 1, |
|||
}, |
|||
{ |
|||
label: '否', |
|||
value: 0, |
|||
}, |
|||
], |
|||
}, |
|||
}, |
|||
customRender: ({ record }) => { |
|||
const onChange = (checked: boolean) => { |
|||
console.log('checked: ', checked); |
|||
record.pendingStatus = true; |
|||
const newState = checked ? 1 : 0; |
|||
record.isAdmin = newState; |
|||
updateUser(record) |
|||
.then(() => { |
|||
record.isAdmin = newState; |
|||
}) |
|||
.catch(() => {}) |
|||
.finally(() => { |
|||
record.pendingStatus = false; |
|||
tableInstance && tableInstance?.reload(); |
|||
}); |
|||
}; |
|||
// return (
|
|||
// <a-switch
|
|||
// v-model:checked={record.state}
|
|||
// v-model:loading={record.pendingStatus}
|
|||
// onChange={onChange}
|
|||
// ></a-switch>
|
|||
// );
|
|||
// 渲染函数写法
|
|||
return h(Switch, { |
|||
checked: record.isAdmin === 1 ? true : false, |
|||
loading: record.pendingStatus, |
|||
onChange, |
|||
}); |
|||
}, |
|||
}, |
|||
{ |
|||
title: '创建时间', |
|||
align: 'center', |
|||
width: 200, |
|||
dataIndex: 'createTime', |
|||
formItemProps: { |
|||
defaultValue: '', |
|||
required: false, |
|||
component: 'RangePicker', |
|||
}, |
|||
}, |
|||
]; |
|||
}; |
@ -0,0 +1,14 @@ |
|||
export const sexTypeList:any = [ |
|||
{ |
|||
label: '男', |
|||
value: 1, |
|||
}, |
|||
{ |
|||
label: '女', |
|||
value: 2, |
|||
}, |
|||
{ |
|||
label: '未知', |
|||
value: 3, |
|||
}, |
|||
]; |
@ -0,0 +1,123 @@ |
|||
/* |
|||
* @Author: AaronWu 2463371514@qq.com |
|||
* @Date: 2025-04-01 09:08:06 |
|||
* @LastEditors: AaronWu 2463371514@qq.com |
|||
* @LastEditTime: 2025-04-01 16:48:50 |
|||
* @FilePath: /IssueSupportManage/src/views/system/user/formSchemas.ts |
|||
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
|||
*/ |
|||
import type { FormSchema } from '@/components/core/schema-form/'; |
|||
import { sexTypeList } from './data'; |
|||
|
|||
export const userSchemas: FormSchema<API.CreateUserParams>[] = [ |
|||
{ |
|||
field: 'account', |
|||
component: 'Input', |
|||
label: '账号', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
rules: [{ required: true }], |
|||
}, |
|||
{ |
|||
field: 'username', |
|||
component: 'Input', |
|||
label: '用户名', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
rules: [{ required: true }], |
|||
}, |
|||
{ |
|||
field: 'password', |
|||
component: 'Input', |
|||
label: '密码', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
rules: [{ required: true }], |
|||
}, |
|||
{ |
|||
field: 'mobile', |
|||
component: 'Input', |
|||
label: '手机号码', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
rules: [ |
|||
{ |
|||
required: true, |
|||
message: '请输入正确格式的电话号码', |
|||
pattern: /^1(3[0-9]|4[01456879]|5[0-3,5-9]|6[2567]|7[0-8]|8[0-9]|9[0-3,5-9])\d{8}$/, |
|||
}, |
|||
], |
|||
}, |
|||
|
|||
{ |
|||
field: 'sex', |
|||
component: 'Select', |
|||
label: '性别', |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
componentProps: { |
|||
mode: 'single', |
|||
request: async () => { |
|||
// const data = await getSexList();
|
|||
return sexTypeList; |
|||
}, |
|||
}, |
|||
}, |
|||
|
|||
{ |
|||
field: 'state', |
|||
component: 'RadioGroup', |
|||
label: '帐号状态', |
|||
defaultValue: 1, |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
componentProps: { |
|||
options: [ |
|||
{ |
|||
label: '启用', |
|||
value: 1, |
|||
}, |
|||
{ |
|||
label: '禁用', |
|||
value: 0, |
|||
}, |
|||
], |
|||
}, |
|||
// required:true,
|
|||
rules: [{ required: true, type: 'number' }], |
|||
}, |
|||
{ |
|||
field: 'isAdmin', |
|||
component: 'RadioGroup', |
|||
label: '是否管理员', |
|||
defaultValue: 0, |
|||
colProps: { |
|||
span: 12, |
|||
}, |
|||
componentProps: { |
|||
options: [ |
|||
{ |
|||
label: '是', |
|||
value: 1, |
|||
}, |
|||
{ |
|||
label: '否', |
|||
value: 0, |
|||
}, |
|||
], |
|||
}, |
|||
// required:true,
|
|||
rules: [{ required: true, type: 'number' }], |
|||
}, |
|||
{ |
|||
field: 'remark', |
|||
component: 'InputTextArea', |
|||
label: '备注', |
|||
}, |
|||
]; |
@ -0,0 +1,241 @@ |
|||
<!-- |
|||
功能:功能描述 |
|||
作者:Aaron.Wu |
|||
时间:2023年05月25日 17:00:26 |
|||
版本:v1.0 |
|||
修改记录: |
|||
修改内容: |
|||
修改人员: |
|||
修改时间: |
|||
--> |
|||
<template> |
|||
<DynamicTable |
|||
size="small" |
|||
showIndex |
|||
headerTitle="管理员列表" |
|||
titleTooltip="" |
|||
:data-request="loadData" |
|||
:columns="columns" |
|||
row-key="id" |
|||
@resize-column="handleResizeColumn" |
|||
:row-selection="rowSelection" |
|||
:scroll="{ x: '100vw' }" |
|||
> |
|||
<template v-if="isCheckRows" #title> |
|||
<Alert class="w-full" type="info" show-icon> |
|||
<template #message> |
|||
已选 {{ isCheckRows }} 项 |
|||
<a-button type="link" @click="rowSelection.selectedRowKeys = []">取消选择</a-button> |
|||
</template> |
|||
</Alert> |
|||
</template> |
|||
<template #toolbar> |
|||
<!-- <a-button type="primary" @click="openUserModal({})">新增</a-button> --> |
|||
<a-button |
|||
type="danger" |
|||
:disabled="!isCheckRows" |
|||
@click="delRowConfirm(rowSelection.selectedRowKeys)" |
|||
> |
|||
<DeleteOutlined /> 删除 |
|||
</a-button> |
|||
</template> |
|||
</DynamicTable> |
|||
</template> |
|||
|
|||
<script lang="tsx" setup> |
|||
import { type TableListItem, getBaseColumns } from './columns'; |
|||
import { useTable, type OnChangeCallbackParams } from '@/components/core/dynamic-table'; |
|||
import { |
|||
fetchUserList, |
|||
fetchUserPageList, |
|||
createUser, |
|||
updateUser, |
|||
findOneById, |
|||
deleteUserById, |
|||
deleteBatchUserById, |
|||
} from '@/api/user'; |
|||
import { computed, reactive, ref, toRaw } from 'vue'; |
|||
import { Modal, message, Alert } from 'ant-design-vue'; |
|||
|
|||
import { useFormModal } from '@/hooks/useModal/index'; |
|||
import { userSchemas } from './formSchemas'; |
|||
import { ExclamationCircleOutlined, DeleteOutlined } from '@ant-design/icons-vue'; |
|||
|
|||
defineOptions({ |
|||
name: 'tanant-user', |
|||
}); |
|||
|
|||
const [showModal] = useFormModal(); |
|||
|
|||
const [DynamicTable, dynamicTableInstance] = useTable(); |
|||
|
|||
const columns = [ |
|||
...getBaseColumns(dynamicTableInstance), |
|||
{ |
|||
title: '操作', |
|||
width: 200, |
|||
dataIndex: 'ACTION', |
|||
hideInSearch: true, |
|||
align: 'center', |
|||
fixed: 'right', |
|||
actions: ({ record }) => [ |
|||
{ |
|||
icon: 'searchoutlined', |
|||
color: '#3b82f6', |
|||
label: '查看', |
|||
onClick: () => handleShow(record), |
|||
}, |
|||
// { |
|||
// icon: 'edit', |
|||
// color: '#3b82f6', |
|||
// size: '15', |
|||
// label: '修改', |
|||
// onClick: () => handleEdit(record), |
|||
// }, |
|||
{ |
|||
icon: 'delete', |
|||
color: '#ec6f6f', |
|||
label: '删除', |
|||
popConfirm: { |
|||
title: '确定要删除吗?', |
|||
onConfirm: () => handleDelete(record.id), |
|||
}, |
|||
}, |
|||
], |
|||
}, |
|||
]; |
|||
/** |
|||
* @description 打开用户弹窗 |
|||
*/ |
|||
const openUserModal = async (record: Partial<TableListItem> = {}, isReadOnly = false) => { |
|||
const [formRef] = await showModal<any>({ |
|||
modalProps: { |
|||
title: `${isReadOnly ? '查看' : record.id ? '编辑' : '新增'}用户`, |
|||
width: 700, |
|||
onFinish: async (values) => { |
|||
console.log('新增/编辑用户', values); |
|||
values.id = record.id; |
|||
await (record.id ? updateUser : createUser)(values); |
|||
message.success(`${record.id ? '编辑' : '新增'}成功`); |
|||
dynamicTableInstance?.reload(); |
|||
}, |
|||
footer: isReadOnly ? null : undefined, |
|||
}, |
|||
formProps: { |
|||
labelWidth: 100, |
|||
schemas: userSchemas as any, |
|||
autoSubmitOnEnter: true, |
|||
disabled: isReadOnly, |
|||
}, |
|||
}); |
|||
|
|||
formRef?.setFieldsValue(record); |
|||
// if (record?.id) { |
|||
// const { roles } = await getUserInfo({ userId: record.id }); |
|||
// formRef?.setFieldsValue({ roles }); |
|||
// } |
|||
}; |
|||
|
|||
const handleEdit = (record: TableListItem) => { |
|||
openUserModal(record); |
|||
}; |
|||
|
|||
const handleShow = (record: TableListItem) => { |
|||
openUserModal(record, true); |
|||
}; |
|||
|
|||
const handleDelete = (id: string) => { |
|||
delRowConfirm([id]); |
|||
}; |
|||
|
|||
/** |
|||
* @description 表格删除行 |
|||
*/ |
|||
const delRowConfirm = async (ids: string[]) => { |
|||
Modal.confirm({ |
|||
title: '确定要删除所选的用户吗?', |
|||
icon: <ExclamationCircleOutlined />, |
|||
centered: true, |
|||
onOk: async () => { |
|||
await deleteBatchUserById(ids).finally(dynamicTableInstance?.reload); |
|||
}, |
|||
}); |
|||
}; |
|||
|
|||
const rowSelection = ref<any>({ |
|||
selectedRowKeys: [] as string[], |
|||
onChange: (selectedRowKeys: string[], selectedRows: TableListItem[]) => { |
|||
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows); |
|||
rowSelection.value.selectedRowKeys = selectedRowKeys; |
|||
}, |
|||
}); |
|||
|
|||
// 是否勾选了表格行 |
|||
const isCheckRows = computed(() => rowSelection.value.selectedRowKeys.length); |
|||
|
|||
const loadData = async ( |
|||
params, |
|||
onChangeParams?: OnChangeCallbackParams, |
|||
): Promise<API.TableListResult> => { |
|||
console.log('params', params); |
|||
console.log('onChangeParams', onChangeParams); |
|||
// 手动设置搜索表单的搜索项 |
|||
// dynamicTableInstance?.getQueryFormRef()?.updateSchema?.([ |
|||
// { |
|||
// field: 'price', |
|||
// componentProps: { |
|||
// options: [ |
|||
// { |
|||
// label: '0-199', |
|||
// value: '0-199', |
|||
// }, |
|||
// { |
|||
// label: '200-999', |
|||
// value: '200-999', |
|||
// }, |
|||
// ], |
|||
// }, |
|||
// }, |
|||
// ]); |
|||
|
|||
// return new Promise((resolve) => { |
|||
// setTimeout(() => { |
|||
// resolve({ |
|||
// list: [ |
|||
// { |
|||
// id: '1', |
|||
// name: '1', |
|||
// }, |
|||
// ], |
|||
// ...params, |
|||
// }); |
|||
// }, 500); |
|||
// }); |
|||
const res = await fetchUserPageList({ |
|||
...params, |
|||
isAdmin: 1, |
|||
current: params.page, |
|||
size: params.limit, |
|||
}); |
|||
console.log('res: ', res); |
|||
rowSelection.value.selectedRowKeys = []; |
|||
|
|||
return { |
|||
list: res.data.records, |
|||
pagination: { |
|||
total: Number(res.data.total), |
|||
...params, |
|||
}, |
|||
}; |
|||
}; |
|||
const handleResizeColumn = (w, col) => { |
|||
// console.log('w', w, col); |
|||
col.width = w; |
|||
}; |
|||
</script> |
|||
|
|||
<style lang="less" scoped> |
|||
.action-divider { |
|||
margin: 0 5px; |
|||
} |
|||
</style> |
Loading…
Reference in new issue