feat(产品需求、项目需求): 支持手动录入"来源业务编号",前端的sourceBizId改为sourceBizCode,也支持按"来源业务编号"搜索。

This commit is contained in:
dk
2026-06-15 11:30:07 +08:00
parent 3c1cf6c7fa
commit 622d8d5a4d
12 changed files with 155 additions and 105 deletions

View File

@@ -7,8 +7,7 @@ import dayjs from 'dayjs';
import {
RDMS_REQ_CAN_DELETE_STATUS_DICT_CODE,
RDMS_REQ_CATEGORY_DICT_CODE,
RDMS_REQ_PRIORITY_DICT_CODE,
RDMS_REQ_SOURCE_TYPE_DICT_CODE
RDMS_REQ_PRIORITY_DICT_CODE
} from '@/constants/dict';
import { getStatusTagType } from '@/constants/status-tag';
import {
@@ -25,7 +24,6 @@ import {
import { useAuth } from '@/hooks/business/auth';
import { useDict } from '@/hooks/business/dict';
import DictTag from '@/components/custom/dict-tag.vue';
import DictText from '@/components/custom/dict-text.vue';
import { useCurrentProduct } from '../shared/use-current-product';
import {
ACTION_ICON_MAP,
@@ -181,7 +179,7 @@ const searchParams = reactive({
priority: undefined as Api.Product.RequirementPriority | undefined,
statusCode: undefined as Api.Product.RequirementStatusCode | undefined,
currentHandlerUserId: undefined as string | undefined,
sourceType: undefined as Api.Product.RequirementSourceType | undefined
sourceBizCode: undefined as string | undefined
});
const createVisible = ref(false);
@@ -384,15 +382,15 @@ const columns = computed(() => [
minWidth: 80,
formatter: (row: Api.Product.Requirement) => row.category
},
{
prop: 'sourceType',
label: '需求来源',
minWidth: 80,
align: 'center',
formatter: (row: Api.Product.Requirement) => (
<DictText dictCode={RDMS_REQ_SOURCE_TYPE_DICT_CODE} value={row.sourceType} />
)
},
// {
// prop: 'sourceType',
// label: '需求来源',
// minWidth: 80,
// align: 'center',
// formatter: (row: Api.Product.Requirement) => (
// <DictText dictCode={RDMS_REQ_SOURCE_TYPE_DICT_CODE} value={row.sourceType} />
// )
// },
// {
// prop: 'description',
// label: '内容',
@@ -415,19 +413,15 @@ const columns = computed(() => [
formatter: (row: Api.Product.Requirement) => getMemberLabel(row.currentHandlerUserId)
},
{
prop: 'sourceBizId',
prop: 'sourceBizCode',
label: '来源业务编号',
minWidth: 140,
formatter: (row: Api.Product.Requirement) => {
if (!row.sourceBizId || row.sourceType === 'manual') {
if (!row.sourceBizCode) {
return '--';
}
return (
<ElButton link type="primary" class="requirement-source-link">
{row.sourceBizId}
</ElButton>
);
return row.sourceBizCode;
}
},
{
@@ -649,7 +643,7 @@ async function loadTreeData() {
priority: searchParams.priority,
statusCode: searchParams.statusCode,
currentHandlerUserId: searchParams.currentHandlerUserId,
sourceType: searchParams.sourceType
sourceBizCode: searchParams.sourceBizCode?.trim() || undefined
});
if (error || !data) {
@@ -705,7 +699,7 @@ function handleResetSearch() {
searchParams.priority = undefined;
searchParams.statusCode = undefined;
searchParams.currentHandlerUserId = undefined;
searchParams.sourceType = undefined;
searchParams.sourceBizCode = undefined;
pagination.pageNo = 1;
reloadTable();
}
@@ -1057,10 +1051,6 @@ onMounted(async () => {
opacity: 0.6;
}
:deep(.requirement-source-link) {
padding: 0;
}
:deep(.el-table__row[class*='el-table__row--level-']:not(.el-table__row--level-0) td:first-child .cell) {
color: transparent;
}

View File

@@ -74,6 +74,7 @@ interface Model {
moduleId: string | null;
category: string;
priority: string | null;
sourceBizCode: string;
expectedTime: string | null;
proposerId: string;
currentHandlerUserId: string;
@@ -139,6 +140,7 @@ function createDefaultModel(): Model {
moduleId: props.defaultModuleId || null,
category: '功能需求',
priority: '3',
sourceBizCode: '',
expectedTime: null,
proposerId: '',
currentHandlerUserId: '',
@@ -186,6 +188,7 @@ async function handleSubmit() {
attachments: [...model.value.attachments],
category: model.value.category,
priority: Number(model.value.priority) as Api.Product.RequirementPriority,
sourceBizCode: model.value.sourceBizCode.trim() || null,
expectedTime: model.value.expectedTime,
proposerId: model.value.proposerId,
proposerNickname,
@@ -315,6 +318,10 @@ watch(
/>
</ElFormItem>
<ElFormItem label="来源业务编号">
<ElInput v-model="model.sourceBizCode" clearable maxlength="128" placeholder="请输入来源业务编号" />
</ElFormItem>
<ElFormItem label="提出人" prop="proposerId">
<ElSelect v-model="model.proposerId" class="w-full" filterable placeholder="请选择提出人">
<ElOption v-for="item in allUserOptions" :key="item.id" :label="item.nickname" :value="item.id" />

View File

@@ -64,6 +64,7 @@ interface Model {
moduleId: string | null;
category: string;
priority: string | null;
sourceBizCode: string;
expectedTime: string | null;
proposerId: string;
proposerNickname: string;
@@ -201,6 +202,7 @@ function createDefaultModel(): Model {
moduleId: null,
category: '',
priority: '3',
sourceBizCode: '',
expectedTime: null,
proposerId: '',
proposerNickname: '',
@@ -252,6 +254,7 @@ async function handleSubmit() {
attachments: [...model.value.attachments],
category: model.value.category,
priority: Number(model.value.priority) as Api.Product.RequirementPriority,
sourceBizCode: model.value.sourceBizCode.trim() || null,
expectedTime: model.value.expectedTime,
proposerId: model.value.proposerId,
proposerNickname: model.value.proposerNickname,
@@ -317,6 +320,7 @@ function transformRequirementData(data: Api.Product.Requirement): typeof model.v
moduleId: data.moduleId || null,
category: data.category || '',
priority: data.priority === null || data.priority === undefined ? null : String(data.priority),
sourceBizCode: data.sourceBizCode || '',
expectedTime: formatExpectedTime(data.expectedTime),
proposerId: data.proposerId || '',
proposerNickname: data.proposerNickname || '',
@@ -446,6 +450,17 @@ watch(
<ReadonlyField :value="getCategoryLabel(model.category) || '--'" />
</ElFormItem>
<ElFormItem label="来源业务编号">
<ReadonlyField v-if="isViewMode" :value="model.sourceBizCode || '--'" />
<ElInput
v-else
v-model="model.sourceBizCode"
clearable
maxlength="128"
placeholder="请输入来源业务编号"
/>
</ElFormItem>
<ElFormItem label="提出人" prop="proposerId">
<ReadonlyField :value="allUserLabelMap.get(model.proposerId) || '--'" />
</ElFormItem>

View File

@@ -1,8 +1,8 @@
<script setup lang="ts">
import { computed, h, onMounted, ref } from 'vue';
import { RDMS_REQ_SOURCE_TYPE_DICT_CODE } from '@/constants/dict';
// import { RDMS_REQ_SOURCE_TYPE_DICT_CODE } from '@/constants/dict';
import { fetchGetRequirementStatusDict } from '@/service/api';
import { useDict } from '@/hooks/business/dict';
// import { useDict } from '@/hooks/business/dict';
import TableSearchFields from '@/components/custom/table-search-fields.vue';
import MemberSelectOption from './member-select-option.vue';
@@ -32,17 +32,15 @@ const emit = defineEmits<Emits>();
const model = defineModel<Api.Product.RequirementSearchParams>('model', { required: true });
const requirementStatusOptions = ref<Array<{ label: string; value: string }>>([]);
const { enabledDictData: sourceTypeDictData } = useDict(RDMS_REQ_SOURCE_TYPE_DICT_CODE);
const sourceTypeOptions = computed(() => {
return sourceTypeDictData.value
.filter(item => item.value !== 'product_requirement')
.map(item => ({
label: item.label,
value: item.value
}));
});
// const { enabledDictData: sourceTypeDictData } = useDict(RDMS_REQ_SOURCE_TYPE_DICT_CODE);
// const sourceTypeOptions = computed(() => {
// return sourceTypeDictData.value
// .filter(item => item.value !== 'product_requirement')
// .map(item => ({
// label: item.label,
// value: item.value
// }));
// });
const memberSelectOptions = computed(() => {
return props.memberOptions.map(item => ({
@@ -105,12 +103,18 @@ const fields = computed(() => [
dictCode: props.categoryDictCode,
placeholder: '筛选需求类型'
},
// {
// key: 'sourceType',
// label: '需求来源',
// type: 'select' as const,
// placeholder: '筛选需求来源',
// options: sourceTypeOptions.value
// },
{
key: 'sourceType',
label: '需求来源',
type: 'select' as const,
placeholder: '筛选需求来源',
options: sourceTypeOptions.value
key: 'sourceBizCode',
label: '业务编号',
type: 'input' as const,
placeholder: '输入来源业务编号'
},
{
key: 'currentHandlerUserId',