简单汉化
This commit is contained in:
@@ -8,10 +8,10 @@
|
||||
<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" />
|
||||
</el-select>
|
||||
<el-input v-model="filters.assignee_id" placeholder="负责人ID" style="width: 180px" @change="loadTasks" />
|
||||
<el-input v-model="filters.assignee_id" placeholder="负责人" style="width: 180px" @change="loadTasks" />
|
||||
<div class="spacer" />
|
||||
<PermissionAction action="task.create">
|
||||
<el-button type="primary" @click="openCreate">新增任务</el-button>
|
||||
<el-button type="primary" @click="openCreate">新建任务</el-button>
|
||||
</PermissionAction>
|
||||
</div>
|
||||
</el-card>
|
||||
@@ -19,10 +19,20 @@
|
||||
<el-card>
|
||||
<el-table :data="tasks" v-loading="loading" style="width: 100%">
|
||||
<el-table-column prop="title" label="标题" />
|
||||
<el-table-column prop="milestone_id" label="里程碑" />
|
||||
<el-table-column prop="milestone_id" label="节点/里程碑">
|
||||
<template #default="scope">
|
||||
{{ milestoneName(scope.row.milestone_id) }}
|
||||
</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="status" label="状态" width="120" />
|
||||
<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>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="due_date" label="截止日期" width="140" />
|
||||
<el-table-column label="操作" width="120">
|
||||
<template #default="scope">
|
||||
@@ -47,7 +57,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from "vue";
|
||||
import { onMounted, ref, computed } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { fetchTasks } from "../api/tasks";
|
||||
import { fetchMilestones } from "../api/milestones";
|
||||
@@ -79,6 +89,12 @@ const showForm = ref(false);
|
||||
const editingTask = ref<any | null>(null);
|
||||
|
||||
const { can } = usePermission();
|
||||
const milestoneMap = computed(() =>
|
||||
milestones.value.reduce<Record<string, string>>((acc, cur) => {
|
||||
acc[cur.id] = cur.name || cur.id;
|
||||
return acc;
|
||||
}, {})
|
||||
);
|
||||
|
||||
const loadMilestones = async () => {
|
||||
if (!study.currentStudy) return;
|
||||
@@ -142,8 +158,35 @@ const ensureUser = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const filterKey = computed(() => (study.currentStudy ? `tasks_filter_${study.currentStudy.id}` : null));
|
||||
const saveFilters = () => {
|
||||
if (!filterKey.value) return;
|
||||
localStorage.setItem(filterKey.value, JSON.stringify({ ...filters.value, page: page.value }));
|
||||
};
|
||||
const loadSavedFilters = () => {
|
||||
if (!filterKey.value) return;
|
||||
const raw = localStorage.getItem(filterKey.value);
|
||||
if (raw) {
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
filters.value.status = parsed.status || "";
|
||||
filters.value.milestone_id = parsed.milestone_id || "";
|
||||
filters.value.assignee_id = parsed.assignee_id || "";
|
||||
page.value = parsed.page || 1;
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const statusLabel = (v: string) =>
|
||||
({ TODO: "待处理", DOING: "进行中", DONE: "已完成", BLOCKED: "阻塞" }[v] || v);
|
||||
|
||||
const milestoneName = (id: string) => milestoneMap.value[id] || id || "-";
|
||||
|
||||
onMounted(async () => {
|
||||
await ensureUser();
|
||||
loadSavedFilters();
|
||||
loadMilestones();
|
||||
loadTasks();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user