修复发布任务失败问题并添加编码自动生成功能
1. 修复task表approval_status字段长度问题(VARCHAR(20)->VARCHAR(50)) 2. 为品牌、平台、类目、任务子类型添加自动生成编码功能 3. 优化编码输入体验,添加自动生成按钮
This commit is contained in:
parent
e3ff05e2b5
commit
e978a7cdb1
36
database/fix_task_approval_status_length.sql
Normal file
36
database/fix_task_approval_status_length.sql
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
-- 修复 task 表的 approval_status 字段长度问题
|
||||||
|
-- 问题:approval_status 字段长度为 VARCHAR(20),但实际值 'pending_demand_approval' 有 23 个字符
|
||||||
|
-- 错误:Data truncation: Data too long for column 'approval_status'
|
||||||
|
-- 解决:将字段长度扩大到 VARCHAR(50)
|
||||||
|
-- 日期:2026-01-02
|
||||||
|
|
||||||
|
USE designhub;
|
||||||
|
|
||||||
|
-- 修改 approval_status 字段长度
|
||||||
|
ALTER TABLE `task`
|
||||||
|
MODIFY COLUMN `approval_status` VARCHAR(50) DEFAULT 'draft'
|
||||||
|
COMMENT '审批状态:draft-草稿,pending_demand_approval-待需求部门审批,pending_receiving_approval-待接单部门审批,approved-已通过,rejected-已拒绝';
|
||||||
|
|
||||||
|
-- 验证修改结果
|
||||||
|
SELECT
|
||||||
|
COLUMN_NAME,
|
||||||
|
COLUMN_TYPE,
|
||||||
|
COLUMN_DEFAULT,
|
||||||
|
COLUMN_COMMENT
|
||||||
|
FROM
|
||||||
|
INFORMATION_SCHEMA.COLUMNS
|
||||||
|
WHERE
|
||||||
|
TABLE_SCHEMA = 'designhub'
|
||||||
|
AND TABLE_NAME = 'task'
|
||||||
|
AND COLUMN_NAME = 'approval_status';
|
||||||
|
|
||||||
|
-- 说明:
|
||||||
|
-- 审批状态值说明:
|
||||||
|
-- 1. draft - 草稿(默认值)
|
||||||
|
-- 2. pending_demand_approval - 待需求部门负责人审批(23字符)
|
||||||
|
-- 3. pending_receiving_approval - 待接单部门主管审批(28字符)
|
||||||
|
-- 4. approved - 已通过
|
||||||
|
-- 5. rejected - 已拒绝
|
||||||
|
--
|
||||||
|
-- VARCHAR(50) 足以容纳所有可能的状态值
|
||||||
|
|
||||||
1
frontend/src/types/components.d.ts
vendored
1
frontend/src/types/components.d.ts
vendored
@ -11,6 +11,7 @@ declare module 'vue' {
|
|||||||
ABadge: typeof import('ant-design-vue/es')['Badge']
|
ABadge: typeof import('ant-design-vue/es')['Badge']
|
||||||
AButton: typeof import('ant-design-vue/es')['Button']
|
AButton: typeof import('ant-design-vue/es')['Button']
|
||||||
ACalendar: typeof import('ant-design-vue/es')['Calendar']
|
ACalendar: typeof import('ant-design-vue/es')['Calendar']
|
||||||
|
ACard: typeof import('ant-design-vue/es')['Card']
|
||||||
ACheckbox: typeof import('ant-design-vue/es')['Checkbox']
|
ACheckbox: typeof import('ant-design-vue/es')['Checkbox']
|
||||||
ACheckboxGroup: typeof import('ant-design-vue/es')['CheckboxGroup']
|
ACheckboxGroup: typeof import('ant-design-vue/es')['CheckboxGroup']
|
||||||
ACol: typeof import('ant-design-vue/es')['Col']
|
ACol: typeof import('ant-design-vue/es')['Col']
|
||||||
|
|||||||
@ -958,7 +958,13 @@
|
|||||||
<a-input v-model:value="formData.taskSubType.name" placeholder="请输入子类型名称(如:新品、优化)" />
|
<a-input v-model:value="formData.taskSubType.name" placeholder="请输入子类型名称(如:新品、优化)" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="子类型编码" required>
|
<a-form-item label="子类型编码" required>
|
||||||
<a-input v-model:value="formData.taskSubType.code" placeholder="请输入子类型编码(如:new_product)" />
|
<a-input v-model:value="formData.taskSubType.code" placeholder="留空自动生成">
|
||||||
|
<template #addonAfter>
|
||||||
|
<a-button size="small" type="link" @click="autoGenerateTaskSubTypeCode" style="padding: 0 8px;">
|
||||||
|
自动生成
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="描述">
|
<a-form-item label="描述">
|
||||||
<a-textarea v-model:value="formData.taskSubType.description" :rows="3" placeholder="请输入描述" />
|
<a-textarea v-model:value="formData.taskSubType.description" :rows="3" placeholder="请输入描述" />
|
||||||
@ -987,7 +993,13 @@
|
|||||||
<a-input v-model:value="formData.brand.name" placeholder="请输入品牌名称" />
|
<a-input v-model:value="formData.brand.name" placeholder="请输入品牌名称" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="品牌编码">
|
<a-form-item label="品牌编码">
|
||||||
<a-input v-model:value="formData.brand.brandCode" placeholder="请输入品牌编码" />
|
<a-input v-model:value="formData.brand.brandCode" placeholder="留空自动生成">
|
||||||
|
<template #addonAfter>
|
||||||
|
<a-button size="small" type="link" @click="autoGenerateBrandCode" style="padding: 0 8px;">
|
||||||
|
自动生成
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="品牌描述">
|
<a-form-item label="品牌描述">
|
||||||
<a-textarea v-model:value="formData.brand.description" :rows="3" placeholder="请输入描述" />
|
<a-textarea v-model:value="formData.brand.description" :rows="3" placeholder="请输入描述" />
|
||||||
@ -1015,7 +1027,13 @@
|
|||||||
<a-input v-model:value="formData.platform.name" placeholder="请输入平台名称" />
|
<a-input v-model:value="formData.platform.name" placeholder="请输入平台名称" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="平台编码">
|
<a-form-item label="平台编码">
|
||||||
<a-input v-model:value="formData.platform.platformCode" placeholder="请输入平台编码" />
|
<a-input v-model:value="formData.platform.platformCode" placeholder="留空自动生成">
|
||||||
|
<template #addonAfter>
|
||||||
|
<a-button size="small" type="link" @click="autoGeneratePlatformCode" style="padding: 0 8px;">
|
||||||
|
自动生成
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="平台描述">
|
<a-form-item label="平台描述">
|
||||||
<a-textarea v-model:value="formData.platform.description" :rows="3" placeholder="请输入描述" />
|
<a-textarea v-model:value="formData.platform.description" :rows="3" placeholder="请输入描述" />
|
||||||
@ -1043,7 +1061,13 @@
|
|||||||
<a-input v-model:value="formData.category.name" placeholder="请输入类目名称" />
|
<a-input v-model:value="formData.category.name" placeholder="请输入类目名称" />
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="类目编码">
|
<a-form-item label="类目编码">
|
||||||
<a-input v-model:value="formData.category.categoryCode" placeholder="请输入类目编码" />
|
<a-input v-model:value="formData.category.categoryCode" placeholder="留空自动生成">
|
||||||
|
<template #addonAfter>
|
||||||
|
<a-button size="small" type="link" @click="autoGenerateCategoryCode" style="padding: 0 8px;">
|
||||||
|
自动生成
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="类目描述">
|
<a-form-item label="类目描述">
|
||||||
<a-textarea v-model:value="formData.category.description" :rows="3" placeholder="请输入描述" />
|
<a-textarea v-model:value="formData.category.description" :rows="3" placeholder="请输入描述" />
|
||||||
@ -1881,6 +1905,82 @@ const handleScoreAdjust = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 自动生成编码的辅助函数
|
||||||
|
const generateCode = (name: string, prefix: string = ''): string => {
|
||||||
|
if (!name) return ''
|
||||||
|
|
||||||
|
// 移除特殊字符,只保留字母、数字和汉字
|
||||||
|
const cleanName = name.replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, '')
|
||||||
|
|
||||||
|
let code = ''
|
||||||
|
|
||||||
|
// 尝试提取英文字母
|
||||||
|
const englishChars = cleanName.match(/[a-zA-Z]+/g)
|
||||||
|
if (englishChars && englishChars.length > 0) {
|
||||||
|
code = englishChars.join('').toUpperCase().substring(0, 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有英文字母,使用时间戳后6位
|
||||||
|
if (!code) {
|
||||||
|
code = 'CODE' + Date.now().toString().slice(-6)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加前缀
|
||||||
|
if (prefix) {
|
||||||
|
code = prefix.toUpperCase() + '_' + code
|
||||||
|
}
|
||||||
|
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动生成品牌编码
|
||||||
|
const autoGenerateBrandCode = () => {
|
||||||
|
if (!formData.brand.name) {
|
||||||
|
message.warning('请先输入品牌名称')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
formData.brand.brandCode = generateCode(formData.brand.name, 'BR')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动生成平台编码
|
||||||
|
const autoGeneratePlatformCode = () => {
|
||||||
|
if (!formData.platform.name) {
|
||||||
|
message.warning('请先输入平台名称')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
formData.platform.platformCode = generateCode(formData.platform.name, 'PF')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动生成类目编码
|
||||||
|
const autoGenerateCategoryCode = () => {
|
||||||
|
if (!formData.category.name) {
|
||||||
|
message.warning('请先输入类目名称')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
formData.category.categoryCode = generateCode(formData.category.name, 'CAT')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动生成任务子类型编码
|
||||||
|
const autoGenerateTaskSubTypeCode = () => {
|
||||||
|
if (!formData.taskSubType.name) {
|
||||||
|
message.warning('请先输入子类型名称')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 任务子类型编码使用小写加下划线格式
|
||||||
|
let code = formData.taskSubType.name
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[^\u4e00-\u9fa5a-zA-Z0-9]/g, '_')
|
||||||
|
.replace(/_{2,}/g, '_')
|
||||||
|
.replace(/^_|_$/g, '')
|
||||||
|
|
||||||
|
// 如果是中文,简化处理
|
||||||
|
if (/[\u4e00-\u9fa5]/.test(code)) {
|
||||||
|
code = 'subtype_' + Date.now().toString().slice(-6)
|
||||||
|
}
|
||||||
|
|
||||||
|
formData.taskSubType.code = code
|
||||||
|
}
|
||||||
|
|
||||||
// 显示弹窗
|
// 显示弹窗
|
||||||
const showDemandTypeModal = async (item?: DemandType) => {
|
const showDemandTypeModal = async (item?: DemandType) => {
|
||||||
editingItem.value = item
|
editingItem.value = item
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user