yyb
9 小时以前 a1df9699594b0a0e46d26a0394eafb1eb030c68b
企业新闻
已添加3个文件
已修改8个文件
953 ■■■■ 文件已修改
src/api/officeProcessAutomation/enterpriseNews.js 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/ApproveManage/approve-list/approveListConstants.js 122 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalInstanceFormConfigTable.js 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/EnterpriseNews/news-manage/components/NewsDetailPanel.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsApprovalBridge.js 109 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsMappers.js 224 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsUtils.js 43 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/EnterpriseNews/news-manage/index.vue 298 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/EnterpriseNews/news-manage/useEnterpriseNewsList.js 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/HrManage/regular-apply/index.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/officeProcessAutomation/HrManage/transfer-apply/index.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/officeProcessAutomation/enterpriseNews.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
import request from "@/utils/request";
/** åˆ†é¡µæŸ¥è¯¢ä¼ä¸šæ–°é—» */
export function listEnterpriseNewsPage(params) {
  return request({
    url: "/enterpriseNews/listPage",
    method: "get",
    params,
  });
}
/** æ–°å¢žä¼ä¸šæ–°é—» */
export function saveEnterpriseNews(enterpriseNewsDto) {
  return request({
    url: "/enterpriseNews/save",
    method: "post",
    data: enterpriseNewsDto,
  });
}
/** ä¿®æ”¹ä¼ä¸šæ–°é—» */
export function updateEnterpriseNews(enterpriseNewsDto) {
  return request({
    url: "/enterpriseNews/update",
    method: "put",
    data: enterpriseNewsDto,
  });
}
/** åˆ é™¤ä¼ä¸šæ–°é—»ï¼ˆbody ä¸º ID æ•°ç»„) */
export function deleteEnterpriseNews(ids) {
  const idList = (Array.isArray(ids) ? ids : [ids]).filter((id) => id != null && id !== "");
  return request({
    url: "/enterpriseNews/delete",
    method: "delete",
    data: idList,
  });
}
src/views/officeProcessAutomation/ApproveManage/approve-list/approveListConstants.js
@@ -33,6 +33,7 @@
/** åˆ—表查询:审批状态(与后端 status æžšä¸¾ä¸€è‡´ï¼‰ */
export const APPROVAL_STATUS_SEARCH_OPTIONS = [
  { value: "DRAFT", label: "草稿" },
  { value: "PENDING", label: "待审批" },
  { value: "APPROVED", label: "已通过" },
  { value: "REJECTED", label: "已驳回" },
@@ -40,34 +41,105 @@
/**
 * å®¡æ‰¹çŠ¶æ€å±•ç¤ºï¼ˆä¸ŽåŽç«¯ status æžšä¸¾ä¸€è‡´ï¼‰
 * PENDING â†’ å¾…审批/进行中  APPROVED â†’ å·²é€šè¿‡/已完成  REJECTED â†’ å·²é©³å›ž
 * DRAFT→草稿 PENDING→待审批/进行中 APPROVED→已通过/已完成 REJECTED→已驳回
 */
export const APPROVAL_STATUS_OPTIONS = [
  { value: "draft", api: "DRAFT", label: "草稿" },
  { value: "pending", api: "PENDING", label: "待审批" },
  { value: "approved", api: "APPROVED", label: "已通过" },
  { value: "rejected", api: "REJECTED", label: "已驳回" },
  { value: "cancelled", api: "CANCELLED", label: "已撤销" },
];
/** æ•°å­—状态码(部分后端用 0/1/2) */
const STATUS_NUMERIC_MAP = {
  0: "pending",
  1: "approved",
  2: "rejected",
  3: "cancelled",
  4: "cancelled",
};
/** åŽç«¯ status / é¡µé¢ approvalStatus â†’ ç»Ÿä¸€é¡µé¢ key(pending | approved | rejected | cancelled) */
export function normalizeApprovalStatusKey(v) {
  const s = String(v ?? "").trim();
  if (v == null || v === "") return "pending";
  if (typeof v === "number" || (typeof v === "string" && /^\d+$/.test(v.trim()))) {
    const numKey = STATUS_NUMERIC_MAP[Number(v)];
    if (numKey) return numKey;
  }
  const s = String(v).trim();
  if (!s) return "pending";
  const upper = s.toUpperCase();
  if (upper === "APPROVED" || upper === "APPROVE" || upper === "PASS") return "approved";
  if (upper === "REJECTED" || upper === "REJECT" || upper === "REFUSE") return "rejected";
  if (upper === "CANCELLED" || upper === "CANCEL") return "cancelled";
  if (upper === "DRAFT") return "draft";
  if (upper === "PUBLISHED") return "approved";
  if (upper === "OFFLINE") return "cancelled";
  if (upper === "APPROVED" || upper === "APPROVE" || upper === "PASS" || upper === "AGREE") {
    return "approved";
  }
  if (
    upper === "REJECTED" ||
    upper === "REJECT" ||
    upper === "REFUSE" ||
    upper === "REFUSED" ||
    upper === "DENIED"
  ) {
    return "rejected";
  }
  if (upper === "CANCELLED" || upper === "CANCEL" || upper === "REVOKED") return "cancelled";
  if (
    upper === "PENDING" ||
    upper === "IN_PROGRESS" ||
    upper === "PROCESSING" ||
    upper === "RUNNING"
    upper === "RUNNING" ||
    upper === "WAIT" ||
    upper === "WAITING"
  ) {
    return "pending";
  }
  if (s.includes("草稿")) return "draft";
  if (s.includes("驳回") || s.includes("拒绝")) return "rejected";
  if (s.includes("下线")) return "cancelled";
  if (s.includes("撤销")) return "cancelled";
  if (s.includes("发布") || s.includes("通过") || s.includes("完成")) return "approved";
  if (s.includes("待审") || s.includes("进行中") || s.includes("审批中")) return "pending";
  const lower = s.toLowerCase();
  if (["pending", "approved", "rejected", "cancelled"].includes(lower)) return lower;
  if (["draft", "pending", "approved", "rejected", "cancelled"].includes(lower)) return lower;
  return "pending";
}
/** ä»Žåˆ—表/详情行解析后端原始状态(兼容多字段命名) */
export function resolveInstanceStatusRaw(row) {
  if (!row || typeof row !== "object") return "";
  const candidates = [
    row.status,
    row.statusRaw,
    row.approvalStatus,
    row.statusName,
    row.statusLabel,
    row.approvalStatusName,
    row.statusDesc,
    row.instanceStatus,
    row.approvalInstanceStatus,
    row.approveStatus,
    row.auditStatus,
    row.approvalInstance?.status,
    row.approvalInstanceVo?.status,
  ];
  for (const c of candidates) {
    if (c != null && c !== "") return c;
  }
  const tasks = row.tasks;
  if (Array.isArray(tasks) && tasks.length) {
    const rejected = tasks.some((t) =>
      normalizeApprovalStatusKey(t?.status ?? t?.taskStatus) === "rejected"
    );
    if (rejected) return "REJECTED";
    const allApproved = tasks.every((t) =>
      normalizeApprovalStatusKey(t?.status ?? t?.taskStatus) === "approved"
    );
    if (allApproved) return "APPROVED";
  }
  return "";
}
/** æäº¤å¼¹çª—:模板卡片(来自后端列表) */
@@ -322,12 +394,15 @@
    dto.id = existingRow?.id ?? submitForm?.instanceId;
    dto.instanceNo = existingRow?.instanceNo ?? submitForm?.instanceNo ?? "";
    dto.status =
      existingRow?.statusRaw || mapInstanceStatusToApi(existingRow?.approvalStatus) || "PENDING";
      submitForm?.saveStatusApi ||
      existingRow?.statusRaw ||
      mapInstanceStatusToApi(existingRow?.approvalStatus) ||
      "PENDING";
    dto.currentLevel = existingRow?.currentLevel ?? submitForm?.currentLevel ?? 1;
    dto.applicantId = existingRow?.applicantId ?? existingRow?.applicantNo;
    dto.applicantName = existingRow?.applicantName || "";
  } else {
    dto.status = "PENDING";
    dto.status = submitForm?.saveStatusApi || "PENDING";
    dto.currentLevel = 1;
    dto.applicantId = userStore?.id;
    dto.applicantName = userStore?.nickName || userStore?.name || "";
@@ -352,6 +427,12 @@
  return normalizeApprovalStatusKey(status);
}
/** åˆ—表/详情行 â†’ é¡µé¢ approvalStatus key */
export function mapInstanceApprovalStatusFromRow(row) {
  const raw = resolveInstanceStatusRaw(row);
  return normalizeApprovalStatusKey(raw);
}
/** é¡µé¢ approvalStatus â†’ åŽç«¯ status */
export function mapInstanceStatusToApi(approvalStatus) {
  const key = normalizeApprovalStatusKey(approvalStatus);
@@ -370,7 +451,8 @@
/** åˆ†é¡µåˆ—表项 â†’ è¡¨æ ¼è¡Œ */
export function mapInstanceFromApi(row) {
  if (!row) return {};
  const approvalStatus = mapInstanceStatusFromApi(row.status);
  const statusRaw = resolveInstanceStatusRaw(row);
  const approvalStatus = normalizeApprovalStatusKey(statusRaw);
  const createTime = formatDisplayTime(row.createTime ?? row.applyTime ?? "");
  const applyTime = formatDisplayTime(row.applyTime ?? "");
  const finishTime = formatDisplayTime(row.finishTime ?? "");
@@ -397,7 +479,7 @@
    unread: Boolean(row.isApprove) && approvalStatus === "pending",
    isApprove: Boolean(row.isApprove),
    approvalStatus,
    statusRaw: row.status,
    statusRaw: statusRaw || row.status,
    createTime,
    applyTime: applyTime === "—" ? "" : applyTime,
    finishTime: finishTime === "—" ? "" : finishTime,
@@ -439,10 +521,16 @@
}
export function buildApprovalInstanceListParams({ page, searchForm, businessType, extraParams }) {
  const extra = { ...(extraParams && typeof extraParams === "object" ? extraParams : {}) };
  if (extra.createTime != null && extra.createTimeStart == null) {
    extra.createTimeStart = extra.createTime;
  }
  delete extra.createTime;
  const params = {
    current: page.current,
    size: page.size,
    ...(extraParams && typeof extraParams === "object" ? extraParams : {}),
    ...extra,
  };
  const bizType = businessType ?? searchForm?.businessType;
  if (bizType != null && bizType !== "") {
@@ -451,9 +539,12 @@
  if (searchForm?.status) {
    params.status = searchForm.status;
  }
  const range = searchForm?.createTimeRange;
  const range =
    searchForm?.createTimeRange ??
    searchForm?.applyDateRange ??
    searchForm?.transferDateRange;
  if (Array.isArray(range) && range[0]) {
    params.createTime = range[0];
    params.createTimeStart = range[0];
  }
  if (Array.isArray(range) && range[1]) {
    params.createTimeEnd = range[1];
@@ -483,6 +574,7 @@
/** ä¸šåŠ¡ç”³è¯·é¡µçŠ¶æ€æ–‡æ¡ˆï¼šPENDING→进行中 APPROVED→已完成 REJECTED→已驳回 */
export function businessApprovalStatusLabel(v) {
  const key = normalizeApprovalStatusKey(v);
  if (key === "draft") return "草稿";
  if (key === "pending") return "进行中";
  if (key === "approved") return "已完成";
  if (key === "rejected") return "已驳回";
@@ -503,6 +595,7 @@
export function businessApprovalStatusTagType(v) {
  const key = normalizeApprovalStatusKey(v);
  if (key === "draft") return "info";
  if (key === "approved") return "success";
  if (key === "rejected") return "danger";
  if (key === "cancelled") return "info";
@@ -511,6 +604,7 @@
export function approvalStatusTagType(v) {
  const key = normalizeApprovalStatusKey(v);
  if (key === "draft") return "info";
  if (key === "approved") return "success";
  if (key === "rejected") return "danger";
  if (key === "cancelled") return "info";
src/views/officeProcessAutomation/ApproveManage/approve-shared/approvalInstanceFormConfigTable.js
@@ -6,8 +6,41 @@
  resolveInstanceFormFields,
} from "../approve-list/approveListConstants.js";
/** åˆ—表/详情不回显为独立列的填报项 key */
const DEFAULT_EXCLUDE_KEYS = new Set(["summary"]);
/** åˆ—表/详情不回显为独立列的填报项 key(避免覆盖实例系统字段) */
const DEFAULT_EXCLUDE_KEYS = new Set([
  "summary",
  "status",
  "approvalStatus",
  "approvalstatus",
  "instanceStatus",
  "publishStatus",
  "newsStatus",
]);
/** enrich åŽå¿…须保留的实例字段(不被 formConfig é“ºå¹³è¦†ç›–) */
const PRESERVE_INSTANCE_FIELDS = [
  "id",
  "approvalStatus",
  "statusRaw",
  "status",
  "instanceNo",
  "templateId",
  "templateName",
  "businessType",
  "businessId",
  "businessName",
  "applicantId",
  "applicantNo",
  "applicantName",
  "createTime",
  "applyTime",
  "finishTime",
  "title",
  "isApprove",
  "unread",
  "currentLevel",
  "newsStatus",
];
/**
 * ä»Žè¡Œæ•°æ® formConfig è§£æžå­—段定义与填报值,并铺平到行上供主表 prop ç»‘定(展示用格式化值)
@@ -41,6 +74,10 @@
    displayRow[f.key] = text;
  }
  for (const key of PRESERVE_INSTANCE_FIELDS) {
    if (row[key] !== undefined) displayRow[key] = row[key];
  }
  return displayRow;
}
src/views/officeProcessAutomation/EnterpriseNews/news-manage/components/NewsDetailPanel.vue
@@ -2,9 +2,9 @@
<template>
  <el-descriptions :column="2" border>
    <el-descriptions-item label="新闻编号">{{ row.newsNo || "—" }}</el-descriptions-item>
    <el-descriptions-item label="发布状态">
      <el-tag :type="publishStatusTag(row.publishStatus)" size="small">
        {{ publishStatusLabel(row.publishStatus) }}
    <el-descriptions-item label="状态">
      <el-tag :type="publishStatusTag(row.newsStatus ?? row.publishStatus)" size="small">
        {{ publishStatusLabel(row.newsStatus ?? row.publishStatus) }}
      </el-tag>
    </el-descriptions-item>
    <el-descriptions-item label="新闻分类">
@@ -57,7 +57,7 @@
  </template>
  <el-empty v-else description="暂无附件" :image-size="48" />
  <template v-if="row.newsType === 'culture' && row.publishStatus === 'published'">
  <template v-if="row.newsType === 'culture' && (row.publishStatus === 'PUBLISHED' || row.publishStatus === 'published')">
    <el-divider content-position="left">互动(点赞 {{ likeCount }} Â· è¯„论 {{ commentCount }})</el-divider>
    <div class="interaction-bar">
      <el-button type="primary" plain size="small" @click="$emit('like')">
src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsApprovalBridge.js
@@ -1,98 +1,11 @@
import {
  createEmptyForm,
  publishStatusLabel,
  PUBLISH_STATUS_OPTIONS,
} from "./enterpriseNewsUtils.js";
import { normalizeApprovalStatusKey } from "../../ApproveManage/approve-list/approveListConstants.js";
/** formPayload ä¸­å­˜æ”¾å®Œæ•´ä¼ä¸šæ–°é—»ä¸šåŠ¡æ•°æ®çš„é”® */
export const ENTERPRISE_NEWS_PAYLOAD_KEY = "enterpriseNews";
export function extractEnterpriseNewsFromRow(row) {
  const payload = row?.formPayload || {};
  const raw = payload[ENTERPRISE_NEWS_PAYLOAD_KEY];
  if (raw && typeof raw === "object") {
    return { ...createEmptyForm(), ...raw };
  }
  return {
    ...createEmptyForm(),
    title: payload.title || row?.title || "",
    summary: payload.summary || "",
    newsType: payload.newsType || "announcement",
    contentHtml: payload.contentHtml || "",
  };
}
/** åˆ—表行增强:主表展示新闻字段 */
export function enrichEnterpriseNewsListRow(row) {
  const news = extractEnterpriseNewsFromRow(row);
  const publishStatus =
    news.publishStatus || mapApprovalStatusToPublishStatus(row?.approvalStatus);
  return {
    ...row,
    newsNo: news.newsNo || row.instanceNo || "—",
    title: news.title || row.title || "—",
    summary: news.summary,
    newsType: news.newsType,
    publisherName: news.publisherName || row.applicantName || "—",
    publishTime: news.publishTime || row.createTime || "",
    updateTime: news.updateTime || row.createTime || "",
    publishStatus,
    _news: news,
  };
}
function mapApprovalStatusToPublishStatus(approvalStatus) {
  const key = normalizeApprovalStatusKey(approvalStatus);
  if (key === "approved") return "published";
  if (key === "pending") return "pending_review";
  if (key === "rejected") return "draft";
  return "draft";
}
/** ä¼ä¸šæ–°é—»è¡¨å• â†’ å®¡æ‰¹å®žä¾‹ formPayload */
export function syncNewsFormToSubmitPayload(newsForm, submitForm) {
  const snapshot = JSON.parse(JSON.stringify(newsForm));
  submitForm.formPayload = {
    ...(submitForm.formPayload || {}),
    [ENTERPRISE_NEWS_PAYLOAD_KEY]: snapshot,
    title: snapshot.title,
    summary: snapshot.summary,
  };
}
export function buildEnterpriseNewsTableColumns(buildTableActions) {
  return [
    { label: "编号", prop: "newsNo", width: 150 },
    { label: "标题", prop: "title", minWidth: 180, showOverflowTooltip: true },
    {
      label: "分类",
      prop: "newsType",
      width: 100,
      dataType: "slot",
      slot: "newsType",
    },
    {
      label: "状态",
      prop: "publishStatus",
      width: 90,
      dataType: "tag",
      formatData: (v) => publishStatusLabel(v),
      formatType: (v) => {
        const hit = PUBLISH_STATUS_OPTIONS.find((x) => x.value === v);
        return hit?.tag || "info";
      },
    },
    { label: "发布人", prop: "publisherName", width: 110 },
    { label: "发布时间", prop: "publishTime", width: 170 },
    { label: "更新时间", prop: "updateTime", width: 170 },
    {
      dataType: "action",
      label: "操作",
      align: "center",
      fixed: "right",
      width: 220,
      operation: buildTableActions(),
    },
  ];
}
/** @deprecated è¯·ä½¿ç”¨ enterpriseNewsMappers.js */
export {
  ENTERPRISE_NEWS_PAYLOAD_KEY,
  buildEnterpriseNewsSaveDto,
  buildEnterpriseNewsTableColumns,
  canEditEnterpriseNewsRow,
  extractEnterpriseNewsFromRow,
  mapApiRowToNewsForm,
  mapEnterpriseNewsFromApi,
  syncNewsFormToSubmitPayload,
} from "./enterpriseNewsMappers.js";
src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsMappers.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,224 @@
import {
  createEmptyForm,
  normalizeEnterpriseNewsStatus,
  publishStatusLabel,
  PUBLISH_STATUS_OPTIONS,
} from "./enterpriseNewsUtils.js";
/** formPayload ä¸­å­˜æ”¾å®Œæ•´ä¼ä¸šæ–°é—»ä¸šåŠ¡æ•°æ®çš„é”®ï¼ˆå®¡æ‰¹å®žä¾‹ä¿å­˜ç”¨ï¼‰ */
export const ENTERPRISE_NEWS_PAYLOAD_KEY = "enterpriseNews";
const READ_SCOPE_FROM_API = {
  all: "all",
  dept: "department",
  department: "department",
  custom: "custom",
  management: "management",
};
const READ_SCOPE_TO_API = {
  all: "all",
  department: "dept",
  dept: "dept",
  custom: "custom",
  management: "all",
};
export function mapReadScopeFromApi(scope) {
  const key = String(scope ?? "").trim().toLowerCase();
  return READ_SCOPE_FROM_API[key] || key || "all";
}
export function mapReadScopeToApi(scope) {
  return READ_SCOPE_TO_API[scope] || scope || "all";
}
export function unwrapEnterpriseNewsPage(res) {
  const data = res?.data ?? res;
  if (!data || typeof data !== "object") {
    return { records: [], total: 0 };
  }
  if (Array.isArray(data.records)) {
    return { records: data.records, total: Number(data.total ?? 0) };
  }
  const nested = data.data;
  if (nested && typeof nested === "object" && Array.isArray(nested.records)) {
    return { records: nested.records, total: Number(nested.total ?? 0) };
  }
  return { records: [], total: 0 };
}
/** ç»„装 listPage æŸ¥è¯¢å‚æ•° */
export function buildEnterpriseNewsListParams({ page, searchForm }) {
  const params = {
    current: page.current,
    size: page.size,
  };
  const kw = (searchForm?.keyword || "").trim();
  if (kw) params.title = kw;
  if (searchForm?.newsType) params.category = searchForm.newsType;
  if (searchForm?.status) params.status = searchForm.status;
  const range = searchForm?.createTimeRange;
  if (Array.isArray(range) && range[0]) {
    params.createTimeStart = range[0];
  }
  if (Array.isArray(range) && range[1]) {
    params.createTimeEnd = range[1];
  }
  return params;
}
/** æŽ¥å£ EnterpriseNewsVo â†’ åˆ—表行 */
export function mapEnterpriseNewsFromApi(row) {
  if (!row) return {};
  const newsStatus = normalizeEnterpriseNewsStatus(row.status);
  return {
    ...row,
    newsNo: row.id != null ? String(row.id) : "—",
    newsType: row.category || "",
    contentHtml: row.content || "",
    publisherName: row.createUserName || "—",
    publishTime: row.createTime || "",
    updateTime: row.updateTime || "",
    newsStatus,
    requireReadConfirm: row.isRequired === "1" || row.isRequired === 1,
    readScope: mapReadScopeFromApi(row.readScope),
    readCount: row.readCount ?? 0,
    requiredReadCount: row.requiredReadCount ?? 0,
  };
}
/** æ˜¯å¦å…è®¸ä¿®æ”¹ï¼ˆè‰ç¨¿ã€é©³å›žå¯æ”¹ï¼‰ */
export function canEditEnterpriseNewsRow(row) {
  const status = normalizeEnterpriseNewsStatus(row?.newsStatus ?? row?.status);
  return status === "DRAFT" || status === "REJECTED";
}
/** æŽ¥å£è¡Œ / è¯¦æƒ… â†’ è¡¨å• */
export function mapApiRowToNewsForm(row) {
  if (!row) return createEmptyForm();
  return {
    ...createEmptyForm(),
    id: row.id != null ? String(row.id) : "",
    newsNo: row.id != null ? String(row.id) : "",
    title: row.title || "",
    summary: row.summary || "",
    contentHtml: row.content || row.contentHtml || "",
    newsType: row.newsType || row.category || "announcement",
    readScope: mapReadScopeFromApi(row.readScope),
    requireReadConfirm: Boolean(row.requireReadConfirm ?? row.isRequired === "1"),
    publisherName: row.createUserName || row.publisherName || "",
    publishStatus: normalizeEnterpriseNewsStatus(row.newsStatus ?? row.status),
    templateId: row.templateId,
    templateName: row.templateName || "",
    targetDeptIds: [...(row.deptIds || row.targetDeptIds || [])],
    targetUserIds: [...(row.userIds || row.targetUserIds || [])],
  };
}
/** å®¡æ‰¹å®žä¾‹è¡Œ formPayload â†’ è¡¨å•(兼容旧数据) */
export function extractEnterpriseNewsFromRow(row) {
  if (!row?.formPayload && !row?.formFieldDefs && !row?.instanceNo) {
    return mapApiRowToNewsForm(row);
  }
  const payload = row?.formPayload || {};
  const raw = payload[ENTERPRISE_NEWS_PAYLOAD_KEY];
  if (raw && typeof raw === "object") {
    return { ...createEmptyForm(), ...raw };
  }
  return {
    ...createEmptyForm(),
    title: payload.title || row?.title || "",
    summary: payload.summary || "",
    newsType: payload.newsType || row?.category || "announcement",
    contentHtml: payload.contentHtml || row?.content || "",
  };
}
export function syncNewsFormToSubmitPayload(newsForm, submitForm) {
  const snapshot = JSON.parse(JSON.stringify(newsForm));
  submitForm.formPayload = {
    ...(submitForm.formPayload || {}),
    [ENTERPRISE_NEWS_PAYLOAD_KEY]: snapshot,
    title: snapshot.title,
    summary: snapshot.summary,
  };
}
function toIdList(ids) {
  if (!Array.isArray(ids) || !ids.length) return undefined;
  const list = ids
    .map((id) => (typeof id === "number" ? id : Number(id)))
    .filter((n) => !Number.isNaN(n));
  return list.length ? list : undefined;
}
/** è¡¨å• â†’ POST /enterpriseNews/save è¯·æ±‚体 */
export function buildEnterpriseNewsSaveDto(newsForm, { status } = {}) {
  const dto = {
    title: (newsForm.title || "").trim(),
    summary: newsForm.summary || "",
    content: newsForm.contentHtml || "",
    category: newsForm.newsType || "",
    readScope: mapReadScopeToApi(newsForm.readScope),
    isRequired: newsForm.requireReadConfirm ? "1" : "0",
    status: normalizeEnterpriseNewsStatus(status ?? newsForm.publishStatus),
  };
  const rawId = newsForm.id;
  if (rawId != null && rawId !== "") {
    const id = Number(rawId);
    if (!Number.isNaN(id)) dto.id = id;
  }
  const deptIds = toIdList(newsForm.targetDeptIds);
  if (deptIds) dto.deptIds = deptIds;
  const userIds = toIdList(newsForm.targetUserIds);
  if (userIds) dto.userIds = userIds;
  const templateId = newsForm.templateId;
  if (templateId != null && templateId !== "") {
    const tid = Number(templateId);
    if (!Number.isNaN(tid)) dto.templateId = tid;
  }
  if (newsForm.templateName) dto.templateName = newsForm.templateName;
  return dto;
}
export function buildEnterpriseNewsTableColumns(buildTableActions) {
  return [
    { label: "编号", prop: "newsNo", width: 120 },
    { label: "标题", prop: "title", minWidth: 180, showOverflowTooltip: true },
    {
      label: "分类",
      prop: "newsType",
      width: 100,
      dataType: "slot",
      slot: "newsType",
    },
    {
      label: "状态",
      prop: "newsStatus",
      width: 100,
      dataType: "tag",
      formatData: (v) => publishStatusLabel(v),
      formatType: (v) => {
        const hit = PUBLISH_STATUS_OPTIONS.find((x) => x.value === v);
        return hit?.tag || "info";
      },
    },
    { label: "创建人", prop: "publisherName", width: 110 },
    { label: "创建时间", prop: "createTime", width: 170 },
    { label: "更新时间", prop: "updateTime", width: 170 },
    {
      dataType: "action",
      label: "操作",
      align: "center",
      fixed: "right",
      width: 220,
      operation: buildTableActions(),
    },
  ];
}
src/views/officeProcessAutomation/EnterpriseNews/news-manage/enterpriseNewsUtils.js
@@ -8,13 +8,36 @@
  { value: "culture", label: "文化活动", color: "#67c23a" },
];
/** å‘布状态 */
/** ä¼ä¸šæ–°é—»çŠ¶æ€ï¼ˆä¸ŽåŽç«¯æžšä¸¾ä¸€è‡´ï¼‰ */
export const PUBLISH_STATUS_OPTIONS = [
  { value: "draft", label: "草稿", tag: "info" },
  { value: "pending_review", label: "待审核", tag: "warning" },
  { value: "published", label: "已发布", tag: "success" },
  { value: "archived", label: "已归档", tag: "" },
  { value: "DRAFT", label: "草稿", tag: "info" },
  { value: "PENDING", label: "待审批", tag: "warning" },
  { value: "PUBLISHED", label: "已发布", tag: "success" },
  { value: "REJECTED", label: "驳回", tag: "danger" },
  { value: "OFFLINE", label: "已下线", tag: "info" },
];
/** ä¼ä¸šæ–°é—»åˆ—表筛选 */
export const ENTERPRISE_NEWS_STATUS_SEARCH_OPTIONS = [...PUBLISH_STATUS_OPTIONS];
const LEGACY_PUBLISH_STATUS_MAP = {
  draft: "DRAFT",
  pending_review: "PENDING",
  published: "PUBLISHED",
  archived: "OFFLINE",
};
/** ç»Ÿä¸€ä¸ºåŽç«¯çŠ¶æ€æžšä¸¾å€¼ */
export function normalizeEnterpriseNewsStatus(v) {
  if (v == null || v === "") return "DRAFT";
  const upper = String(v).trim().toUpperCase();
  if (upper === "APPROVED") return "PUBLISHED";
  const hit = PUBLISH_STATUS_OPTIONS.find((x) => x.value === upper);
  if (hit) return hit.value;
  const legacy = LEGACY_PUBLISH_STATUS_MAP[String(v).trim().toLowerCase()];
  if (legacy) return legacy;
  return upper;
}
/** æŽ’版模板 */
export const LAYOUT_TEMPLATE_OPTIONS = [
@@ -63,11 +86,13 @@
}
export function publishStatusLabel(v) {
  return PUBLISH_STATUS_OPTIONS.find((x) => x.value === v)?.label || v || "—";
  const key = normalizeEnterpriseNewsStatus(v);
  return PUBLISH_STATUS_OPTIONS.find((x) => x.value === key)?.label || v || "—";
}
export function publishStatusTag(v) {
  return PUBLISH_STATUS_OPTIONS.find((x) => x.value === v)?.tag || "info";
  const key = normalizeEnterpriseNewsStatus(v);
  return PUBLISH_STATUS_OPTIONS.find((x) => x.value === key)?.tag || "info";
}
export function layoutTemplateLabel(v) {
@@ -99,7 +124,7 @@
    readScope: "all",
    targetDeptIds: [],
    targetUserIds: [],
    publishStatus: "draft",
    publishStatus: "DRAFT",
    publisherName: "",
    publishTime: "",
    readRecords: [],
@@ -109,6 +134,8 @@
    versions: [],
    versionNo: 1,
    requireReadConfirm: false,
    templateId: null,
    templateName: "",
  };
}
src/views/officeProcessAutomation/EnterpriseNews/news-manage/index.vue
@@ -1,4 +1,4 @@
<!--OA模块:EnterpriseNews ä¼ä¸šæ–°é—»ï¼ˆåˆ—表走审批实例,新增/修改保留原表单 + æ¨¡æ¿å®¡æ‰¹æµç¨‹ï¼‰-->
<!--OA模块:EnterpriseNews ä¼ä¸šæ–°é—»ï¼ˆlistPage|save|update|delete,新建保留审批模板)-->
<template>
  <div class="app-container enterprise-news-page">
    <div class="search_form mb20">
@@ -7,7 +7,7 @@
        <el-input
          v-model="searchForm.keyword"
          style="width: 200px"
          placeholder="标题 / ç¼–号 / æ‘˜è¦"
          placeholder="标题"
          clearable
          :prefix-icon="Search"
          @keyup.enter="onSearch"
@@ -16,16 +16,16 @@
        <el-select v-model="searchForm.newsType" placeholder="全部" clearable style="width: 140px">
          <el-option v-for="opt in NEWS_TYPE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
        </el-select>
        <span class="search_title" style="margin-left: 12px">审批状态:</span>
        <span class="search_title" style="margin-left: 12px">状态:</span>
        <el-select v-model="searchForm.status" placeholder="全部" clearable style="width: 120px">
          <el-option
            v-for="opt in APPROVAL_STATUS_SEARCH_OPTIONS"
            v-for="opt in ENTERPRISE_NEWS_STATUS_SEARCH_OPTIONS"
            :key="opt.value"
            :label="opt.label"
            :value="opt.value"
          />
        </el-select>
        <span class="search_title" style="margin-left: 12px">申请日期:</span>
        <span class="search_title" style="margin-left: 12px">创建时间:</span>
        <el-date-picker
          v-model="searchForm.createTimeRange"
          type="daterange"
@@ -72,7 +72,6 @@
      @closed="onTemplateBindClosed"
    />
    <!-- æ–°å»º / ç¼–辑:原企业新闻表单 + æ¨¡æ¿å®¡æ‰¹æµç¨‹ -->
    <el-dialog
      v-model="newsFormDialog.visible"
      :title="newsFormDialog.title"
@@ -171,45 +170,41 @@
        <el-form-item label="政策类必读">
          <el-switch v-model="newsForm.requireReadConfirm" active-text="需阅读确认(便于统计未读)" />
        </el-form-item>
        <el-form-item label="发布人">
          <el-input v-model="newsForm.publisherName" placeholder="如:人力资源部" maxlength="50" />
        </el-form-item>
        <template v-if="activeTemplate">
        <template v-if="hasApprovalTemplate">
          <el-divider content-position="left">审批流程</el-divider>
          <el-form-item label="审批模板">
            <span class="template-name">{{ activeTemplate.label || submitForm.templateName }}</span>
            <span class="template-name">{{ approvalTemplateLabel }}</span>
          </el-form-item>
          <el-form-item label="审批流程" required>
          <el-form-item v-if="activeTemplate" label="审批流程" required>
            <TemplateFlowEditor v-model="submitForm.flowNodes" :user-options="flowUserOptions" />
            <p class="section-tip">流程与审批人由模板预置,可按需微调节点审批人。</p>
          </el-form-item>
        </template>
        <el-alert v-else type="warning" show-icon :closable="false" title="请先通过「新建新闻」选择审批模板" />
        <el-alert
          v-else-if="!isNewsEdit"
          type="warning"
          show-icon
          :closable="false"
          title="请先通过「新建新闻」选择审批模板"
        />
      </el-form>
      <template v-if="!newsFormDialog.readonly" #footer>
        <el-button @click="newsFormDialog.visible = false">取 æ¶ˆ</el-button>
        <el-button :loading="submitSaving" @click="onNewsSave('draft')">存草稿</el-button>
        <el-button type="warning" :loading="submitSaving" @click="onNewsSave('submit_review')">
        <el-button :loading="newsSaving" @click="onNewsSave('draft')">存草稿</el-button>
        <el-button type="warning" :loading="newsSaving" @click="onNewsSave('submit_review')">
          æäº¤å®¡æ ¸
        </el-button>
        <el-button type="primary" :loading="submitSaving" @click="onNewsSave('submit_review')">
        <el-button type="primary" :loading="newsSaving" @click="onNewsSave('submit_review')">
          ä¿ å­˜
        </el-button>
      </template>
    </el-dialog>
    <!-- è¯¦æƒ… -->
    <el-dialog v-model="detailDialog.visible" title="新闻详情" width="880px" append-to-body destroy-on-close>
      <NewsDetailPanel :row="detailNewsRow" />
      <el-divider content-position="left">审批信息</el-divider>
      <ApproveDetailPanel :row="detailRow" />
      <template #footer>
        <el-button
          v-if="canEditBusinessInstanceRow(detailRow)"
          type="primary"
          @click="openNewsEditFromDetail"
        >
        <el-button v-if="canEditEnterpriseNewsRow(detailRow)" type="primary" @click="openNewsEditFromDetail">
          ä¿®æ”¹
        </el-button>
        <el-button @click="detailDialog.visible = false">关 é—­</el-button>
@@ -220,22 +215,27 @@
<script setup>
import { Plus, RefreshRight, Search } from "@element-plus/icons-vue";
import { ElMessage } from "element-plus";
import { ElMessage, ElMessageBox } from "element-plus";
import {
  deleteEnterpriseNews,
  saveEnterpriseNews,
  updateEnterpriseNews,
} from "@/api/officeProcessAutomation/enterpriseNews.js";
import { computed, onMounted, reactive, ref } from "vue";
import useUserStore from "@/store/modules/user";
import Editor from "@/components/Editor/index.vue";
import FileUpload from "@/components/AttachmentUpload/file/index.vue";
import { APPROVAL_STATUS_SEARCH_OPTIONS } from "../../ApproveManage/approve-list/approveListConstants.js";
import ApproveDetailPanel from "../../ApproveManage/approve-list/components/ApproveDetailPanel.vue";
import { buildEditFormFromInstanceRow } from "../../ApproveManage/approve-list/approveListConstants.js";
import ApprovalTemplateBindDialog from "../../ApproveManage/approve-shared/components/ApprovalTemplateBindDialog.vue";
import TemplateFlowEditor from "../../ApproveManage/approve-template/components/TemplateFlowEditor.vue";
import {
  applyBindingToForm,
  validateTemplateBinding,
} from "../../ApproveManage/approve-shared/approvalTemplateBindingUtils.js";
import { createEmptySubmitForm } from "../../ApproveManage/approve-list/approveListConstants.js";
import { APPROVAL_MODULE_KEYS } from "../../ApproveManage/approve-shared/approvalModuleRegistry.js";
import { useApprovalInstanceModule } from "../../ApproveManage/approve-shared/useApprovalInstanceModule.js";
import {
  applyBindingToForm,
  validateTemplateBinding,
} from "../../ApproveManage/approve-shared/approvalTemplateBindingUtils.js";
import { useFlowUserOptions } from "../../ApproveManage/approve-shared/useFlowUserOptions.js";
import NewsDetailPanel from "./components/NewsDetailPanel.vue";
import {
@@ -245,18 +245,18 @@
  PUBLISH_ROLE_OPTIONS,
  DEPT_OPTIONS,
  createEmptyForm,
  ENTERPRISE_NEWS_STATUS_SEARCH_OPTIONS,
  newsTypeColor,
  newsTypeLabel,
  validateNewsForm,
} from "./enterpriseNewsUtils.js";
import {
  enrichEnterpriseNewsListRow,
  extractEnterpriseNewsFromRow,
  syncNewsFormToSubmitPayload,
  buildEnterpriseNewsSaveDto,
  buildEnterpriseNewsTableColumns,
} from "./enterpriseNewsApprovalBridge.js";
const userStore = useUserStore();
  canEditEnterpriseNewsRow,
  mapApiRowToNewsForm,
} from "./enterpriseNewsMappers.js";
import { useEnterpriseNewsList } from "./useEnterpriseNewsList.js";
const searchForm = reactive({
  keyword: "",
@@ -266,6 +266,8 @@
});
const newsFormDialog = reactive({ visible: false, title: "", mode: "add", readonly: false });
const detailDialog = reactive({ visible: false });
const detailRow = ref({});
const newsForm = reactive(createEmptyForm());
const newsFormRef = ref();
const galleryInput = ref("");
@@ -276,66 +278,44 @@
  readScope: [{ required: true, message: "请选择阅读范围", trigger: "change" }],
};
const mod = useApprovalInstanceModule({
  moduleKey: APPROVAL_MODULE_KEYS.ENTERPRISE_NEWS,
  enrichListRow: enrichEnterpriseNewsListRow,
  buildExtraListParams(sf) {
    const extra = {};
    const kw = (sf?.keyword || "").trim();
    if (kw) extra.title = kw;
    if (sf?.newsType) extra.newsType = sf.newsType;
    return extra;
  },
  async beforeSave(submitForm) {
    const v = validateNewsForm(newsForm);
    if (!v.ok) {
      ElMessage.warning(v.message);
      throw new Error(v.message);
    }
    if (!activeTemplate.value) {
      ElMessage.warning("请先选择审批模板");
      throw new Error("no template");
    }
    const bindingCheck = validateTemplateBinding({ flowNodes: submitForm.flowNodes });
    if (!bindingCheck.ok) {
      ElMessage.warning(bindingCheck.message);
      throw new Error(bindingCheck.message);
    }
    syncNewsFormToSubmitPayload(newsForm, submitForm);
  },
});
const newsList = useEnterpriseNewsList();
const { tableData, tableLoading, page, handleQuery: fetchNewsList, pagination: paginateNewsList } =
  newsList;
const {
  tableData,
  tableLoading,
  page,
  detailDialog,
  detailRow,
  submitDialog,
  submitForm,
  submitSaving,
  isSubmitEdit,
  activeTemplate,
  templateBindVisible,
  pendingTemplateBinding,
  submitEditRow,
  handleQuery,
  initModuleList,
  pagination,
  openAddWithTemplate,
  onTemplateBound,
  resetSubmitForm,
  submitInstanceForm,
  removeInstance,
  canEditBusinessInstanceRow,
} = mod;
const submitForm = reactive(createEmptySubmitForm(""));
const templateBindVisible = ref(false);
const pendingTemplateBinding = ref(null);
const newsSaving = ref(false);
const isNewsEdit = computed(() => newsFormDialog.mode === "edit");
const activeTemplate = computed(() => submitForm.templateSnapshot || null);
const hasApprovalTemplate = computed(
  () => Boolean(activeTemplate.value || newsForm.templateId)
);
const approvalTemplateLabel = computed(
  () =>
    activeTemplate.value?.label ||
    newsForm.templateName ||
    submitForm.templateName ||
    "—"
);
const { flowUserOptions, loadFlowUsers } = useFlowUserOptions();
const detailNewsRow = computed(() => {
  if (!detailRow.value?.id) return {};
  return extractEnterpriseNewsFromRow(detailRow.value);
});
function openAddWithTemplate() {
  pendingTemplateBinding.value = null;
  templateBindVisible.value = true;
}
function onTemplateBound(binding) {
  pendingTemplateBinding.value = binding;
}
function resetSubmitForm() {
  Object.assign(submitForm, createEmptySubmitForm(""));
}
const detailNewsRow = computed(() => mapApiRowToNewsForm(detailRow.value));
const tableColumn = ref(
  buildEnterpriseNewsTableColumns(() => [
@@ -343,13 +323,14 @@
    {
      name: "修改",
      type: "text",
      disabled: (row) => !canEditBusinessInstanceRow(row),
      disabled: (row) => !canEditEnterpriseNewsRow(row),
      clickFun: (row) => openNewsEdit(row),
    },
    {
      name: "删除",
      type: "danger",
      clickFun: (row) => removeInstance(row),
      disabled: (row) => !canEditEnterpriseNewsRow(row),
      clickFun: (row) => handleNewsDelete(row),
    },
  ])
);
@@ -364,11 +345,9 @@
  newsFormDialog.title =
    mode === "add" ? "新建企业新闻" : mode === "edit" ? "编辑企业新闻" : "查看企业新闻";
  if (mode === "add") {
    resetNewsForm({
      publisherName: userStore?.nickName || userStore?.name || "当前用户",
    });
    resetNewsForm();
  } else if (row) {
    resetNewsForm(extractEnterpriseNewsFromRow(row));
    resetNewsForm(mapApiRowToNewsForm(row));
  }
  newsFormDialog.visible = true;
}
@@ -379,19 +358,23 @@
  pendingTemplateBinding.value = null;
  resetSubmitForm();
  applyBindingToForm(submitForm, binding);
  submitDialog.mode = "add";
  submitEditRow.value = null;
  if (binding.templateId) {
    newsForm.templateId = binding.templateId;
    newsForm.templateName = binding.templateName || "";
  }
  openNewsFormDialog("add");
}
function openNewsEdit(row) {
  if (!canEditBusinessInstanceRow(row)) {
    ElMessage.warning("进行中或已完成的审批不可修改");
  if (!canEditEnterpriseNewsRow(row)) {
    ElMessage.warning("当前状态不可修改");
    return;
  }
  submitDialog.mode = "edit";
  submitEditRow.value = { ...row };
  Object.assign(submitForm, buildEditFormFromInstanceRow(row));
  resetSubmitForm();
  if (row?.templateId != null) {
    submitForm.templateId = row.templateId;
    submitForm.templateName = row.templateName || "";
  }
  openNewsFormDialog("edit", row);
}
@@ -404,6 +387,40 @@
  const row = detailRow.value;
  detailDialog.visible = false;
  openNewsEdit(row);
}
async function handleNewsDelete(row) {
  if (!canEditEnterpriseNewsRow(row)) {
    ElMessage.warning("当前状态不可删除");
    return;
  }
  if (row?.id == null || row.id === "") {
    ElMessage.warning("无法删除:缺少新闻 ID");
    return;
  }
  const title = (row.title || "").trim() || "该条新闻";
  try {
    await ElMessageBox.confirm(
      `确定要删除「${title}」吗?删除后不可恢复。`,
      "删除确认",
      {
        type: "warning",
        confirmButtonText: "确定删除",
        cancelButtonText: "取消",
        distinguishCancelAndClose: true,
        autofocus: false,
      }
    );
  } catch {
    return;
  }
  try {
    await deleteEnterpriseNews([row.id]);
    ElMessage.success("删除成功");
    await fetchNewsList(searchForm);
  } catch {
    /* é”™è¯¯ç”±è¯·æ±‚拦截器提示 */
  }
}
function onNewsFormClosed() {
@@ -425,19 +442,67 @@
    ElMessage.warning("请完善表单必填项后再保存");
    return;
  }
  if (action === "draft") newsForm.publishStatus = "draft";
  else newsForm.publishStatus = "pending_review";
  const ok = await submitInstanceForm({ skipValidate: true });
  if (ok) {
  const v = validateNewsForm(newsForm);
  if (!v.ok) {
    ElMessage.warning(v.message);
    return;
  }
  const status = action === "draft" ? "DRAFT" : "PENDING";
  newsForm.publishStatus = status;
  if (!isNewsEdit.value) {
    const templateId = newsForm.templateId || submitForm.templateId;
    if (!templateId) {
      ElMessage.warning("请先选择审批模板");
      return;
    }
    if (!newsForm.templateId) newsForm.templateId = templateId;
    if (!newsForm.templateName && submitForm.templateName) {
      newsForm.templateName = submitForm.templateName;
    }
    if (action !== "draft") {
      const bindingCheck = validateTemplateBinding({ flowNodes: submitForm.flowNodes });
      if (!bindingCheck.ok) {
        ElMessage.warning(bindingCheck.message);
        return;
      }
    }
  } else if (!newsForm.templateId && submitForm.templateId) {
    newsForm.templateId = submitForm.templateId;
    newsForm.templateName = submitForm.templateName || newsForm.templateName;
  }
  const dto = buildEnterpriseNewsSaveDto(newsForm, { status });
  if (isNewsEdit.value) {
    if (dto.id == null) {
      ElMessage.warning("无法修改:缺少新闻 ID");
      return;
    }
  }
  if (newsSaving.value) return;
  newsSaving.value = true;
  try {
    if (isNewsEdit.value) {
      await updateEnterpriseNews(dto);
    } else {
      await saveEnterpriseNews(dto);
    }
    newsFormDialog.visible = false;
    const msg =
      action === "draft" ? "已保存草稿" : isSubmitEdit.value ? "修改成功" : "已提交审核";
      action === "draft" ? "已保存草稿" : isNewsEdit.value ? "修改成功" : "已提交审核";
    ElMessage.success(msg);
    if (!isNewsEdit.value) page.current = 1;
    await fetchNewsList(searchForm);
  } catch {
    /* é”™è¯¯ç”±è¯·æ±‚拦截器提示 */
  } finally {
    newsSaving.value = false;
  }
}
function onSearch() {
  handleQuery(searchForm);
  fetchNewsList(searchForm);
}
function resetSearch() {
@@ -449,17 +514,12 @@
}
function onPagination(obj) {
  pagination(obj, searchForm);
  paginateNewsList(obj, searchForm);
}
onMounted(async () => {
  try {
    localStorage.removeItem("oa_enterprise_news_v1");
  } catch {
    /* æ¸…除历史本地演示缓存 */
  }
onMounted(() => {
  loadFlowUsers();
  await initModuleList(searchForm);
  fetchNewsList(searchForm);
});
</script>
src/views/officeProcessAutomation/EnterpriseNews/news-manage/useEnterpriseNewsList.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
import { listEnterpriseNewsPage } from "@/api/officeProcessAutomation/enterpriseNews.js";
import { ElMessage } from "element-plus";
import { reactive, ref } from "vue";
import {
  buildEnterpriseNewsListParams,
  mapEnterpriseNewsFromApi,
  unwrapEnterpriseNewsPage,
} from "./enterpriseNewsMappers.js";
/** ä¼ä¸šæ–°é—»åˆ—表:分页查询 /enterpriseNews/listPage */
export function useEnterpriseNewsList() {
  const tableData = ref([]);
  const tableLoading = ref(false);
  const page = reactive({ current: 1, size: 10, total: 0 });
  let lastSearchForm = null;
  async function fetchList(searchForm = {}) {
    tableLoading.value = true;
    try {
      const res = await listEnterpriseNewsPage(
        buildEnterpriseNewsListParams({ page, searchForm })
      );
      const { records, total } = unwrapEnterpriseNewsPage(res);
      tableData.value = records.map(mapEnterpriseNewsFromApi);
      page.total = total;
    } catch {
      tableData.value = [];
      page.total = 0;
      ElMessage.error("企业新闻列表加载失败");
    } finally {
      tableLoading.value = false;
    }
  }
  function handleQuery(searchForm) {
    lastSearchForm = searchForm;
    page.current = 1;
    return fetchList(searchForm);
  }
  function pagination({ page: p, limit }, searchForm) {
    page.current = p;
    page.size = limit;
    return fetchList(searchForm ?? lastSearchForm ?? {});
  }
  return {
    tableData,
    tableLoading,
    page,
    fetchList,
    handleQuery,
    pagination,
  };
}
src/views/officeProcessAutomation/HrManage/regular-apply/index.vue
@@ -95,11 +95,10 @@
const mod = useApprovalInstanceModule({
  moduleKey: APPROVAL_MODULE_KEYS.REGULAR,
  buildExtraListParams(sf) {
    const range = sf?.applyDateRange;
    if (Array.isArray(range) && range[0]) {
      return { createTime: range[0], createTimeEnd: range[1] };
    }
    return {};
    const extra = {};
    const name = (sf?.applicantName || "").trim();
    if (name) extra.applicantName = name;
    return extra;
  },
});
src/views/officeProcessAutomation/HrManage/transfer-apply/index.vue
@@ -137,11 +137,7 @@
const mod = useApprovalInstanceModule({
  moduleKey: APPROVAL_MODULE_KEYS.TRANSFER,
  buildExtraListParams(sf) {
    const range = sf?.transferDateRange;
    if (Array.isArray(range) && range[0]) {
      return { createTime: range[0], createTimeEnd: range[1] };
    }
  buildExtraListParams() {
    return {};
  },
});