Browse Source

feat: 工单状态修改,提交函数添加防抖

master
AaronWu 3 months ago
parent
commit
1168b0f2e3
  1. 4
      src/views/client/issue/columns.tsx
  2. 38
      src/views/client/issue/data.ts
  3. 14
      src/views/client/issue/index.vue
  4. 4
      src/views/question/issue/columns.tsx
  5. 25
      src/views/question/issue/data.ts
  6. 245
      src/views/question/issue/index.vue
  7. 171
      src/views/question/knowledge/index.vue
  8. 2
      vite.config.ts

4
src/views/client/issue/columns.tsx

@ -157,7 +157,9 @@ export const baseColumns: TableColumnItem[] = [
}, },
}, },
customRender: ({ record }) => { customRender: ({ record }) => {
const { label, color } = stateTypeList.find((e) => e.value === record.state);
const obj = stateTypeList.find((e) => e.value === record.state);
const label = obj?.label;
const color = obj?.color;
return <Tag color={color}>{label}</Tag>; return <Tag color={color}>{label}</Tag>;
}, },

38
src/views/client/issue/data.ts

@ -1,32 +1,46 @@
/*
* @Author: AaronWu 2463371514@qq.com
* @Date: 2025-04-16 14:22:07
* @LastEditors: AaronWu 2463371514@qq.com
* @LastEditTime: 2026-01-14 10:57:35
* @FilePath: /IssueSupportManage/src/views/client/issue/data.ts
* @Description: ,`customMade`, koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
export const stateTypeList: any = [ export const stateTypeList: any = [
// Init(0,"待处理"),
// Back(1,"退回"),
// Develop(2,"开发中"),
// Test(3,"测试中"),
// End(4,"结束"),
{
label: '退回',
value: -1,
color: '#2db7f5',
},
{ {
label: '待处理', label: '待处理',
value: 0, value: 0,
color: '#f50', color: '#f50',
}, },
{ {
label: '退回',
label: '开发中',
value: 1, value: 1,
color: '#2db7f5',
color: '#87d068',
}, },
{ {
label: '开发中',
label: '测试中',
value: 2, value: 2,
color: '#87d068',
color: '#108ee9',
}, },
// 待客户确认
{ {
label: '测试中',
label: '待客户确认',
value: 3, value: 3,
color: '#108ee9',
color: '#2db7f5',
}, },
{ {
label: '已解决', label: '已解决',
value: 4, value: 4,
color: '#f50',
color: '#87d068',
},
{
label: '关闭',
value: 5,
color: '#d9d9d9',
}, },
]; ];

14
src/views/client/issue/index.vue

@ -275,7 +275,10 @@
...e, ...e,
}; };
}); });
values.fileIds = values.files.filter((e) => e.id).map((e) => e.id).join(',');
values.fileIds = values.files
.filter((e) => e.id)
.map((e) => e.id)
.join(',');
} }
if (values?.fileIds === ',') { if (values?.fileIds === ',') {
values.fileIds = ''; values.fileIds = '';
@ -529,8 +532,9 @@
if (records && Array.isArray(records) && records.length) { if (records && Array.isArray(records) && records.length) {
childItem.children = (records as any).map((e) => { childItem.children = (records as any).map((e) => {
const { label, color } = stateTypeList.find((d) => d.value === e.state);
const obj = stateTypeList.find((i) => i.value === e.state);
const label = obj?.label;
const color = obj?.color;
return { return {
title: e.title, title: e.title,
key: e.id, key: e.id,
@ -567,7 +571,9 @@
if (records && Array.isArray(records) && records.length) { if (records && Array.isArray(records) && records.length) {
tree = (records as any).map((e) => { tree = (records as any).map((e) => {
const { label, color } = stateTypeList.find((d) => d.value === e.state);
const obj = stateTypeList.find((i) => i.value === e.state);
const label = obj?.label;
const color = obj?.color;
return { return {
title: e.title, title: e.title,

4
src/views/question/issue/columns.tsx

@ -242,7 +242,9 @@ export const baseColumns: TableColumnItem[] = [
}, },
}, },
customRender: ({ record }) => { customRender: ({ record }) => {
const { label, color } = stateTypeList.find((e) => e.value === record.state);
const obj = stateTypeList.find((e) => e.value === record.state);
const label = obj?.label;
const color = obj?.color;
return <Tag color={color}>{label}</Tag>; return <Tag color={color}>{label}</Tag>;
}, },

25
src/views/question/issue/data.ts

@ -1,43 +1,38 @@
export const stateTypeList: any = [ export const stateTypeList: any = [
// Init(0,"待处理"),
// Back(1,"退回"),
// Develop(2,"开发中"),
// Test(3,"测试中"),
// End(4,"结束"),
{
label: '退回',
value: -1,
color: '#2db7f5',
},
{ {
label: '待处理', label: '待处理',
value: 0, value: 0,
color: '#f50', color: '#f50',
}, },
{
label: '退回',
value: 1,
color: '#2db7f5',
},
{ {
label: '开发中', label: '开发中',
value: 2,
value: 1,
color: '#87d068', color: '#87d068',
}, },
{ {
label: '测试中', label: '测试中',
value: 3,
value: 2,
color: '#108ee9', color: '#108ee9',
}, },
// 待客户确认 // 待客户确认
{ {
label: '待客户确认', label: '待客户确认',
value: 4,
value: 3,
color: '#2db7f5', color: '#2db7f5',
}, },
{ {
label: '已解决', label: '已解决',
value: 5,
value: 4,
color: '#87d068', color: '#87d068',
}, },
{ {
label: '关闭', label: '关闭',
value: 6,
value: 5,
color: '#d9d9d9', color: '#d9d9d9',
}, },
]; ];

245
src/views/question/issue/index.vue

@ -126,6 +126,7 @@
const curRowId = ref<any>(''); const curRowId = ref<any>('');
const visible = ref(false); const visible = ref(false);
const quillEditor = ref<InstanceType<typeof QuillEditor> | null>(null); const quillEditor = ref<InstanceType<typeof QuillEditor> | null>(null);
const submitting = ref(false); //
const editorOptions = ref({ const editorOptions = ref({
theme: 'snow', theme: 'snow',
modules: { modules: {
@ -205,7 +206,11 @@
// quillImageUploadCustom(quillEditor.value); // quillImageUploadCustom(quillEditor.value);
}); });
const handleOk = async () => {
const handleOk = useDebounceFn(async () => {
if (submitting.value) {
return;
}
const values = await formRef?.validate(); const values = await formRef?.validate();
if (values) { if (values) {
console.log('values: ', values); console.log('values: ', values);
@ -214,43 +219,51 @@
message.warning('请等待附件上传完成'); message.warning('请等待附件上传完成');
return; return;
} }
values.id = curRecord.value.id;
if (values.files && Array.isArray(values.files) && values.files.length) {
values.files = values.files.map((e) => {
if (e.response) {
submitting.value = true;
try {
values.id = curRecord.value.id;
if (values.files && Array.isArray(values.files) && values.files.length) {
values.files = values.files.map((e) => {
if (e.response) {
return {
name: e.name,
url: e.response.url,
id: e.response.id,
};
}
return { return {
name: e.name,
url: e.response.url,
id: e.response.id,
...e,
}; };
}
return {
...e,
};
});
values.fileIds = values.files
.filter((e) => e.id)
.map((e) => e.id)
.join(',');
} else {
values.fileIds = '';
}
if (values?.fileIds === ',') {
values.fileIds = '';
}
if (values?.tags && Array.isArray(values.tags) && values.tags.length) {
values.tags = values.tags.join(',');
});
values.fileIds = values.files
.filter((e) => e.id)
.map((e) => e.id)
.join(',');
} else {
values.fileIds = '';
}
if (values?.fileIds === ',') {
values.fileIds = '';
}
if (values?.tags && Array.isArray(values.tags) && values.tags.length) {
values.tags = values.tags.join(',');
}
await (values.id ? updateIssue : createIssue)(values);
message.success(`${values.id ? '编辑' : '新增'}成功`);
visible.value = false;
resetFormFields();
dynamicTableInstance?.reload();
} catch (error) {
console.error('提交失败:', error);
} finally {
submitting.value = false;
} }
await (values.id ? updateIssue : createIssue)(values);
message.success(`${values.id ? '编辑' : '新增'}成功`);
visible.value = false;
resetFormFields();
dynamicTableInstance?.reload();
} }
};
}, 300);
const handleCancel = () => { const handleCancel = () => {
visible.value = false; visible.value = false;
@ -311,17 +324,17 @@
handleEdit(record); handleEdit(record);
}, },
}, },
{
icon: 'init',
size: '15',
title: '处理',
label: '处理',
ifShow: stateText === '退回',
onClick: (e) => {
e.stopPropagation();
changeState(record, 0);
},
},
// {
// icon: 'init',
// size: '15',
// title: '',
// label: '',
// ifShow: stateText === '退',
// onClick: (e) => {
// e.stopPropagation();
// changeState(record, 0);
// },
// },
{ {
icon: 'dev', icon: 'dev',
size: '15', size: '15',
@ -330,7 +343,7 @@
ifShow: stateText === '待处理', ifShow: stateText === '待处理',
onClick: (e) => { onClick: (e) => {
e.stopPropagation(); e.stopPropagation();
changeState(record, 2);
changeState(record, 1);
}, },
}, },
{ {
@ -338,10 +351,10 @@
size: '20', size: '20',
title: '退回', title: '退回',
label: '退回', label: '退回',
ifShow: stateText === '开发中' || stateText === '测试中',
ifShow: stateText !== '待处理' && stateText !== '关闭',
onClick: (e) => { onClick: (e) => {
e.stopPropagation(); e.stopPropagation();
changeState(record, 1);
changeState(record, record.state - 1);
}, },
}, },
{ {
@ -352,7 +365,7 @@
ifShow: stateText === '开发中', ifShow: stateText === '开发中',
onClick: (e) => { onClick: (e) => {
e.stopPropagation(); e.stopPropagation();
changeState(record, 3);
changeState(record, 2);
}, },
}, },
// 4 // 4
@ -364,7 +377,7 @@
ifShow: stateText === '测试中', ifShow: stateText === '测试中',
onClick: (e) => { onClick: (e) => {
e.stopPropagation(); e.stopPropagation();
changeState(record, 4);
changeState(record, 3);
}, },
}, },
{ {
@ -375,7 +388,7 @@
ifShow: stateText === '待客户确认', ifShow: stateText === '待客户确认',
onClick: (e) => { onClick: (e) => {
e.stopPropagation(); e.stopPropagation();
changeState(record, 5);
changeState(record, 4);
}, },
}, },
{ {
@ -397,7 +410,7 @@
ifShow: stateText !== '关闭', ifShow: stateText !== '关闭',
onClick: (e) => { onClick: (e) => {
e.stopPropagation(); e.stopPropagation();
changeState(record, 6);
changeState(record, 5);
}, },
}, },
{ {
@ -425,44 +438,62 @@
/** /**
* @description 打开问题工单弹窗 * @description 打开问题工单弹窗
*/ */
//
const createSubmitHandler = (record: Partial<TableListItem>, isModal = false) => {
let isSubmitting = false;
return useDebounceFn(async (values: any) => {
if (isSubmitting) {
return;
}
isSubmitting = true;
try {
console.log('新增/编辑问题工单', values);
values.id = record.id;
if (values.files && Array.isArray(values.files) && values.files.length) {
values.files = values.files.map((e) => {
if (e.response) {
return {
name: e.name,
url: e.response.url,
id: e.response.id,
};
}
return {
...e,
};
});
values.fileIds = values.files
.filter((e) => e.id)
.map((e) => e.id)
.join(',');
} else {
values.fileIds = '';
}
if (values?.tags && Array.isArray(values.tags) && values.tags.length) {
values.tags = values.tags.join(',');
}
await (record.id ? updateIssue : createIssue)(values);
message.success(`${record.id ? '编辑' : '新增'}成功`);
dynamicTableInstance?.reload();
} catch (error) {
console.error('提交失败:', error);
} finally {
isSubmitting = false;
}
}, 300);
};
const openIssueModal = async (record: Partial<TableListItem> = {}, isReadOnly = false) => { const openIssueModal = async (record: Partial<TableListItem> = {}, isReadOnly = false) => {
const handleSubmit = createSubmitHandler(record);
const [formRef] = await showModal<any>({ const [formRef] = await showModal<any>({
modalProps: { modalProps: {
title: `${isReadOnly ? '查看' : record.id ? '编辑' : '新增'}问题工单`, title: `${isReadOnly ? '查看' : record.id ? '编辑' : '新增'}问题工单`,
width: 700, width: 700,
onFinish: async (values) => {
console.log('新增/编辑问题工单', values);
values.id = record.id;
if (values.files && Array.isArray(values.files) && values.files.length) {
values.files = values.files.map((e) => {
if (e.response) {
return {
name: e.name,
url: e.response.url,
id: e.response.id,
};
}
return {
...e,
};
});
values.fileIds = values.files
.filter((e) => e.id)
.map((e) => e.id)
.join(',');
} else {
values.fileIds = '';
}
if (values?.tags && Array.isArray(values.tags) && values.tags.length) {
values.tags = values.tags.join(',');
}
await (record.id ? updateIssue : createIssue)(values);
message.success(`${record.id ? '编辑' : '新增'}成功`);
dynamicTableInstance?.reload();
},
onFinish: handleSubmit,
footer: isReadOnly ? null : undefined, footer: isReadOnly ? null : undefined,
}, },
formProps: { formProps: {
@ -499,26 +530,40 @@
const openFlowModal = async (record: Partial<TableListItem> = {}, state) => { const openFlowModal = async (record: Partial<TableListItem> = {}, state) => {
const flowTitle = stateTypeList.find((item) => item.value === state)?.label; const flowTitle = stateTypeList.find((item) => item.value === state)?.label;
let isFlowSubmitting = false;
const handleFlowSubmit = useDebounceFn(async (values: any) => {
if (isFlowSubmitting) {
return;
}
isFlowSubmitting = true;
try {
await updateIssueState({
id: record.id,
state: state,
...values,
});
message.success(`操作成功`);
dynamicTableInstance?.reload();
//
if (curRowId.value === record.id) {
curRowId.value = '';
nextTick(() => {
curRowId.value = record.id;
});
}
} catch (error) {
console.error('提交失败:', error);
} finally {
isFlowSubmitting = false;
}
}, 300);
const [formRef] = await showFlowModal<any>({ const [formRef] = await showFlowModal<any>({
modalProps: { modalProps: {
title: `${flowTitle}问题工单`, title: `${flowTitle}问题工单`,
width: 700, width: 700,
onFinish: async (values) => {
await updateIssueState({
id: record.id,
state: state,
...values,
});
message.success(`操作成功`);
dynamicTableInstance?.reload();
//
if (curRowId.value === record.id) {
curRowId.value = '';
nextTick(() => {
curRowId.value = record.id;
});
}
},
onFinish: handleFlowSubmit,
}, },
formProps: { formProps: {
labelWidth: 100, labelWidth: 100,

171
src/views/question/knowledge/index.vue

@ -98,6 +98,7 @@
import { createDictValue } from '@/api/dict'; import { createDictValue } from '@/api/dict';
import { DictEnum } from '@/enums/dictEnum'; import { DictEnum } from '@/enums/dictEnum';
import { getDictionaryByTypeName } from '@/utils/dict'; import { getDictionaryByTypeName } from '@/utils/dict';
import { useDebounceFn } from '@vueuse/core';
defineOptions({ defineOptions({
name: 'knowledge', name: 'knowledge',
}); });
@ -106,6 +107,7 @@
const curRecord = ref<Partial<TableListItem>>({}); const curRecord = ref<Partial<TableListItem>>({});
const visible = ref(false); const visible = ref(false);
const submitting = ref(false); //
const quillEditor = ref<InstanceType<typeof QuillEditor> | null>(null); const quillEditor = ref<InstanceType<typeof QuillEditor> | null>(null);
@ -170,7 +172,11 @@
// quillImageUploadCustom(quillEditor.value); // quillImageUploadCustom(quillEditor.value);
}); });
const handleOk = async () => {
const handleOk = useDebounceFn(async () => {
if (submitting.value) {
return;
}
const values = await formRef?.validate(); const values = await formRef?.validate();
if (values) { if (values) {
console.log('values: ', values); console.log('values: ', values);
@ -179,57 +185,65 @@
message.warning('请等待附件上传完成'); message.warning('请等待附件上传完成');
return; return;
} }
values.id = curRecord.value.id;
if (values.files && Array.isArray(values.files) && values.files.length) {
values.files = values.files.map((e) => {
if (e.response) {
submitting.value = true;
try {
values.id = curRecord.value.id;
if (values.files && Array.isArray(values.files) && values.files.length) {
values.files = values.files.map((e) => {
if (e.response) {
return {
name: e.name,
url: e.response.url,
id: e.response.id,
};
}
return { return {
name: e.name,
url: e.response.url,
id: e.response.id,
...e,
}; };
}
return {
...e,
};
});
values.fileIds = values.files
.filter((e) => e.id)
.map((e) => e.id)
.join(',');
} else {
values.fileIds = '';
}
});
values.fileIds = values.files
.filter((e) => e.id)
.map((e) => e.id)
.join(',');
} else {
values.fileIds = '';
}
if (values?.fileIds === ',') {
values.fileIds = '';
}
if (values?.fileIds === ',') {
values.fileIds = '';
}
if (values?.tags && Array.isArray(values.tags) && values.tags.length) {
const allTags = (await getDictionaryByTypeName(DictEnum.TAG_TYPE)) || [];
// values.tagsallTags
const notInTags = values.tags.filter((tag) => {
return !allTags.some((e) => e.value === tag);
});
console.log('notInTags: ', notInTags);
for (const tag of notInTags) {
await createDictValue({
dictValue: tag,
typeId: 33,
enable: 1,
if (values?.tags && Array.isArray(values.tags) && values.tags.length) {
const allTags = (await getDictionaryByTypeName(DictEnum.TAG_TYPE)) || [];
// values.tagsallTags
const notInTags = values.tags.filter((tag) => {
return !allTags.some((e) => e.value === tag);
}); });
console.log('notInTags: ', notInTags);
for (const tag of notInTags) {
await createDictValue({
dictValue: tag,
typeId: 33,
enable: 1,
});
}
values.tags = values.tags.join(',');
} }
values.tags = values.tags.join(',');
}
await (values.id ? updateKnowledgeBase : createKnowledgeBase)(values);
message.success(`${values.id ? '编辑' : '新增'}成功`);
visible.value = false;
resetFormFields();
dynamicTableInstance?.reload();
await (values.id ? updateKnowledgeBase : createKnowledgeBase)(values);
message.success(`${values.id ? '编辑' : '新增'}成功`);
visible.value = false;
resetFormFields();
dynamicTableInstance?.reload();
} catch (error) {
console.error('提交失败:', error);
} finally {
submitting.value = false;
}
} }
};
}, 300);
const handleCancel = () => { const handleCancel = () => {
visible.value = false; visible.value = false;
@ -283,39 +297,52 @@
record: Partial<TableListItem> = {}, record: Partial<TableListItem> = {},
isReadOnly = false, isReadOnly = false,
) => { ) => {
let isModalSubmitting = false;
const handleModalSubmit = useDebounceFn(async (values: any) => {
if (isModalSubmitting) {
return;
}
isModalSubmitting = true;
try {
console.log('新增/编辑知识库', values);
values.id = record.id;
if (values.files && Array.isArray(values.files) && values.files.length) {
values.files = values.files.map((e) => {
if (e.response) {
return {
name: e.name,
url: e.response.url,
id: e.response.id,
};
}
return {
...e,
};
});
values.fileIds = values.files
.filter((e) => e.id)
.map((e) => e.id)
.join(',');
} else {
values.fileIds = '';
}
await (record.id ? updateKnowledgeBase : createKnowledgeBase)(values);
message.success(`${record.id ? '编辑' : '新增'}成功`);
dynamicTableInstance?.reload();
} catch (error) {
console.error('提交失败:', error);
} finally {
isModalSubmitting = false;
}
}, 300);
const [formRef] = await showModal<any>({ const [formRef] = await showModal<any>({
modalProps: { modalProps: {
title: `${isReadOnly ? '查看' : record.id ? '编辑' : '新增'}知识库`, title: `${isReadOnly ? '查看' : record.id ? '编辑' : '新增'}知识库`,
width: 700, width: 700,
onFinish: async (values) => {
console.log('新增/编辑知识库', values);
values.id = record.id;
if (values.files && Array.isArray(values.files) && values.files.length) {
values.files = values.files.map((e) => {
if (e.response) {
return {
name: e.name,
url: e.response.url,
id: e.response.id,
};
}
return {
...e,
};
});
values.fileIds = values.files
.filter((e) => e.id)
.map((e) => e.id)
.join(',');
} else {
values.fileIds = '';
}
await (record.id ? updateKnowledgeBase : createKnowledgeBase)(values);
message.success(`${record.id ? '编辑' : '新增'}成功`);
dynamicTableInstance?.reload();
},
onFinish: handleModalSubmit,
footer: isReadOnly ? null : undefined, footer: isReadOnly ? null : undefined,
}, },
formProps: { formProps: {

2
vite.config.ts

@ -126,7 +126,7 @@ export default defineConfig({
// }, // },
'/server': { '/server': {
target: 'http://43.137.2.78:8085', target: 'http://43.137.2.78:8085',
// target: 'http://192.168.2.22:8089',
// target: 'http://192.168.2.27:8089',
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/server/, '/server'), rewrite: (path) => path.replace(/^\/server/, '/server'),
}, },

Loading…
Cancel
Save