数据字典集中治理

This commit is contained in:
Cheng Zhou
2025-12-17 20:58:42 +08:00
parent c2328594b0
commit b0bffbc75e
16 changed files with 170 additions and 39 deletions
+4 -3
View File
@@ -62,8 +62,9 @@ import CommentList from "../components/CommentList.vue";
import AttachmentList from "../components/attachments/AttachmentList.vue";
import PermissionAction from "../components/PermissionAction.vue";
import { usePermission } from "../utils/permission";
import { aeMachine, getAvailableActions, getStateColor, getStateLabel } from "../state-machine";
import { aeMachine, getAvailableActions } from "../state-machine";
import type { ActionConfig } from "../state-machine";
import { statusDict, getDictColor, getDictLabel } from "../dictionaries";
const route = useRoute();
const study = useStudyStore();
@@ -75,8 +76,8 @@ const studyId = computed(() => study.currentStudy?.id || "");
const { can } = usePermission();
const aeState = computed(() => (ae.value?.status as string) || "NEW");
const availableActions = computed(() => getAvailableActions(aeMachine, aeState.value));
const stateLabel = (v?: string | null) => getStateLabel(aeMachine, v);
const stateColor = (v?: string | null) => getStateColor(aeMachine, v) || "info";
const stateLabel = (v?: string | null) => getDictLabel(statusDict, v || "");
const stateColor = (v?: string | null) => getDictColor(statusDict, v || "") || "info";
const enrichOverdue = (item: any) => {
if (!item) return item;
+4 -3
View File
@@ -53,7 +53,8 @@ import { fetchFinanceItem } from "../api/finance";
import { useStudyStore } from "../store/study";
import { useAuthStore } from "../store/auth";
import { usePermission } from "../utils/permission";
import { financeMachine, getAvailableActions, getStateColor, getStateLabel } from "../state-machine";
import { financeMachine, getAvailableActions } from "../state-machine";
import { financeStatusDict, getDictColor, getDictLabel } from "../dictionaries";
const study = useStudyStore();
const auth = useAuthStore();
@@ -83,8 +84,8 @@ const loadItem = async () => {
}
};
const stateLabel = (v?: string | null) => getStateLabel(financeMachine, v);
const stateColor = (v?: string | null) => getStateColor(financeMachine, v) || "info";
const stateLabel = (v?: string | null) => getDictLabel(financeStatusDict, v || "");
const stateColor = (v?: string | null) => getDictColor(financeStatusDict, v || "") || "info";
const formatAmount = (num?: number | string) => {
const n = Number(num);
+3 -2
View File
@@ -42,6 +42,7 @@ import { usePermission } from "../utils/permission";
import VisitTable from "../components/VisitTable.vue";
import { getAvailableActions, getStateColor, getStateLabel, subjectMachine } from "../state-machine";
import type { ActionConfig } from "../state-machine";
import { statusDict, getDictLabel, getDictColor } from "../dictionaries";
const route = useRoute();
const study = useStudyStore();
@@ -58,8 +59,8 @@ const permissionMap: Record<string, string> = {
drop: "subject.drop",
};
const availableActions = computed(() => getAvailableActions(subjectMachine, subject.value?.status));
const stateLabel = (v?: string | null) => getStateLabel(subjectMachine, v);
const stateColor = (v?: string | null) => getStateColor(subjectMachine, v) || "info";
const stateLabel = (v?: string | null) => getDictLabel(statusDict, v || "");
const stateColor = (v?: string | null) => getDictColor(statusDict, v || "") || "info";
const loadSubject = async () => {
if (!study.currentStudy) return;
+13 -8
View File
@@ -3,7 +3,7 @@
<el-card class="mb-12">
<div class="filters">
<el-select v-model="filters.status" placeholder="状态" clearable @change="loadTasks">
<el-option v-for="s in statuses" :key="s" :label="s" :value="s" />
<el-option v-for="opt in statusOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
</el-select>
<el-select v-model="filters.milestone_id" placeholder="里程碑" clearable @change="loadTasks">
<el-option v-for="m in milestones" :key="m.id" :label="m.name" :value="m.id" />
@@ -25,12 +25,14 @@
</template>
</el-table-column>
<el-table-column prop="assignee_id" label="负责人" width="160" />
<el-table-column prop="priority" label="优先级" width="100" />
<el-table-column prop="priority" label="优先级" width="100">
<template #default="scope">
<el-tag :type="priorityColor(scope.row.priority)">{{ priorityLabel(scope.row.priority) }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="120">
<template #default="scope">
<el-tag :type="scope.row.status === 'DONE' ? 'success' : scope.row.status === 'BLOCKED' ? 'danger' : 'info'">
{{ statusLabel(scope.row.status) }}
</el-tag>
<el-tag :type="statusColor(scope.row.status)">{{ statusLabel(scope.row.status) }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="due_date" label="截止日期" width="140" />
@@ -66,6 +68,7 @@ import { useAuthStore } from "../store/auth";
import PermissionAction from "../components/PermissionAction.vue";
import { usePermission } from "../utils/permission";
import TaskForm from "../components/TaskForm.vue";
import { getDictColor, getDictLabel, getDictOptions, statusDict, priorityDict } from "../dictionaries";
const study = useStudyStore();
const auth = useAuthStore();
@@ -77,7 +80,7 @@ const total = ref(0);
const page = ref(1);
const pageSize = 10;
const statuses = ["TODO", "DOING", "DONE", "BLOCKED"];
const statusOptions = getDictOptions(statusDict).filter((opt) => ["TODO", "DOING", "DONE", "BLOCKED"].includes(opt.value));
const filters = ref({
status: "",
@@ -179,8 +182,10 @@ const loadSavedFilters = () => {
}
};
const statusLabel = (v: string) =>
({ TODO: "待处理", DOING: "进行中", DONE: "已完成", BLOCKED: "阻塞" }[v] || v);
const statusLabel = (v: string) => getDictLabel(statusDict, v);
const statusColor = (v: string) => getDictColor(statusDict, v) || "info";
const priorityLabel = (v: string) => getDictLabel(priorityDict, v);
const priorityColor = (v: string) => getDictColor(priorityDict, v) || "info";
const milestoneName = (id: string) => milestoneMap.value[id] || id || "-";