| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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, |
| | | }); |
| | | } |
| | |
| | | |
| | | /** å表æ¥è¯¢ï¼å®¡æ¹ç¶æï¼ä¸å端 status æä¸¾ä¸è´ï¼ */ |
| | | export const APPROVAL_STATUS_SEARCH_OPTIONS = [ |
| | | { value: "DRAFT", label: "è稿" }, |
| | | { value: "PENDING", label: "å¾
审æ¹" }, |
| | | { value: "APPROVED", label: "å·²éè¿" }, |
| | | { value: "REJECTED", label: "已驳å" }, |
| | |
| | | |
| | | /** |
| | | * 审æ¹ç¶æå±ç¤ºï¼ä¸å端 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 ""; |
| | | } |
| | | |
| | | /** æäº¤å¼¹çªï¼æ¨¡æ¿å¡çï¼æ¥èªå端åè¡¨ï¼ */ |
| | |
| | | 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 || ""; |
| | |
| | | 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); |
| | |
| | | /** å页å表项 â è¡¨æ ¼è¡ */ |
| | | 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 ?? ""); |
| | |
| | | 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, |
| | |
| | | } |
| | | |
| | | 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 !== "") { |
| | |
| | | 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]; |
| | |
| | | /** ä¸å¡ç³è¯·é¡µç¶æææ¡ï¼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 "已驳å"; |
| | |
| | | |
| | | 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"; |
| | |
| | | |
| | | 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"; |
| | |
| | | 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 ç»å®ï¼å±ç¤ºç¨æ ¼å¼åå¼ï¼ |
| | |
| | | displayRow[f.key] = text; |
| | | } |
| | | |
| | | for (const key of PRESERVE_INSTANCE_FIELDS) { |
| | | if (row[key] !== undefined) displayRow[key] = row[key]; |
| | | } |
| | | |
| | | return displayRow; |
| | | } |
| | | |
| | |
| | | <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="æ°é»åç±»"> |
| | |
| | | </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')"> |
| | |
| | | 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"; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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(), |
| | | }, |
| | | ]; |
| | | } |
| | |
| | | { 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 = [ |
| | |
| | | } |
| | | |
| | | 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) { |
| | |
| | | readScope: "all", |
| | | targetDeptIds: [], |
| | | targetUserIds: [], |
| | | publishStatus: "draft", |
| | | publishStatus: "DRAFT", |
| | | publisherName: "", |
| | | publishTime: "", |
| | | readRecords: [], |
| | |
| | | versions: [], |
| | | versionNo: 1, |
| | | requireReadConfirm: false, |
| | | templateId: null, |
| | | templateName: "", |
| | | }; |
| | | } |
| | | |
| | |
| | | <!--OA模åï¼EnterpriseNews ä¼ä¸æ°é»ï¼å表走审æ¹å®ä¾ï¼æ°å¢/ä¿®æ¹ä¿çå表å + 模æ¿å®¡æ¹æµç¨ï¼--> |
| | | <!--OA模åï¼EnterpriseNews ä¼ä¸æ°é»ï¼listPage|save|update|deleteï¼æ°å»ºä¿çå®¡æ¹æ¨¡æ¿ï¼--> |
| | | <template> |
| | | <div class="app-container enterprise-news-page"> |
| | | <div class="search_form mb20"> |
| | |
| | | <el-input |
| | | v-model="searchForm.keyword" |
| | | style="width: 200px" |
| | | placeholder="æ é¢ / ç¼å· / æè¦" |
| | | placeholder="æ é¢" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @keyup.enter="onSearch" |
| | |
| | | <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" |
| | |
| | | @closed="onTemplateBindClosed" |
| | | /> |
| | | |
| | | <!-- æ°å»º / ç¼è¾ï¼åä¼ä¸æ°é»è¡¨å + 模æ¿å®¡æ¹æµç¨ --> |
| | | <el-dialog |
| | | v-model="newsFormDialog.visible" |
| | | :title="newsFormDialog.title" |
| | |
| | | <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> |
| | |
| | | |
| | | <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 { |
| | |
| | | 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: "", |
| | |
| | | }); |
| | | |
| | | 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(""); |
| | |
| | | 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(() => [ |
| | |
| | | { |
| | | 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), |
| | | }, |
| | | ]) |
| | | ); |
| | |
| | | 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; |
| | | } |
| | |
| | | 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); |
| | | } |
| | | |
| | |
| | | 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() { |
| | |
| | | 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() { |
| | |
| | | } |
| | | |
| | | 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> |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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, |
| | | }; |
| | | } |
| | |
| | | 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; |
| | | }, |
| | | }); |
| | | |
| | |
| | | |
| | | 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 {}; |
| | | }, |
| | | }); |