@@ -0,0 +1,17 @@ | |||
export interface ErrorCodeVO { | |||
id: number | |||
type: number | |||
applicationName: string | |||
code: number | |||
message: string | |||
memo: string | |||
createTime: Date | |||
} | |||
export interface ErrorCodePageReqVO extends PageParam { | |||
type?: number | |||
applicationName?: string | |||
code?: number | |||
message?: string | |||
createTime?: Date[] | |||
} |
@@ -9,6 +9,7 @@ export * from './platform-product.data.ts' | |||
export * from './notice.data.ts' | |||
export * from './logs.data.ts' | |||
export * from './system-dict.data.ts' | |||
export * from './error-code.data.ts' | |||
export interface ResponseDTO<T>{ | |||
code: number; | |||
@@ -117,3 +117,11 @@ export interface UserPageReqVO extends PageParam { | |||
status?: number | |||
createTime?: Date[] | |||
} | |||
export interface UserExportReqVO { | |||
code?: string | |||
name?: string | |||
status?: number | |||
createTime?: Date[] | |||
} |
@@ -0,0 +1,120 @@ | |||
import React, { useEffect, useState } from 'react' | |||
import { Form, Input, Radio, Modal, InputNumber, ColorPicker } from 'antd'; | |||
import { useRequest } from '@/hooks/use-request'; | |||
import { antdUtils } from '@/utils/antd'; | |||
import service from '@/request/service/error-code'; | |||
import type { ErrorCodeVO, ErrorCodePageReqVO } from '@/models'; | |||
const layout = { | |||
labelCol: { span: 4, }, | |||
wrapperCol: { span: 16 } | |||
}; | |||
interface DataTypeEditorProps { | |||
visible: boolean; | |||
onCancel: (flag?: boolean) => void; | |||
onSave: (role: ErrorCodeVO) => void; | |||
data?: ErrorCodeVO | null; | |||
} | |||
export default (props: DataTypeEditorProps) => { | |||
const { visible, onCancel, onSave, data } = props; | |||
const { runAsync: update } = useRequest(service.updateErrorCodeApi, { manual: true }); | |||
const { runAsync: create } = useRequest(service.createErrorCodeApi, { manual: true }); | |||
const isEdit = !!data; | |||
const [saveLoading, setSaveLoading] = useState(false); | |||
const [form] = Form.useForm(); | |||
useEffect(() => { | |||
if (visible) { | |||
if (data) { | |||
form.setFieldsValue(data); | |||
} | |||
} else { | |||
form.resetFields(); | |||
} | |||
}, [visible]); | |||
const save = async () => { | |||
setSaveLoading(true); | |||
const fieldValues = form.getFieldsValue(); | |||
const cssClass = fieldValues.cssClass ? fieldValues.cssClass.toHex() : ''; | |||
const newValue = isEdit ? { ...data, ...fieldValues, cssClass } : fieldValues; | |||
const [error, { msg, code }] = isEdit ? await update(newValue) : await create(newValue); | |||
if (!error && code === 0) { | |||
onSave(newValue); | |||
} else { | |||
antdUtils.message?.open({ | |||
type: 'error', | |||
content: msg ?? '操作失败', | |||
}); | |||
} | |||
setSaveLoading(false); | |||
} | |||
return ( | |||
<> | |||
<Modal | |||
open={visible} | |||
title={isEdit ? "编辑" : "新建"} | |||
width={640} | |||
onOk={save} | |||
onCancel={() => onCancel()} | |||
confirmLoading={saveLoading} | |||
destroyOnClose | |||
> | |||
<Form | |||
form={form} | |||
{...layout} | |||
onFinish={save} | |||
labelCol={{ flex: '0 0 100px' }} | |||
wrapperCol={{ span: 16 }} | |||
> | |||
<Form.Item name="type" label="错误码类型"> | |||
<Radio.Group options={[ | |||
{ value: 1, label: "自动生成" }, | |||
{ value: 2, label: "手动编辑" } | |||
]} optionType="button"> | |||
</Radio.Group> | |||
</Form.Item> | |||
<Form.Item name="applicationName" label="应用名" | |||
rules={[ | |||
{ | |||
required: true, | |||
message: '请输入应用名', | |||
}, | |||
]} | |||
> | |||
<Input /> | |||
</Form.Item> | |||
<Form.Item name="code" label="错误码编码" | |||
rules={[ | |||
{ | |||
required: true, | |||
message: '请输入错误码编码', | |||
}, | |||
]}> | |||
<InputNumber min={0} /> | |||
</Form.Item> | |||
<Form.Item name="message" label="错误码提示" | |||
rules={[ | |||
{ | |||
required: true, | |||
message: '请输入错误码编码', | |||
}, | |||
]}> | |||
<Input.TextArea showCount maxLength={100} /> | |||
</Form.Item> | |||
</Form> | |||
</Modal> | |||
</> | |||
) | |||
}; |
@@ -0,0 +1,227 @@ | |||
import React, { useState, useEffect, useMemo } from 'react'; | |||
import { Space, Table, Button, Tag, Divider, Input, Card } from 'antd'; | |||
import { useSetState } from 'ahooks'; | |||
import type { TableProps, ColumnsType, ColumnType } from 'antd/es/table'; | |||
import { t } from '@/utils/i18n'; | |||
import { PlusOutlined, ExclamationCircleFilled, SearchOutlined } from '@ant-design/icons'; | |||
import { antdUtils } from '@/utils/antd'; | |||
import { useRequest } from '@/hooks/use-request'; | |||
import type { ErrorCodeVO, ErrorCodePageReqVO } from '@/models' | |||
import errorCodeService from '@/request/service/error-code'; | |||
import ErrorCodeEditor from './error-code-editor'; | |||
type DataIndex = keyof ErrorCodeVO; | |||
export default () => { | |||
const showDeleteConfirm = (item: ErrorCodeVO) => { | |||
antdUtils.modal?.confirm({ | |||
title: `确认删除编号为 ${item.id} 的错误码吗?`, | |||
icon: <ExclamationCircleFilled />, | |||
content: '请注意删除以后不可恢复!', | |||
okText: '删除', | |||
okType: 'danger', | |||
cancelText: '取消', | |||
onOk() { | |||
return new Promise(async (resolve, reject) => { | |||
const [error, { code, msg }] = await deleteApi(item.id); | |||
if (error || code !== 0) { | |||
antdUtils.message?.open({ type: 'error', content: msg ?? '操作失败' }) | |||
} else { | |||
antdUtils.message?.open({ type: 'success', content: '删除成功' }) | |||
} | |||
await load(); | |||
resolve(''); | |||
}).catch(() => antdUtils.message?.open({ | |||
type: 'error', | |||
content: '操作失败', | |||
})); | |||
}, | |||
onCancel() { | |||
}, | |||
}); | |||
}; | |||
const [editorVisable, seEditorVisable] = useState<boolean>(false); | |||
const [editData, seEditData] = useState<ErrorCodeVO>(); | |||
const [dataSource, setDataSource] = useState<ErrorCodeVO[]>([]); | |||
const [total, setTotal] = useState(0); | |||
const [searchState, setSearchState] = useSetState<ErrorCodePageReqVO>({}); | |||
const [onSearching, setOnSearching] = useState(false); | |||
const { runAsync: getPageApi } = useRequest(errorCodeService.getErrorCodePageApi, { manual: true }); | |||
const { runAsync: deleteApi } = useRequest(errorCodeService.deleteErrorCodeApi, { manual: true }); | |||
const showEditor = (record: ErrorCodeVO | undefined) => { | |||
seEditData(record); | |||
seEditorVisable(true); | |||
} | |||
const load = async () => { | |||
const [error, { data, code, msg }] = await getPageApi(searchState); | |||
setOnSearching(false); | |||
if (!error) { | |||
setDataSource(data.list); | |||
setTotal(data.total); | |||
} else { | |||
if (error || code !== 0) { | |||
antdUtils.message?.open({ type: 'error', content: msg ?? '操作失败' }); | |||
return | |||
} | |||
} | |||
}; | |||
const getColumnSearchProps = (dataIndex: DataIndex): ColumnType<ErrorCodeVO> => ({ | |||
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters, close }) => ( | |||
<div style={{ padding: 8 }} onKeyDown={(e) => e.stopPropagation()}> | |||
<Input.Search | |||
placeholder={dataIndex === 'type' ? '输入要搜索的字典名称' : '输入要搜索的字典类型'} | |||
value={selectedKeys[0]} | |||
onChange={(e) => { | |||
setSelectedKeys(e.target.value && e.target.value !== '' ? [e.target.value] : []) | |||
}} | |||
onSearch={(value) => { | |||
if (value === '' && clearFilters) { | |||
clearFilters!!() | |||
} | |||
confirm(); | |||
}} | |||
onPressEnter={() => confirm()} | |||
allowClear | |||
style={{ marginBottom: 8, display: 'block' }} | |||
enterButton="搜索" | |||
size="middle" | |||
loading={onSearching} | |||
/> | |||
</div> | |||
), | |||
filterIcon: (filtered: boolean) => ( | |||
<SearchOutlined style={{ color: filtered ? 'primaryColor' : undefined }} /> | |||
), | |||
}); | |||
const columns: ColumnsType<ErrorCodeVO> = [ | |||
{ | |||
title: '编号', | |||
dataIndex: 'id', | |||
key: 'id', | |||
align: 'center', | |||
width: 100, | |||
}, | |||
{ | |||
title: '错误码类型', | |||
dataIndex: 'type', | |||
key: 'type', | |||
align: 'center', | |||
width: 150, | |||
filters: [ | |||
{ text: '自动生成', value: 1 }, | |||
{ text: '手动编辑', value: 2 }, | |||
], | |||
filterMultiple: false, | |||
filterSearch: false, | |||
render: (value: number) => { | |||
return (value === 1 ? <Tag color="purple">自动生成</Tag> : <Tag color="blue">手动编辑</Tag>) | |||
}, | |||
}, | |||
{ | |||
title: '应用名', | |||
dataIndex: 'applicationName', | |||
key: 'applicationName', | |||
align: 'center', | |||
width: 150, | |||
...getColumnSearchProps('applicationName') | |||
}, | |||
{ | |||
title: '错误码编码', | |||
key: 'code', | |||
dataIndex: 'code', | |||
align: 'center', | |||
width: 150, | |||
...getColumnSearchProps('code') | |||
}, | |||
{ | |||
title: '错误码错误提示', | |||
key: 'message', | |||
dataIndex: 'message', | |||
align: 'center', | |||
width: 200, | |||
...getColumnSearchProps('message') | |||
}, | |||
{ | |||
title: t("QkOmYwne" /* 操作 */), | |||
key: 'action', | |||
align: 'center', | |||
render: (_, record) => ( | |||
<Space size="middle" split={( | |||
<Divider type='vertical' /> | |||
)}> | |||
<a onClick={() => showEditor(record)}> | |||
编辑 | |||
</a> | |||
<a onClick={() => showDeleteConfirm(record)}> | |||
删除 | |||
</a> | |||
</Space> | |||
), | |||
width: 150, | |||
}, | |||
]; | |||
useEffect(() => { | |||
load(); | |||
}, [searchState]); | |||
useMemo(() => { | |||
console.log('onMemChanged: ' + editData) | |||
}, [editData]) | |||
const onChange: TableProps<ErrorCodeVO>['onChange'] = (pagination, filters, sorter, extra) => { | |||
const state: ErrorCodePageReqVO = { | |||
applicationName: filters.applicationName ? filters.applicationName[0] as string : undefined, | |||
message: filters.message ? filters.message[0] as string : undefined, | |||
code: filters.code ? filters.code[0] as number : undefined, | |||
type: filters.type ? filters.type[0] as number : undefined, | |||
pageNo: pagination.current, | |||
pageSize: pagination.pageSize | |||
} | |||
setSearchState(state); | |||
}; | |||
return ( | |||
<> | |||
<Card className='mt-[4px] dark:bg-[rgb(33,41,70)] bg-white roundle-lg px[12px]' | |||
bodyStyle={{ | |||
paddingTop: 0, | |||
paddingBottom: 0 | |||
}}> | |||
<div className="py-[8px] flex flex-row-reverse"> | |||
<Button className="ml-5" | |||
type='primary' | |||
icon={<PlusOutlined />} | |||
onClick={() => showEditor(undefined)}> 新增 </Button> | |||
</div> | |||
<Table rowKey="id" | |||
scroll={{ x: true }} | |||
onChange={onChange} | |||
columns={columns} | |||
dataSource={dataSource} | |||
className='bg-transparent' | |||
pagination={{ | |||
pageSize: searchState.pageSize, | |||
current: searchState.pageNo, | |||
total, | |||
position: ['bottomRight'] | |||
}} | |||
/> | |||
</Card> | |||
<ErrorCodeEditor onSave={() => { | |||
load(); | |||
seEditorVisable(false); | |||
}} | |||
onCancel={() => { seEditorVisable(false) }} | |||
visible={editorVisable} | |||
data={editData} /> | |||
</> | |||
); | |||
}; |
@@ -0,0 +1,38 @@ | |||
import request from '@/request'; | |||
import { ErrorCodeVO, ErrorCodePageReqVO, PageData } from '@/models' | |||
const BASE_URL = '/admin-api/system/error-code'; | |||
export default { | |||
// 查询错误码列表 | |||
getErrorCodePageApi: (params: ErrorCodePageReqVO) => { | |||
return request.get<PageData<ErrorCodeVO>>(`${BASE_URL}/page`, { params }) | |||
}, | |||
// 查询错误码详情 | |||
getErrorCodeApi: (id: number) => { | |||
return request.get(`${BASE_URL}/get?id=${id}`) | |||
}, | |||
// 新增错误码 | |||
createErrorCodeApi: (data: ErrorCodeVO) => { | |||
return request.post(`${BASE_URL}/create`, data) | |||
}, | |||
// 修改错误码 | |||
updateErrorCodeApi: (data: ErrorCodeVO) => { | |||
return request.put(`${BASE_URL}/update`, data) | |||
}, | |||
// 删除错误码 | |||
deleteErrorCodeApi: (id: number) => { | |||
return request.delete(`${BASE_URL}/delete?id=${id}`) | |||
}, | |||
// 导出错误码 | |||
excelErrorCodeApi: (params: ErrorCodePageReqVO) => { | |||
return request.get(`${BASE_URL}/export-excel`, { params, responseType: 'blob' }) | |||
}, | |||
}; | |||
@@ -36,10 +36,10 @@ export default { | |||
return request.delete(`${BASE_URL}/get?id=${id}`) | |||
}, | |||
// 导出岗位 | |||
// exportPostApi: (params: PostExportReqVO) => { | |||
// return request.download({ url: '/system/post/export', params }) | |||
// }, | |||
//导出岗位 | |||
exportPostApi: (params: PositionExportReqVO) => { | |||
return request.get(`${BASE_URL}/export`, { params, responseType: 'blob' }) | |||
}, | |||
}; | |||
@@ -36,6 +36,6 @@ export default { | |||
}, | |||
// 导出字典类型数据 | |||
exportDictDataApi: (params: DictDataExportReqVO) => { | |||
return request.get(`${BASE_URL}/export`, { params }) | |||
return request.get(`${BASE_URL}/export`, { params, responseType: 'blob' }) | |||
} | |||
}; |
@@ -36,7 +36,7 @@ export default { | |||
}, | |||
// 导出字典类型 | |||
exportDictTypeApi: (params: DictTypeExportReqVO) => { | |||
return request.get(`${BASE_URL}/export`, { params }) | |||
return request.get(`${BASE_URL}/export`, { params, responseType: 'blob' }) | |||
} | |||
}; | |||
@@ -31,7 +31,7 @@ export default { | |||
// 导出租户 | |||
exportTenantApi: (params: TenantExportReqVO) => { | |||
return request.download(`${BASE_URL}/export-excel`, params) | |||
return request.get(`${BASE_URL}/export-excel`, { params, responseType: 'blob'}) | |||
}, | |||
} | |||
@@ -1,5 +1,5 @@ | |||
import request from '@/request'; | |||
import { User, UserVO, UserPageReqVO, PageData } from '@/models'; | |||
import { User, UserVO, UserPageReqVO, UserExportReqVO, PageData } from '@/models'; | |||
const BASE_URL = '/admin-api/system/user'; | |||
@@ -11,7 +11,7 @@ export default { | |||
// 查询用户管理列表 | |||
getUserPageApi: (params: UserPageReqVO) => { | |||
return request.get<PageData<UserVO>>(`${BASE_URL}/page`, {params}) | |||
return request.get<PageData<UserVO>>(`${BASE_URL}/page`, { params }) | |||
}, | |||
// 查询用户详情 | |||
@@ -35,14 +35,14 @@ export default { | |||
}, | |||
// 导出用户 | |||
// exportUserApi: (params: UserExportReqVO) => { | |||
// return request.download(`${BASE_URL}/export`, params ) | |||
// }, | |||
exportUserApi: (params: UserExportReqVO) => { | |||
return request.get(`${BASE_URL}/export`, { params, responseType: 'blob' }) | |||
}, | |||
// 下载用户导入模板 | |||
// importUserTemplateApi: () => { | |||
// return request.download(`${BASE_URL}/get-import-template` ) | |||
// }, | |||
importUserTemplateApi: () => { | |||
return request.get(`${BASE_URL}/get-import-template`, { responseType: 'blob' }) | |||
}, | |||
// 用户密码重置 | |||
resetUserPwdApi: (id: number, password: string) => { | |||