fix(personal-item): 个人事项&任务添加type类型字段
This commit is contained in:
@@ -85,12 +85,20 @@ export const RDMS_PROJECT_EXECUTION_TYPE_DICT_CODE = 'rdms_project_execution_typ
|
||||
export const OBJECT_STATUS_MODEL_OBJECT_TYPE_DICT_CODE = 'object_status_model_object_type';
|
||||
|
||||
/**
|
||||
* 工作日志完成难度字典编码
|
||||
* 工作日志难度字典编码
|
||||
*
|
||||
* 对应业务字段:任务/个人事项工作日志中的 difficulty
|
||||
* 来源口径:后端工作日志表 `rdms_task_worklog.difficulty` 字段注释明确使用字典 `rdms_worklog_difficulty`
|
||||
* 来源口径:用户明确指定任务/个人事项工作日志难度下拉来自运行时字典 rdms_task&item_worklog_difficulty
|
||||
*/
|
||||
export const RDMS_WORKLOG_DIFFICULTY_DICT_CODE = 'rdms_worklog_difficulty';
|
||||
export const RDMS_WORKLOG_DIFFICULTY_DICT_CODE = 'rdms_task&item_worklog_difficulty';
|
||||
|
||||
/**
|
||||
* 任务/个人事项类型字典编码
|
||||
*
|
||||
* 对应业务字段:任务、个人事项中的 type
|
||||
* 来源口径:用户明确指定任务/个人事项类型下拉来自运行时字典 rdms_task&item_type
|
||||
*/
|
||||
export const RDMS_TASK_ITEM_TYPE_DICT_CODE = 'rdms_task&item_type';
|
||||
|
||||
/**
|
||||
* 需求允许删除的状态字典编码
|
||||
|
||||
@@ -61,6 +61,7 @@ type PersonalItemExecutionOptionResponse = ProjectExecutionResponse & {
|
||||
type PersonalItemSaveRequest = {
|
||||
executionId?: string;
|
||||
taskTitle: string;
|
||||
type: string;
|
||||
progressRate?: number;
|
||||
plannedStartDate?: string;
|
||||
plannedEndDate?: string;
|
||||
@@ -86,7 +87,7 @@ type PersonalItemWorklogSaveRequest = {
|
||||
size?: number;
|
||||
contentType?: string;
|
||||
}>;
|
||||
difficulty?: string;
|
||||
difficulty: string;
|
||||
};
|
||||
|
||||
const PERSONAL_ITEM_PREFIX = `${WEB_SERVICE_PREFIX}/project/personal-items`;
|
||||
@@ -163,6 +164,7 @@ function normalizePersonalItem(response: PersonalItemResponse): Api.PersonalItem
|
||||
return {
|
||||
id: normalizeStringId(response.id),
|
||||
taskTitle: response.taskTitle ?? '',
|
||||
type: response.type ?? '',
|
||||
ownerId: normalizeStringId(response.ownerId),
|
||||
statusCode: response.statusCode,
|
||||
terminal: normalizeBooleanFlag(response.terminal),
|
||||
@@ -214,6 +216,7 @@ function toPersonalItemSaveRequest(data: Api.PersonalItem.SavePersonalItemParams
|
||||
return {
|
||||
executionId: data.executionId ?? undefined,
|
||||
taskTitle: data.taskTitle.trim(),
|
||||
type: data.type,
|
||||
progressRate: typeof data.progressRate === 'number' ? data.progressRate : undefined,
|
||||
plannedStartDate: data.plannedStartDate ?? undefined,
|
||||
plannedEndDate: data.plannedEndDate ?? undefined,
|
||||
@@ -246,7 +249,7 @@ function toPersonalItemWorklogSaveRequest(
|
||||
size: item.size,
|
||||
contentType: item.contentType
|
||||
})) ?? undefined,
|
||||
difficulty: data.difficulty ?? undefined
|
||||
difficulty: data.difficulty
|
||||
};
|
||||
}
|
||||
|
||||
@@ -341,6 +344,7 @@ function createSeedItems(): PersonalItemRecord[] {
|
||||
{
|
||||
id: 'personal-item-1',
|
||||
taskTitle: '整理供应商沟通纪要',
|
||||
type: 'daily',
|
||||
ownerId: CURRENT_USER_ID,
|
||||
statusCode: 'active',
|
||||
progressRate: 45,
|
||||
@@ -362,6 +366,7 @@ function createSeedItems(): PersonalItemRecord[] {
|
||||
{
|
||||
id: 'personal-item-2',
|
||||
taskTitle: '清理浏览器收藏夹里的项目入口',
|
||||
type: 'daily',
|
||||
ownerId: CURRENT_USER_ID,
|
||||
statusCode: 'pending',
|
||||
progressRate: 0,
|
||||
@@ -383,6 +388,7 @@ function createSeedItems(): PersonalItemRecord[] {
|
||||
{
|
||||
id: 'personal-item-3',
|
||||
taskTitle: '补充账号开通说明截图',
|
||||
type: 'support',
|
||||
ownerId: CURRENT_USER_ID,
|
||||
statusCode: 'completed',
|
||||
progressRate: 100,
|
||||
@@ -587,6 +593,7 @@ function syncItemFromWorklogs(itemId: string) {
|
||||
|
||||
function applySaveFields(target: PersonalItemRecord, payload: Api.PersonalItem.SavePersonalItemParams) {
|
||||
target.taskTitle = payload.taskTitle.trim();
|
||||
target.type = payload.type;
|
||||
target.ownerId = payload.ownerId || target.ownerId;
|
||||
target.ownerName = CURRENT_USER_NAME;
|
||||
target.plannedStartDate = payload.plannedStartDate;
|
||||
@@ -661,6 +668,7 @@ export async function fetchCreatePersonalItem(data: Api.PersonalItem.SavePersona
|
||||
const createdItem: PersonalItemRecord = {
|
||||
id: mapped.data,
|
||||
taskTitle: data.taskTitle.trim(),
|
||||
type: data.type,
|
||||
ownerId: data.ownerId || CURRENT_USER_ID,
|
||||
statusCode: 'pending',
|
||||
progressRate: typeof data.progressRate === 'number' ? data.progressRate : 0,
|
||||
|
||||
@@ -133,10 +133,14 @@ export type ProjectTaskResponse = Omit<
|
||||
totalSpentHours?: number | null;
|
||||
};
|
||||
|
||||
export type TaskWorklogResponse = Omit<Api.Project.TaskWorklog, 'id' | 'taskId' | 'userId' | 'attachments'> & {
|
||||
export type TaskWorklogResponse = Omit<
|
||||
Api.Project.TaskWorklog,
|
||||
'id' | 'taskId' | 'userId' | 'difficulty' | 'attachments'
|
||||
> & {
|
||||
id: StringIdResponse;
|
||||
taskId: StringIdResponse;
|
||||
userId: StringIdResponse;
|
||||
difficulty?: string | null;
|
||||
attachments?: AttachmentItemResponse[] | null;
|
||||
};
|
||||
|
||||
@@ -290,6 +294,7 @@ export function normalizeProjectTask(response: ProjectTaskResponse): Api.Project
|
||||
projectId: normalizeStringId(response.projectId),
|
||||
executionId: normalizeStringId(response.executionId),
|
||||
parentTaskId: normalizeNullableStringId(response.parentTaskId),
|
||||
type: response.type ?? '',
|
||||
ownerId: normalizeStringId(response.ownerId),
|
||||
ownerNickname: response.ownerNickname ?? null,
|
||||
statusName: response.statusName ?? null,
|
||||
@@ -322,6 +327,7 @@ export function normalizeTaskWorklog(response: TaskWorklogResponse): Api.Project
|
||||
userId: normalizeStringId(response.userId),
|
||||
userNickname: response.userNickname ?? null,
|
||||
workContent: response.workContent ?? null,
|
||||
difficulty: response.difficulty ?? '',
|
||||
attachments: normalizeAttachments(response.attachments),
|
||||
progressRate: typeof response.progressRate === 'number' ? response.progressRate : 0
|
||||
};
|
||||
|
||||
2
src/typings/api/personal-item.d.ts
vendored
2
src/typings/api/personal-item.d.ts
vendored
@@ -16,6 +16,7 @@ declare namespace Api {
|
||||
interface PersonalItem {
|
||||
id: string;
|
||||
taskTitle: string;
|
||||
type: string;
|
||||
ownerId: string;
|
||||
statusCode: PersonalItemStatusCode;
|
||||
terminal?: boolean;
|
||||
@@ -56,6 +57,7 @@ declare namespace Api {
|
||||
|
||||
interface SavePersonalItemParams {
|
||||
taskTitle: string;
|
||||
type: string;
|
||||
ownerId?: string;
|
||||
executionId?: string | null;
|
||||
progressRate?: number | null;
|
||||
|
||||
8
src/typings/api/project.d.ts
vendored
8
src/typings/api/project.d.ts
vendored
@@ -214,6 +214,7 @@ declare namespace Api {
|
||||
executionId: string;
|
||||
parentTaskId: string | null;
|
||||
taskTitle: string;
|
||||
type: string;
|
||||
ownerId: string;
|
||||
ownerNickname?: string | null;
|
||||
/** 所属执行的负责人 userId(按钮可见度公式用) */
|
||||
@@ -350,6 +351,7 @@ declare namespace Api {
|
||||
interface SaveProjectTaskParams {
|
||||
parentTaskId: string | null;
|
||||
taskTitle: string;
|
||||
type: string;
|
||||
ownerId: string | null;
|
||||
progressRate?: number;
|
||||
plannedStartDate: string | null;
|
||||
@@ -380,7 +382,8 @@ declare namespace Api {
|
||||
durationHours: number;
|
||||
/** 本次填报进度(0~100,scale=2) */
|
||||
progressRate: number;
|
||||
difficulty?: string | null;
|
||||
/** 难度,来自字典 rdms_task&item_worklog_difficulty */
|
||||
difficulty: string;
|
||||
workContent: string | null;
|
||||
attachments?: AttachmentItem[] | null;
|
||||
createTime: string;
|
||||
@@ -404,7 +407,8 @@ declare namespace Api {
|
||||
durationHours: number;
|
||||
/** 本次填报进度(0~100,scale=2,必填) */
|
||||
progressRate: number;
|
||||
difficulty?: string | null;
|
||||
/** 难度,来自字典 rdms_task&item_worklog_difficulty */
|
||||
difficulty: string;
|
||||
workContent?: string | null;
|
||||
/** 编辑语义:null 保留原值 / [] 清空 / [...] 替换 */
|
||||
attachments?: AttachmentItem[] | null;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { computed, nextTick, reactive, ref, watch } from 'vue';
|
||||
import { useResizeObserver } from '@vueuse/core';
|
||||
import dayjs from 'dayjs';
|
||||
import { RDMS_TASK_ITEM_TYPE_DICT_CODE } from '@/constants/dict';
|
||||
import { fetchCreatePersonalItem, fetchGetPersonalItemDetail, fetchUpdatePersonalItem } from '@/service/api';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
import { useForm, useFormRules } from '@/hooks/common/form';
|
||||
@@ -9,6 +10,7 @@ import BusinessAttachmentUploader from '@/components/custom/business-attachment-
|
||||
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
||||
import BusinessFormSection from '@/components/custom/business-form-section.vue';
|
||||
import BusinessRichTextEditor from '@/components/custom/business-rich-text-editor.vue';
|
||||
import DictSelect from '@/components/custom/dict-select.vue';
|
||||
import { isEmptyRichText } from './personal-item-shared';
|
||||
|
||||
defineOptions({ name: 'PersonalItemOperateDialog' });
|
||||
@@ -57,6 +59,7 @@ const submitting = ref(false);
|
||||
|
||||
interface Model {
|
||||
taskTitle: string;
|
||||
type: string;
|
||||
plannedStartDate: string | null;
|
||||
plannedEndDate: string | null;
|
||||
taskDesc: string | null;
|
||||
@@ -76,6 +79,7 @@ const title = computed(() => {
|
||||
function createDefaultModel(): Model {
|
||||
return {
|
||||
taskTitle: '',
|
||||
type: '',
|
||||
plannedStartDate: null,
|
||||
plannedEndDate: null,
|
||||
taskDesc: null,
|
||||
@@ -108,6 +112,7 @@ const rules = computed(
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
type: [createRequiredRule('请选择事项类型')],
|
||||
plannedStartDate: [createRequiredRule('请选择计划开始日期')],
|
||||
plannedEndDate: [
|
||||
createRequiredRule('请选择计划结束日期'),
|
||||
@@ -136,6 +141,7 @@ async function initModel() {
|
||||
|
||||
if (!error && data) {
|
||||
model.taskTitle = data.taskTitle;
|
||||
model.type = data.type;
|
||||
model.plannedStartDate = data.plannedStartDate;
|
||||
model.plannedEndDate = data.plannedEndDate;
|
||||
model.taskDesc = data.taskDesc;
|
||||
@@ -166,6 +172,7 @@ async function handleSubmit() {
|
||||
|
||||
const payload: Api.PersonalItem.SavePersonalItemParams = {
|
||||
taskTitle: model.taskTitle.trim(),
|
||||
type: model.type,
|
||||
ownerId: currentUserId.value,
|
||||
plannedStartDate: model.plannedStartDate,
|
||||
plannedEndDate: model.plannedEndDate,
|
||||
@@ -235,6 +242,16 @@ watch(
|
||||
/>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem label="事项类型" prop="type">
|
||||
<DictSelect
|
||||
v-model="model.type"
|
||||
:dict-code="RDMS_TASK_ITEM_TYPE_DICT_CODE"
|
||||
:clearable="!isView"
|
||||
:disabled="isView"
|
||||
placeholder="请选择事项类型"
|
||||
/>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem label="计划开始日期" prop="plannedStartDate">
|
||||
<ElDatePicker
|
||||
v-model="model.plannedStartDate"
|
||||
|
||||
@@ -162,7 +162,7 @@ const rules = computed(
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
difficulty: [createRequiredRule('请选择完成难度')],
|
||||
difficulty: [createRequiredRule('请选择难度')],
|
||||
workContent: [
|
||||
{
|
||||
required: true,
|
||||
@@ -356,7 +356,7 @@ defineExpose({
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="完成难度" prop="difficulty">
|
||||
<ElFormItem label="难度" prop="difficulty">
|
||||
<DictSelect
|
||||
v-model="model.difficulty"
|
||||
:dict-code="RDMS_WORKLOG_DIFFICULTY_DICT_CODE"
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { ElPopconfirm, ElTag, ElTooltip } from 'element-plus';
|
||||
import { ElMessageBox, ElPopconfirm, ElTag, ElTooltip } from 'element-plus';
|
||||
import dayjs from 'dayjs';
|
||||
import { Plus } from '@element-plus/icons-vue';
|
||||
import { RDMS_WORKLOG_DIFFICULTY_DICT_CODE } from '@/constants/dict';
|
||||
import {
|
||||
fetchCompletePersonalItem,
|
||||
fetchCreatePersonalItemWorklog,
|
||||
fetchDeletePersonalItemWorklog,
|
||||
fetchGetPersonalItemDetail,
|
||||
fetchGetPersonalItemWorklogPage,
|
||||
fetchUpdatePersonalItemWorklog
|
||||
} from '@/service/api';
|
||||
@@ -52,6 +54,8 @@ const currentUserName = computed(
|
||||
|
||||
const PAGE_SIZE = 10;
|
||||
const TABLE_HEIGHT = 390;
|
||||
const COMPLETED_STATUS_CODE: Api.PersonalItem.PersonalItemStatusCode = 'completed';
|
||||
const COMPLETE_ACTION_CODE = 'complete';
|
||||
|
||||
const pageNo = ref(1);
|
||||
const total = ref(0);
|
||||
@@ -189,6 +193,56 @@ async function loadRecords() {
|
||||
total.value = data.total;
|
||||
}
|
||||
|
||||
function canPromptCompleteItem(item: Api.PersonalItem.PersonalItem) {
|
||||
if (item.statusCode === COMPLETED_STATUS_CODE || item.terminal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
item.progressRate >= 100 && (item.availableActions ?? []).some(action => action.actionCode === COMPLETE_ACTION_CODE)
|
||||
);
|
||||
}
|
||||
|
||||
async function fetchLatestItem() {
|
||||
const { error, data } = await fetchGetPersonalItemDetail(props.item.id);
|
||||
|
||||
if (error || !data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async function promptCompleteItemIfNeeded() {
|
||||
const latestItem = await fetchLatestItem();
|
||||
|
||||
if (!latestItem || !canPromptCompleteItem(latestItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await ElMessageBox.confirm('事项进度已达 100%,是否完成当前事项?', '完成确认', {
|
||||
confirmButtonText: '完成事项',
|
||||
cancelButtonText: '仅保留工时',
|
||||
type: 'info'
|
||||
});
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
const { error } = await fetchCompletePersonalItem(latestItem.id);
|
||||
|
||||
if (!error) {
|
||||
window.$message?.success('个人事项已完成');
|
||||
}
|
||||
}
|
||||
|
||||
async function reloadAfterWorklogChanged() {
|
||||
await loadRecords();
|
||||
await promptCompleteItemIfNeeded();
|
||||
emit('changed');
|
||||
}
|
||||
|
||||
function handlePageChange(page: number) {
|
||||
pageNo.value = page;
|
||||
loadRecords();
|
||||
@@ -225,8 +279,7 @@ async function handleDelete(row: Api.PersonalItem.PersonalItemWorklog) {
|
||||
}
|
||||
|
||||
window.$message?.success('工作日志删除成功');
|
||||
await loadRecords();
|
||||
emit('changed');
|
||||
await reloadAfterWorklogChanged();
|
||||
}
|
||||
|
||||
async function handleSubmit(payload: Api.PersonalItem.SavePersonalItemWorklogParams) {
|
||||
@@ -249,8 +302,7 @@ async function handleSubmit(payload: Api.PersonalItem.SavePersonalItemWorklogPar
|
||||
|
||||
window.$message?.success(formMode.value === 'edit' ? '工作日志修改成功' : '工作日志新增成功');
|
||||
formVisible.value = false;
|
||||
await loadRecords();
|
||||
emit('changed');
|
||||
await reloadAfterWorklogChanged();
|
||||
} finally {
|
||||
submitting.value = false;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { RDMS_TASK_ITEM_TYPE_DICT_CODE } from '@/constants/dict';
|
||||
import BusinessAttachmentUploader from '@/components/custom/business-attachment-uploader.vue';
|
||||
import BusinessFormSection from '@/components/custom/business-form-section.vue';
|
||||
import BusinessRichTextEditor from '@/components/custom/business-rich-text-editor.vue';
|
||||
import BusinessUserSelect from '@/components/custom/business-user-select.vue';
|
||||
import DictSelect from '@/components/custom/dict-select.vue';
|
||||
|
||||
defineOptions({ name: 'ProjectExecutionTaskInfoReadonly' });
|
||||
|
||||
@@ -19,6 +21,7 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
});
|
||||
|
||||
const taskTitle = computed(() => props.task?.taskTitle ?? '');
|
||||
const taskType = computed(() => props.task?.type ?? '');
|
||||
const taskDesc = computed(() => props.task?.taskDesc ?? '');
|
||||
const ownerId = computed(() => props.task?.ownerId ?? null);
|
||||
const parentTaskId = computed(() => props.task?.parentTaskId ?? null);
|
||||
@@ -46,6 +49,9 @@ const parentTaskOptions = computed(() => {
|
||||
<ElFormItem label="任务名称">
|
||||
<ElInput :model-value="taskTitle" readonly placeholder="--" />
|
||||
</ElFormItem>
|
||||
<ElFormItem label="任务类型">
|
||||
<DictSelect :model-value="taskType" :dict-code="RDMS_TASK_ITEM_TYPE_DICT_CODE" disabled placeholder="--" />
|
||||
</ElFormItem>
|
||||
<ElFormItem label="父任务">
|
||||
<ElSelect :model-value="parentTaskId" disabled clearable filterable class="w-full" placeholder="无">
|
||||
<ElOption v-for="item in parentTaskOptions" :key="item.id" :label="item.taskTitle" :value="item.id" />
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
import { computed, nextTick, reactive, ref, watch } from 'vue';
|
||||
import { useResizeObserver } from '@vueuse/core';
|
||||
import dayjs from 'dayjs';
|
||||
import { RDMS_TASK_ITEM_TYPE_DICT_CODE } from '@/constants/dict';
|
||||
import { useForm, useFormRules } from '@/hooks/common/form';
|
||||
import BusinessAttachmentUploader from '@/components/custom/business-attachment-uploader.vue';
|
||||
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
||||
import BusinessFormSection from '@/components/custom/business-form-section.vue';
|
||||
import BusinessRichTextEditor from '@/components/custom/business-rich-text-editor.vue';
|
||||
import BusinessUserSelect from '@/components/custom/business-user-select.vue';
|
||||
import DictSelect from '@/components/custom/dict-select.vue';
|
||||
defineOptions({ name: 'ProjectExecutionTaskOperateDialog' });
|
||||
|
||||
type OperateMode = 'create' | 'edit';
|
||||
@@ -58,6 +60,7 @@ const richTextEditorRef = ref<InstanceType<typeof BusinessRichTextEditor> | null
|
||||
interface FormModel {
|
||||
parentTaskId: string | null;
|
||||
taskTitle: string;
|
||||
type: string;
|
||||
ownerId: string | null;
|
||||
plannedStartDate: string | null;
|
||||
plannedEndDate: string | null;
|
||||
@@ -69,6 +72,7 @@ interface FormModel {
|
||||
const model = reactive<FormModel>({
|
||||
parentTaskId: null,
|
||||
taskTitle: '',
|
||||
type: '',
|
||||
ownerId: null,
|
||||
plannedStartDate: null,
|
||||
plannedEndDate: null,
|
||||
@@ -120,6 +124,7 @@ const rules = computed(
|
||||
() =>
|
||||
({
|
||||
taskTitle: [createRequiredRule('请输入任务名称')],
|
||||
type: [createRequiredRule('请选择任务类型')],
|
||||
ownerId: model.parentTaskId ? [] : [createRequiredRule('请选择负责人')],
|
||||
plannedStartDate: [createRequiredRule('请选择计划开始日期')],
|
||||
plannedEndDate: [
|
||||
@@ -227,6 +232,7 @@ async function handleConfirm() {
|
||||
const payload: Api.Project.SaveProjectTaskParams = {
|
||||
parentTaskId: model.parentTaskId || null,
|
||||
taskTitle: model.taskTitle.trim(),
|
||||
type: model.type,
|
||||
ownerId: model.ownerId || null,
|
||||
plannedStartDate: model.plannedStartDate,
|
||||
plannedEndDate: model.plannedEndDate,
|
||||
@@ -254,6 +260,7 @@ function applyRowDataToModel() {
|
||||
model.parentTaskId =
|
||||
props.mode === 'create' ? (props.defaultParentTaskId ?? null) : props.rowData?.parentTaskId || null;
|
||||
model.taskTitle = props.rowData?.taskTitle || '';
|
||||
model.type = props.rowData?.type || '';
|
||||
model.ownerId = props.rowData?.ownerId || null;
|
||||
model.plannedStartDate = props.rowData?.plannedStartDate || null;
|
||||
model.plannedEndDate = props.rowData?.plannedEndDate || null;
|
||||
@@ -318,6 +325,14 @@ defineExpose({
|
||||
<ElInput v-model="model.taskTitle" maxlength="200" placeholder="请输入任务名称" />
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem label="任务类型" prop="type">
|
||||
<DictSelect
|
||||
v-model="model.type"
|
||||
:dict-code="RDMS_TASK_ITEM_TYPE_DICT_CODE"
|
||||
placeholder="请选择任务类型"
|
||||
/>
|
||||
</ElFormItem>
|
||||
|
||||
<ElFormItem label="父任务">
|
||||
<ElSelect v-model="model.parentTaskId" clearable filterable class="w-full" placeholder="请选择父任务">
|
||||
<ElOption
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, nextTick, reactive, ref, watch } from 'vue';
|
||||
import dayjs from 'dayjs';
|
||||
import { RDMS_WORKLOG_DIFFICULTY_DICT_CODE } from '@/constants/dict';
|
||||
import { fetchGetProjectTaskWorklogPage } from '@/service/api/project';
|
||||
import { useAuthStore } from '@/store/modules/auth';
|
||||
import { useForm, useFormRules } from '@/hooks/common/form';
|
||||
import BusinessAttachmentUploader from '@/components/custom/business-attachment-uploader.vue';
|
||||
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
|
||||
import DictSelect from '@/components/custom/dict-select.vue';
|
||||
|
||||
defineOptions({ name: 'ProjectExecutionTaskWorklogFormDialog' });
|
||||
|
||||
@@ -60,6 +62,7 @@ interface FormModel {
|
||||
/** 0.5 颗粒小时数 */
|
||||
durationHours: number | null;
|
||||
progressRate: number;
|
||||
difficulty: string;
|
||||
workContent: string | null;
|
||||
attachments: Api.Project.AttachmentItem[];
|
||||
}
|
||||
@@ -75,6 +78,7 @@ const model = reactive<FormModel>({
|
||||
weekDate: null,
|
||||
durationHours: null,
|
||||
progressRate: 0,
|
||||
difficulty: '2',
|
||||
workContent: null,
|
||||
attachments: []
|
||||
});
|
||||
@@ -180,6 +184,7 @@ const rules = computed(
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
difficulty: [createRequiredRule('请选择难度')],
|
||||
workContent: [
|
||||
{
|
||||
required: true,
|
||||
@@ -282,6 +287,7 @@ async function handleConfirm() {
|
||||
endDate,
|
||||
durationHours: Number(model.durationHours!.toFixed(1)),
|
||||
progressRate: Number(model.progressRate.toFixed(2)),
|
||||
difficulty: model.difficulty,
|
||||
workContent: model.workContent?.trim() || null,
|
||||
attachments: [...model.attachments]
|
||||
};
|
||||
@@ -309,6 +315,7 @@ watch(
|
||||
model.weekDate = null;
|
||||
}
|
||||
model.durationHours = typeof row.durationHours === 'number' ? row.durationHours : null;
|
||||
model.difficulty = row.difficulty || '2';
|
||||
model.workContent = row.workContent || null;
|
||||
model.attachments = row.attachments ? [...row.attachments] : [];
|
||||
} else {
|
||||
@@ -316,6 +323,7 @@ watch(
|
||||
model.workDate = dayjs().format('YYYY-MM-DD');
|
||||
model.weekDate = null;
|
||||
model.durationHours = null;
|
||||
model.difficulty = '2';
|
||||
model.workContent = null;
|
||||
model.attachments = [];
|
||||
}
|
||||
@@ -409,6 +417,16 @@ defineExpose({
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="12">
|
||||
<ElFormItem label="难度" prop="difficulty">
|
||||
<DictSelect
|
||||
v-model="model.difficulty"
|
||||
:dict-code="RDMS_WORKLOG_DIFFICULTY_DICT_CODE"
|
||||
:disabled="isView"
|
||||
:clearable="false"
|
||||
/>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="24">
|
||||
<ElFormItem label="工作内容" prop="workContent">
|
||||
<ElInput
|
||||
|
||||
Reference in New Issue
Block a user