Files
CampusnoticeFront/src/views/notice/DraftList.vue
T
lijing ec1f94eaa8
build / build (push) Successful in 10m17s
feat: 提交校园公告前端工程源码(Vue3 + Vite + view-ui-plus)
- 同步仓库 CI 配置 .gitea/workflows/build.yml
- 纳入 src/public/config/scripts 等工程文件
- .gitignore 增加 .scratch/.backup/.trash,排除本地临时产物
2026-09-15 11:15:03 +08:00

238 lines
8.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { ref, computed, onMounted, nextTick, h } from "vue";
import { useRouter } from "vue-router";
import { useRequest } from "alova/client";
import { Message } from "view-ui-plus";
import { noticeApi } from "@/api/module/notice";
import type { NoticeVo, NoticeQuery } from "@/types/notice";
import ApprovalFlowEditor, { type FlowModel } from "@/components/ApprovalFlowEditor.vue";
import MyConfirm from "@/components/MyConfirm";
import Utils from "@/utils";
/**
* 草稿箱:未发送的通知草稿(status=0 本人)。
* 操作:继续编辑(带参进写通知)、提交审批(选审批人后 Submit,空选复用草稿已存流程定义)、删除。
*/
const router = useRouter();
const keyword = ref("");
const pageNum = ref(1);
const pageSize = ref(parseInt(localStorage.getItem("customPageCount") || "10"));
const { data: page, loading, send: reload } = useRequest(
(params: NoticeQuery) => noticeApi.draftList(params),
{ immediate: false, initialData: { content: [], total: 0, pageIndex: 1, pageSize: 10, totalPages: 0, hasNext: false } }
);
async function run() {
try {
await reload({ keyword: keyword.value || "", pageIndex: pageNum.value, pageSize: pageSize.value, orderByTime: "2" });
} catch (e: any) {
Message.error(e.message || "获取草稿列表失败");
}
}
function doSearch() {
pageNum.value = 1;
run();
}
function pageUpdate(p: number) {
pageNum.value = p;
run();
}
function pageSizeUpdate(size: number) {
pageNum.value = 1;
pageSize.value = size;
localStorage.setItem("customPageCount", String(size));
run();
}
onMounted(run);
/* ---------- 继续编辑 ---------- */
function edit(row: NoticeVo) {
router.push({ path: "/list/new", query: { serid: row.id } });
}
/* ---------- 删除 ---------- */
function del(row: NoticeVo) {
MyConfirm({
title: "删除草稿",
msg: `确定删除“ ${row.title} ”这份草稿吗?`,
info: "删除后不可恢复",
async onOk() {
try {
await noticeApi.deleteNotice(String(row.id)).send();
Message.success("操作成功!");
if ((page.value?.content?.length || 0) <= 1 && pageNum.value > 1) pageNum.value -= 1;
run();
} catch (e: any) {
Message.error(e.message || "删除失败");
}
},
});
}
/* ---------- 提交审批(弹窗选审批人 → Submit) ---------- */
const submitModal = ref(false);
const submitRow = ref<NoticeVo | null>(null);
const flowModel = ref<FlowModel>({ enabled: false, flow: [] });
const flowEditorRef = ref();
const submitting = ref(false);
function openSubmit(row: NoticeVo) {
submitRow.value = row;
flowModel.value = { enabled: false, flow: [] };
submitModal.value = true;
// 弹窗复用同一编辑器实例,打开时重置内部勾选与步骤
nextTick(() => flowEditorRef.value?.setFlow(null));
}
async function doSubmit() {
if (!submitRow.value) return;
// 勾了审批但一步都没选人 → 拦截;未勾选(不重选人)则沿用草稿已存流程定义
if (flowEditorRef.value && !flowEditorRef.value.validate()) {
Message.info("请为审批流程选择审批人,或取消勾选");
return;
}
const flow = flowModel.value.flow || [];
submitting.value = true;
try {
const steps = flow.length
? flow.map((s, i) => ({ name: `第${i + 1}步`, vote: s.vote, approverTeaIds: [...s.approverTeaIds] }))
: undefined;
await noticeApi.submit({ serid: submitRow.value.id, steps }).send();
Message.success("已提交审批,可在「已发管理」查看进度");
submitModal.value = false;
run();
} catch (e: any) {
Message.error(e.message || "提交审批失败");
} finally {
submitting.value = false;
}
}
/* ---------- 表格 ---------- */
const columns = [
{ title: "序号", type: "index", width: 90, align: "center" },
{
title: "标题",
key: "title",
align: "left",
tooltip: true,
render: (h: any, p: any) => {
const row: any = p.row;
const children = [h("span", {}, row.title)];
if (row.timingSendTime) {
children.push(h("Tag", { style: "margin-left:6px" }, () => "定时"));
}
return h("div", {}, children);
},
},
{
title: "类型",
width: 100,
align: "center",
render: (h: any, p: any) =>
h("Tag", { color: p.row.type == 2 ? "error" : "default" }, () => p.row.typeDesc || (p.row.type == 2 ? "重要" : "普通")),
},
{
title: "定时发送",
width: 170,
align: "left",
render: (h: any, p: any) => h("span", {}, p.row.timingSendTime ? String(p.row.timingSendTime).replace("T", " ").slice(0, 16) : "—"),
},
{
title: "最后修改",
width: 170,
align: "left",
render: (h: any, p: any) => h("span", {}, String(p.row.updateTime || p.row.createTime || "").replace("T", " ").slice(0, 16)),
},
{
title: "操作",
width: 220,
align: "center",
fixed: "right",
render: (h: any, p: any) => {
const row: any = p.row;
return [
Utils.operatingHandle(h, "继续编辑", "icon-xiugaijl", () => edit(row)),
Utils.operatingHandle(h, "提交审批", "icon-shenpi", () => openSubmit(row)),
Utils.operatingHandle(h, "删除草稿", "icon-ashbin", () => del(row)),
];
},
},
];
const tableHeight = computed(() => Utils.useTableHeight({ isSearch: true, isOperat: true, isPage: true }));
</script>
<template>
<div class="page-wrapper">
<div class="main-container">
<!-- 搜索区 -->
<div class="search-wrap fix">
<Button class="fl" type="primary" size="large" @click="router.push('/list/new')">写公告</Button>
<Input
class="fr"
style="width: 220px"
search
suffix="ios-search"
placeholder="输入标题关键字搜索"
v-model="keyword"
@on-search="doSearch"
@on-clear="doSearch"
/>
</div>
<!-- 表格 + 分页 -->
<Table
:columns="columns"
:data="page.content"
class="link-table table-bottom-box"
:height="tableHeight"
:loading="loading"
no-data-text="草稿箱是空的"
></Table>
<div class="page-panel">
<div class="fl ml-15 align-middle"></div>
<Page
class="page-box fr"
:total="page.total"
:current="pageNum"
:page-size="pageSize"
:page-size-opts="[10, 20, 30, 40]"
@on-page-size-change="pageSizeUpdate"
@on-change="pageUpdate"
placement="top"
show-total
show-sizer
></Page>
</div>
<!-- 提交审批弹窗 -->
<Modal v-model="submitModal" title="提交审批" :mask-closable="false" width="620px">
<p class="submit-tip">公告:{{ submitRow?.title }}</p>
<ApprovalFlowEditor ref="flowEditorRef" v-model="flowModel" unchecked-text="(不勾选=沿用草稿已存流程)"></ApprovalFlowEditor>
<p class="submit-hint">不重选审批人时,将沿用草稿保存时配置的审批流程。</p>
<template #footer>
<Button type="warning" :loading="submitting" @click="doSubmit">提交审批</Button>
<Button @click="submitModal = false" style="margin-left: 8px">取消</Button>
</template>
</Modal>
</div>
</div>
</template>
<style scoped>
.submit-tip {
font-size: 14px;
font-weight: 600;
margin-bottom: 12px;
}
.submit-hint {
color: #808695;
font-size: 12px;
margin-top: 8px;
}
</style>