feat(M5-P4): mock V2 化 + 伪接口清理 + vite 代理 + 走查修复

- mock 整体重写为「V2 单一存储 + V1 适配层」:教师 19 / 学生 6 / 通知 3 全端点,
  V1 冻结 7 端点由同一存储派生(与后端同一张 homework 表一致);
  提交内核对齐后端 doSubmit(版本翻转/逾期分流/附件 dataURL 拒绝/
  仅查阅拒绝),submit/action 返回 {submissionId} 契约对齐
- 删除伪接口 mock 与客户端方法:Submissions/SubmissionDetail/Grade/Remind/
  MyHomeworks/MySubmission/Submit/Create/Edit/InitializeRed/UserPull/
  SetTopmost/Expedite/ReceiveUsers/List/GetClassTree(真实环境必 404)
- types/homework.ts 收敛为 V1 冻结契约(删 11 个孤儿类型)
- 删除被切换孤儿化的组件:HomeworkUpload/ClassCheckInput/UserCheckModal
- vite 代理指向本地 8102(M5 联调目标,远程测试环境保留注释)
- 走查修复:TeacherHomeworks 操作列改模板插槽(render 函数 Dropdown 插槽
  在 view-ui-plus 下失效导致菜单内联);ReviewModal :value/@input 改
  modelValue(Vue2 API 残留导致弹窗打不开);StudentHomeworks 重新提交
  按钮补 canSubmit 门控(已截止且不允许补交时后端必拒)
- 验收:dev:mock 冒烟 58/58 PASS;构建 EXIT=0;tsc 47 条均为存量(基线 65)
  且无引用已删符号;浏览器走查 9 页面 + 批阅保存闭环 + 3 秒阅读上报通过
This commit is contained in:
wanghu
2026-09-16 03:18:38 +08:00
parent 6258ebb173
commit 44ace7c697
18 changed files with 1587 additions and 1916 deletions
+38 -48
View File
@@ -252,11 +252,6 @@ function del(row: HomeworkV2Vo) {
});
}
/* 文本按钮 */
function btn(text: string, onClick: () => void) {
return h("Button", { type: "text", size: "small", onClick }, () => text);
}
/* ============ 已发布列表列 ============ */
const pubColumns = computed(() => [
{ title: "序号", type: "index", width: 60, align: "center" },
@@ -335,44 +330,21 @@ const pubColumns = computed(() => [
},
{
title: "操作",
width: 250,
slot: "action",
width: 230,
align: "center",
fixed: "right",
render: (h: any, p: any) => {
const row = p.row as HomeworkV2Vo;
const nodes: any[] = [];
nodes.push(btn("提交情况", () => viewSubmissions(row)));
if ((row.progress?.pendingGrade ?? 0) > 0) nodes.push(btn("批阅", () => toGrade(row)));
const more: any[] = [];
if (row.hwStatus === "PUBLISHED") {
if ((row.progress?.unread ?? 0) > 0) more.push(mItem("提醒未读", () => remind(row, "NOT_READ")));
if ((row.progress?.unsubmitted ?? 0) > 0) more.push(mItem("催交", () => remind(row, "NOT_SUBMITTED")));
more.push(mItem("延长截止", () => openExtend(row)));
}
more.push(mItem("复制", () => copyRow(row)));
if (row.hwStatus === "PUBLISHED" || row.hwStatus === "CLOSED") more.push(mItem("归档", () => archive(row)));
more.push(mItem("导出报表", () => doExport(row)));
nodes.push(
h("Dropdown", { transfer: true, onOnClick: (name: string) => onMore(name) }, () => [
h("Button", { type: "text", size: "small" }, () => "更多∨"),
h("DropdownMenu", { slot: "list" }, () => more),
])
);
return h("div", {}, nodes);
},
},
]);
/* 更多菜单回调(闭包 name→action) */
const moreActions = new Map<string, () => void>();
let moreSeq = 0;
function mItem(text: string, action: () => void) {
const key = `m${++moreSeq}`;
moreActions.set(key, action);
return h("DropdownItem", { name: key }, () => text);
}
function onMore(name: string) {
moreActions.get(name)?.();
/* 更多菜单分发 */
function onPubMore(name: string, row: HomeworkV2Vo) {
if (name === "notRead") remind(row, "NOT_READ");
else if (name === "notSubmitted") remind(row, "NOT_SUBMITTED");
else if (name === "extend") openExtend(row);
else if (name === "copy") copyRow(row);
else if (name === "archive") archive(row);
else if (name === "export") doExport(row);
}
/* ============ 草稿箱列 ============ */
@@ -401,18 +373,10 @@ const draftColumns = computed(() => [
},
{
title: "操作",
slot: "draftAction",
width: 250,
align: "center",
fixed: "right",
render: (h: any, p: any) => {
const row = p.row as HomeworkV2Vo;
const nodes: any[] = [];
nodes.push(btn("编辑", () => edit(row)));
nodes.push(btn("发布", () => publishDraft(row)));
if (row.hwStatus === "DRAFT_SCHEDULED") nodes.push(btn("取消定时", () => cancelSchedule(row)));
nodes.push(btn("删除", () => del(row)));
return nodes;
},
},
]);
@@ -462,7 +426,33 @@ const tableHeight = computed(() => Utils.useTableHeight({ isSearch: true, isOper
:height="tableHeight"
:loading="loading"
no-data-text="暂无数据"
></Table>
>
<!-- 已发布行操作 -->
<template #action="{ row }">
<Button type="text" size="small" @click="viewSubmissions(row)">提交情况</Button>
<Button v-if="(row.progress?.pendingGrade ?? 0) > 0" type="text" size="small" @click="toGrade(row)">批阅</Button>
<Dropdown transfer @on-click="(name: string) => onPubMore(name, row)">
<Button type="text" size="small">更多∨</Button>
<template #list>
<DropdownMenu>
<DropdownItem v-if="row.hwStatus === 'PUBLISHED' && (row.progress?.unread ?? 0) > 0" name="notRead">提醒未读</DropdownItem>
<DropdownItem v-if="row.hwStatus === 'PUBLISHED' && (row.progress?.unsubmitted ?? 0) > 0" name="notSubmitted">催交</DropdownItem>
<DropdownItem v-if="row.hwStatus === 'PUBLISHED'" name="extend">延长截止</DropdownItem>
<DropdownItem name="copy">复制</DropdownItem>
<DropdownItem v-if="row.hwStatus === 'PUBLISHED' || row.hwStatus === 'CLOSED'" name="archive">归档</DropdownItem>
<DropdownItem name="export">导出报表</DropdownItem>
</DropdownMenu>
</template>
</Dropdown>
</template>
<!-- 草稿箱行操作 -->
<template #draftAction="{ row }">
<Button type="text" size="small" @click="edit(row)">编辑</Button>
<Button type="text" size="small" @click="publishDraft(row)">发布</Button>
<Button v-if="row.hwStatus === 'DRAFT_SCHEDULED'" type="text" size="small" @click="cancelSchedule(row)">取消定时</Button>
<Button type="text" size="small" @click="del(row)">删除</Button>
</template>
</Table>
<div class="page-panel">
<div class="fl ml-15 align-middle"></div>
<Page