29 changed files with 715 additions and 118 deletions
|
After Width: | Height: | Size: 1.0 KiB |
@ -1,4 +1,5 @@ |
|||||
export default { |
export default { |
||||
settings: 'settings', |
settings: 'settings', |
||||
about: 'about', |
about: 'about', |
||||
|
goToClient: 'go to client', |
||||
}; |
}; |
||||
|
|||||
@ -1,4 +1,5 @@ |
|||||
export default { |
export default { |
||||
settings: '个人设置', |
settings: '个人设置', |
||||
about: '关于', |
about: '关于', |
||||
|
goToClient: '去客户端', |
||||
}; |
}; |
||||
|
|||||
@ -0,0 +1,165 @@ |
|||||
|
import type { TableColumn } from '@/components/core/dynamic-table'; |
||||
|
import { stateTypeList } from './data'; |
||||
|
import { Tag } from 'ant-design-vue'; |
||||
|
import { DictEnum } from '@/enums/dictEnum'; |
||||
|
import { getDictionaryByTypeName } from '@/utils/dict'; |
||||
|
export type TableListItem = API.IssueType; |
||||
|
export type TableColumnItem = TableColumn<TableListItem>; |
||||
|
|
||||
|
// const questionTypeList = await getDictionaryByTypeName(DictEnum.QUESTION_TYPE);
|
||||
|
|
||||
|
// 数据项类型
|
||||
|
// export type ListItemType = typeof tableData[number];
|
||||
|
// 使用TableColumn<ListItemType> 将会限制dataIndex的类型,但换来的是dataIndex有类型提示
|
||||
|
export const baseColumns: TableColumnItem[] = [ |
||||
|
{ |
||||
|
title: '问题标题', |
||||
|
align: 'center', |
||||
|
dataIndex: 'title', |
||||
|
// sorter: true,
|
||||
|
width: 150, |
||||
|
resizable: true, |
||||
|
formItemProps: { |
||||
|
defaultValue: '', |
||||
|
required: false, |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '问题描述', |
||||
|
align: 'center', |
||||
|
dataIndex: 'description', |
||||
|
width: 150, |
||||
|
ellipsis: true, |
||||
|
resizable: true, |
||||
|
formItemProps: { |
||||
|
defaultValue: '', |
||||
|
required: false, |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '标签', |
||||
|
align: 'center', |
||||
|
dataIndex: 'tags', |
||||
|
width: 200, |
||||
|
hideInSearch: true, |
||||
|
}, |
||||
|
// {
|
||||
|
// title: '问题属性',
|
||||
|
// align: 'center',
|
||||
|
// dataIndex: 'attribute',
|
||||
|
// width: 150,
|
||||
|
// formItemProps: {
|
||||
|
// defaultValue: undefined,
|
||||
|
// required: false,
|
||||
|
// component: 'Select',
|
||||
|
// componentProps: {
|
||||
|
// options: questionTypeList,
|
||||
|
// },
|
||||
|
// },
|
||||
|
// customRender: ({ record }) => {
|
||||
|
// const label = questionTypeList?.find((e) => e.value === record.attribute)?.label;
|
||||
|
|
||||
|
// return <div>{{ label }}</div>;
|
||||
|
// },
|
||||
|
// },
|
||||
|
{ |
||||
|
title: '问题号', |
||||
|
align: 'center', |
||||
|
dataIndex: 'billcode', |
||||
|
width: 200, |
||||
|
formItemProps: { |
||||
|
defaultValue: '', |
||||
|
required: false, |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '客户', |
||||
|
align: 'center', |
||||
|
dataIndex: 'customer', |
||||
|
width: 150, |
||||
|
hideInSearch: true, |
||||
|
formItemProps: { |
||||
|
defaultValue: '', |
||||
|
required: false, |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '产品', |
||||
|
align: 'center', |
||||
|
dataIndex: 'product', |
||||
|
width: 150, |
||||
|
hideInSearch: true, |
||||
|
formItemProps: { |
||||
|
defaultValue: '', |
||||
|
required: false, |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '版本', |
||||
|
align: 'center', |
||||
|
dataIndex: 'version', |
||||
|
width: 150, |
||||
|
hideInSearch: true, |
||||
|
formItemProps: { |
||||
|
defaultValue: '', |
||||
|
required: false, |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '代理商', |
||||
|
align: 'center', |
||||
|
dataIndex: 'agent', |
||||
|
width: 150, |
||||
|
hideInSearch: true, |
||||
|
formItemProps: { |
||||
|
defaultValue: '', |
||||
|
required: false, |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '服务号', |
||||
|
align: 'center', |
||||
|
dataIndex: 'serviceNumber', |
||||
|
width: 150, |
||||
|
hideInSearch: true, |
||||
|
formItemProps: { |
||||
|
defaultValue: '', |
||||
|
required: false, |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
title: '创建时间', |
||||
|
align: 'center', |
||||
|
width: 200, |
||||
|
dataIndex: 'createTime', |
||||
|
formItemProps: { |
||||
|
defaultValue: '', |
||||
|
required: false, |
||||
|
component: 'RangePicker', |
||||
|
componentProps: { |
||||
|
valueFormat: 'YYYY-MM-DD', |
||||
|
}, |
||||
|
}, |
||||
|
}, |
||||
|
// state 问题状态
|
||||
|
{ |
||||
|
title: '问题状态', |
||||
|
align: 'center', |
||||
|
dataIndex: 'state', |
||||
|
width: 150, |
||||
|
fixed: 'right', |
||||
|
formItemProps: { |
||||
|
defaultValue: undefined, |
||||
|
required: false, |
||||
|
component: 'Select', |
||||
|
componentProps: { |
||||
|
options: stateTypeList, |
||||
|
}, |
||||
|
}, |
||||
|
customRender: ({ record }) => { |
||||
|
const { label, color } = stateTypeList.find((e) => e.value === record.state); |
||||
|
|
||||
|
return <Tag color={color}>{label}</Tag>; |
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
@ -0,0 +1,32 @@ |
|||||
|
export const stateTypeList: any = [ |
||||
|
// Init(0,"待处理"),
|
||||
|
// Back(1,"退回"),
|
||||
|
// Develop(2,"开发中"),
|
||||
|
// Test(3,"测试中"),
|
||||
|
// End(4,"结束"),
|
||||
|
{ |
||||
|
label: '待处理', |
||||
|
value: 0, |
||||
|
color: '#f50', |
||||
|
}, |
||||
|
{ |
||||
|
label: '退回', |
||||
|
value: 1, |
||||
|
color: '#2db7f5', |
||||
|
}, |
||||
|
{ |
||||
|
label: '开发中', |
||||
|
value: 2, |
||||
|
color: '#87d068', |
||||
|
}, |
||||
|
{ |
||||
|
label: '测试中', |
||||
|
value: 3, |
||||
|
color: '#108ee9', |
||||
|
}, |
||||
|
{ |
||||
|
label: '已解决', |
||||
|
value: 4, |
||||
|
color: '#f50', |
||||
|
}, |
||||
|
]; |
||||
@ -0,0 +1,294 @@ |
|||||
|
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 { DictEnum } from '@/enums/dictEnum'; |
||||
|
import { getDictionaryByTypeName } from '@/utils/dict'; |
||||
|
import { fetchProdList, fetchVersionPageList } from '@/api/prodVersion'; |
||||
|
import { vShow } from 'vue'; |
||||
|
const questionTypeList = await getDictionaryByTypeName(DictEnum.QUESTION_TYPE); |
||||
|
// 编辑页字段
|
||||
|
export const getEditFormSchema: ( |
||||
|
row?: Partial<TableListItem>, |
||||
|
isDetail?: boolean, |
||||
|
) => FormSchema[] = (record = {}, isDetail = false) => { |
||||
|
console.log('questionTypeList: ', questionTypeList); |
||||
|
|
||||
|
return [ |
||||
|
{ |
||||
|
field: 'billcode', |
||||
|
component: 'Input', |
||||
|
label: '问题号', |
||||
|
dynamicDisabled: true, |
||||
|
colProps: { |
||||
|
span: 24, |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
field: 'title', |
||||
|
component: 'Input', |
||||
|
componentProps: { |
||||
|
showCount: true, |
||||
|
maxlength: 150, |
||||
|
}, |
||||
|
label: '问题标题', |
||||
|
colProps: { |
||||
|
span: 12, |
||||
|
}, |
||||
|
rules: [{ required: true }], |
||||
|
}, |
||||
|
{ |
||||
|
field: 'tags', |
||||
|
component: 'Select', |
||||
|
componentProps: { |
||||
|
request: async () => { |
||||
|
const data = await getDictionaryByTypeName(DictEnum.TAG_TYPE); |
||||
|
return data; |
||||
|
}, |
||||
|
multiple: true, |
||||
|
placeholder: '请选择标签', |
||||
|
mode: 'tags', |
||||
|
allowClear: true, |
||||
|
}, |
||||
|
label: '标签', |
||||
|
colProps: { |
||||
|
span: 12, |
||||
|
}, |
||||
|
rules: [{ required: true, type: 'array' }], |
||||
|
}, |
||||
|
// {
|
||||
|
// label: '问题属性',
|
||||
|
// field: 'arrtibute',
|
||||
|
// component: 'Select',
|
||||
|
// componentProps: {
|
||||
|
// options: questionTypeList,
|
||||
|
// },
|
||||
|
// colProps: {
|
||||
|
// span: 12,
|
||||
|
// },
|
||||
|
// rules: [{ required: true, type: 'string' }],
|
||||
|
// },
|
||||
|
|
||||
|
{ |
||||
|
field: 'customer', |
||||
|
component: 'Input', |
||||
|
label: '客户', |
||||
|
colProps: { |
||||
|
span: 12, |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
field: 'productId', |
||||
|
component: 'Select', |
||||
|
componentProps: ({ formModel, formInstance }) => { |
||||
|
return { |
||||
|
request: async () => { |
||||
|
const data = (await fetchProdList({})) as any; |
||||
|
return data.map((e) => { |
||||
|
return { |
||||
|
label: e.name, |
||||
|
value: e.id, |
||||
|
}; |
||||
|
}); |
||||
|
}, |
||||
|
onChange: async (e) => { |
||||
|
console.log('e: ', e); |
||||
|
const { data } = await fetchVersionPageList({ |
||||
|
productId: e, |
||||
|
current: 1, |
||||
|
size: 999, |
||||
|
}); |
||||
|
if (data && Array.isArray(data) && data.length) { |
||||
|
formInstance?.setFieldsValue({ |
||||
|
versionId: data[0].id, |
||||
|
}); |
||||
|
formInstance.updateSchema({ |
||||
|
field: 'versionId', |
||||
|
componentProps: { |
||||
|
options: data.map((e) => { |
||||
|
return { |
||||
|
label: e.name, |
||||
|
value: e.id, |
||||
|
}; |
||||
|
}), |
||||
|
}, |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
}; |
||||
|
}, |
||||
|
label: '产品', |
||||
|
colProps: { |
||||
|
span: 12, |
||||
|
}, |
||||
|
rules: [{ required: true, type: 'number' }], |
||||
|
}, |
||||
|
{ |
||||
|
field: 'versionId', |
||||
|
component: 'Select', |
||||
|
componentProps: { |
||||
|
options: [], |
||||
|
}, |
||||
|
label: '版本', |
||||
|
colProps: { |
||||
|
span: 12, |
||||
|
}, |
||||
|
rules: [{ required: true, type: 'number' }], |
||||
|
}, |
||||
|
{ |
||||
|
field: 'agent', |
||||
|
component: 'Input', |
||||
|
label: '代理商', |
||||
|
colProps: { |
||||
|
span: 12, |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
{ |
||||
|
field: 'serviceNumber', |
||||
|
component: 'Input', |
||||
|
label: '服务号', |
||||
|
colProps: { |
||||
|
span: 12, |
||||
|
}, |
||||
|
}, |
||||
|
|
||||
|
{ |
||||
|
field: 'contacts', |
||||
|
component: 'Input', |
||||
|
label: '联系人', |
||||
|
colProps: { |
||||
|
span: 12, |
||||
|
}, |
||||
|
rules: [{ required: true, type: 'string' }], |
||||
|
}, |
||||
|
{ |
||||
|
field: 'contactsEmail', |
||||
|
component: 'Input', |
||||
|
label: '联系人邮箱', |
||||
|
colProps: { |
||||
|
span: 12, |
||||
|
}, |
||||
|
rules: [{ required: true, type: 'string' }], |
||||
|
}, |
||||
|
{ |
||||
|
field: 'contactsMobile', |
||||
|
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})$|^0\d{2,3}-?\d{7,8}$/, |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
// {
|
||||
|
// field: 'state',
|
||||
|
// component: 'Select',
|
||||
|
// defaultValue: 0,
|
||||
|
// label: '状态',
|
||||
|
// colProps: {
|
||||
|
// span: 12,
|
||||
|
// },
|
||||
|
// componentProps: {
|
||||
|
// options: stateTypeList,
|
||||
|
// disabled: true,
|
||||
|
// },
|
||||
|
// rules: [{ required: true, type: 'number' }],
|
||||
|
// },
|
||||
|
{ |
||||
|
field: 'description', |
||||
|
component: 'InputTextArea', |
||||
|
componentProps: { |
||||
|
rows: 4, |
||||
|
placeholder: '请输入问题描述', |
||||
|
showCount: true, |
||||
|
maxlength: 150, |
||||
|
}, |
||||
|
label: '问题描述', |
||||
|
colProps: { |
||||
|
span: 24, |
||||
|
}, |
||||
|
rules: [{ required: true }], |
||||
|
}, |
||||
|
|
||||
|
{ |
||||
|
label: '描述附件', |
||||
|
field: 'files', |
||||
|
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', 'jpg', 'jpeg', 'png']; |
||||
|
|
||||
|
// 检查文件类型
|
||||
|
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 }], |
||||
|
}, |
||||
|
{ |
||||
|
label: '解决方案', |
||||
|
field: 'solution', |
||||
|
colProps: { |
||||
|
span: 24, |
||||
|
}, |
||||
|
vShow: isDetail, |
||||
|
// rules: [{ required: true, type: 'array' }],
|
||||
|
slot: 'solution', |
||||
|
}, |
||||
|
] as any; |
||||
|
}; |
||||
|
|
||||
|
export const getFlowFormSchema: (row?: Partial<TableListItem>) => FormSchema[] = (record = {}) => { |
||||
|
return [ |
||||
|
{ |
||||
|
field: 'remark', |
||||
|
component: 'InputTextArea', |
||||
|
label: '文字补充内容', |
||||
|
colProps: { |
||||
|
span: 24, |
||||
|
}, |
||||
|
}, |
||||
|
]; |
||||
|
}; |
||||
Loading…
Reference in new issue