From 82360505461675e49fa3f55d6b03fe20e84d4f41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=AF=E8=BE=89?= Date: Tue, 7 Jul 2026 19:48:37 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A3=8E=E9=87=87=E5=AE=A1=E6=A0=B8=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/routes.ts | 5 + .../PersonalCenter/Showcase/index.tsx | 90 +++-- .../Management/EnterpriseShowcase/index.tsx | 90 +++-- src/pages/Management/Showcase/index.tsx | 325 ++++++++++++++++++ src/services/Management/showcaseReview.ts | 46 +++ 5 files changed, 502 insertions(+), 54 deletions(-) create mode 100644 src/pages/Management/Showcase/index.tsx create mode 100644 src/services/Management/showcaseReview.ts diff --git a/config/routes.ts b/config/routes.ts index 0da0fa4..7252283 100644 --- a/config/routes.ts +++ b/config/routes.ts @@ -199,6 +199,11 @@ export default [ path: '/management/interview-list', component: './Management/InterviewList', }, + { + name: '风采审核', + path: '/management/showcase-review', + component: './Management/Showcase', + }, ], }, { diff --git a/src/pages/JobPortal/PersonalCenter/Showcase/index.tsx b/src/pages/JobPortal/PersonalCenter/Showcase/index.tsx index f23a0ad..8d29c2d 100644 --- a/src/pages/JobPortal/PersonalCenter/Showcase/index.tsx +++ b/src/pages/JobPortal/PersonalCenter/Showcase/index.tsx @@ -9,6 +9,8 @@ import { message, Typography, Modal, + Tag, + Tooltip, } from 'antd'; import { UploadOutlined, @@ -29,6 +31,9 @@ interface ShowcaseItem { type: string; url: string; createTime: string; + id: number; + reviewStatus: string; // '0' | '1' | '2' + reviewRemark?: string; } /** 从 getInfoCache 缓存获取 userId */ @@ -75,11 +80,16 @@ const serverFileToItem = (row: { id: number; fileUrl: string; createTime?: string; + reviewStatus?: string; + reviewRemark?: string; }): ShowcaseItem => ({ uid: `server-${row.id}`, type: guessType(row.fileUrl), url: getFileDisplayUrl(row.fileUrl), createTime: formatTime(row.createTime), + id: row.id, + reviewStatus: row.reviewStatus || '0', + reviewRemark: row.reviewRemark, }); const isVideo = (type: string): boolean => type.startsWith('video/'); @@ -214,34 +224,60 @@ const ShowcasePage: React.FC = () => { 共 {items.length} 条记录
- {items.map((item) => ( - setPreviewItem(item)}> -
- ) : ( -
- 风采图片 }} - /> -
- ) - } - > - 上传时间:{item.createTime}} /> - - ))} + ) : ( +
+ 风采图片 }} + /> +
+ ) + } + > + + 上传时间:{item.createTime} + {isPending && ( +
+ 审核中 +
+ )} + {isRejected && ( +
+ + 审核未通过 + +
+ )} + + } + /> + + ); + })} )} diff --git a/src/pages/Management/EnterpriseShowcase/index.tsx b/src/pages/Management/EnterpriseShowcase/index.tsx index aee8b9f..4199ffa 100644 --- a/src/pages/Management/EnterpriseShowcase/index.tsx +++ b/src/pages/Management/EnterpriseShowcase/index.tsx @@ -9,6 +9,8 @@ import { message, Typography, Modal, + Tag, + Tooltip, } from 'antd'; import { UploadOutlined, @@ -29,6 +31,9 @@ interface ShowcaseItem { type: string; url: string; createTime: string; + id: number; + reviewStatus: string; // '0' | '1' | '2' + reviewRemark?: string; } /** 从 getInfoCache 缓存获取 userId */ @@ -75,11 +80,16 @@ const serverFileToItem = (row: { id: number; fileUrl: string; createTime?: string; + reviewStatus?: string; + reviewRemark?: string; }): ShowcaseItem => ({ uid: `server-${row.id}`, type: guessType(row.fileUrl), url: getFileDisplayUrl(row.fileUrl), createTime: formatTime(row.createTime), + id: row.id, + reviewStatus: row.reviewStatus || '0', + reviewRemark: row.reviewRemark, }); const isVideo = (type: string): boolean => type.startsWith('video/'); @@ -209,34 +219,60 @@ const EnterpriseShowcase: React.FC = () => { 共 {items.length} 条记录
- {items.map((item) => ( - setPreviewItem(item)}> -
- ) : ( -
- 企业风采图片 }} - /> -
- ) - } - > - 上传时间:{item.createTime}} /> - - ))} + ) : ( +
+ 企业风采图片 }} + /> +
+ ) + } + > + + 上传时间:{item.createTime} + {isPending && ( +
+ 审核中 +
+ )} + {isRejected && ( +
+ + 审核未通过 + +
+ )} + + } + /> + + ); + })} )} diff --git a/src/pages/Management/Showcase/index.tsx b/src/pages/Management/Showcase/index.tsx new file mode 100644 index 0000000..7fad1eb --- /dev/null +++ b/src/pages/Management/Showcase/index.tsx @@ -0,0 +1,325 @@ +import React, { useRef, useState } from 'react'; +import { useAccess } from '@umijs/max'; +import { Button, Image, message, Modal, Tag, Tooltip } from 'antd'; +import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components'; +import { EyeOutlined } from '@ant-design/icons'; +import { + getShowcaseReviewList, + reviewShowcase, + type ShowcaseReviewItem, +} from '@/services/Management/showcaseReview'; +import { getFileDisplayUrl } from '@/utils/fileUrl'; + +/** 根据文件名后缀推断类型 */ +const guessType = (filename: string): string => { + const ext = filename.split('.').pop()?.toLowerCase() || ''; + const videoExts = ['mp4', 'mov', 'avi', 'wmv', 'flv', 'mkv', 'webm', 'm4v']; + if (videoExts.includes(ext)) return 'video'; + return 'image'; +}; + +const isVideo = (fileUrl: string): boolean => guessType(fileUrl) === 'video'; + +const statusValueEnum = { + '0': { text: '待审核', status: 'Processing' }, + '1': { text: '已通过', status: 'Success' }, + '2': { text: '已驳回', status: 'Error' }, +}; + +const ShowcaseReview: React.FC = () => { + const access = useAccess(); + const actionRef = useRef(); + + const [approvalVisible, setApprovalVisible] = useState(false); + const [currentRow, setCurrentRow] = useState(null); + const [approvalStatus, setApprovalStatus] = useState<'1' | '2'>('1'); + const [approvalRemark, setApprovalRemark] = useState(''); + const [submitting, setSubmitting] = useState(false); + const [previewVisible, setPreviewVisible] = useState(false); + const [previewUrl, setPreviewUrl] = useState(''); + + const handleReview = (record: ShowcaseReviewItem) => { + setCurrentRow(record); + setApprovalStatus('1'); + setApprovalRemark(''); + setApprovalVisible(true); + }; + + const handleSubmit = async () => { + if (!currentRow) return; + + if (approvalStatus === '2' && !approvalRemark.trim()) { + message.warning('请填写驳回原因'); + return; + } + + try { + setSubmitting(true); + const resp = await reviewShowcase({ + id: currentRow.id, + reviewStatus: approvalStatus, + reviewRemark: approvalStatus === '2' ? approvalRemark.trim() : undefined, + }); + + if (resp?.code === 200) { + message.success('审核成功'); + setApprovalVisible(false); + setCurrentRow(null); + setApprovalRemark(''); + actionRef.current?.reload(); + } else { + message.error(resp?.msg || '审核失败'); + } + } catch (error) { + message.error('审核失败,请重试'); + } finally { + setSubmitting(false); + } + }; + + const columns: ProColumns[] = [ + { + title: 'ID', + dataIndex: 'id', + width: 80, + search: false, + }, + { + title: '预览', + dataIndex: 'fileUrl', + width: 100, + search: false, + render: (_, record) => { + const url = getFileDisplayUrl(record.fileUrl); + if (isVideo(record.fileUrl)) { + return ( +
{ + setPreviewUrl(url); + setPreviewVisible(true); + }} + > +
+ ); + } + return ( + }} + /> + ); + }, + }, + { + title: '类型', + dataIndex: 'fileUrl', + width: 80, + search: false, + render: (_, record) => ( + {isVideo(record.fileUrl) ? '视频' : '图片'} + ), + }, + { + title: '上传用户ID', + dataIndex: 'bussinessid', + width: 120, + fieldProps: { placeholder: '输入用户ID' }, + }, + { + title: '审核状态', + dataIndex: 'reviewStatus', + width: 100, + valueType: 'select', + valueEnum: statusValueEnum, + render: (_, record) => { + const status = record.reviewStatus || '0'; + const map: Record = { + '0': { color: 'orange', text: '待审核' }, + '1': { color: 'green', text: '已通过' }, + '2': { color: 'red', text: '已驳回' }, + }; + const info = map[status] || map['0']; + return {info.text}; + }, + }, + { + title: '审核备注', + dataIndex: 'reviewRemark', + width: 200, + search: false, + ellipsis: true, + render: (_, record) => { + if (!record.reviewRemark) return '-'; + return ( + + {record.reviewRemark} + + ); + }, + }, + { + title: '审核时间', + dataIndex: 'reviewTime', + width: 160, + search: false, + render: (_, record) => record.reviewTime || '-', + }, + { + title: '上传时间', + dataIndex: 'createTime', + width: 160, + search: false, + }, + { + title: '操作', + dataIndex: 'option', + valueType: 'option', + width: 100, + render: (_, record) => { + const isPending = (record.reviewStatus || '0') === '0'; + if (!isPending) return '-'; + return ( + + ); + }, + }, + ]; + + return ( + <> + + headerTitle="风采审核管理" + actionRef={actionRef} + rowKey="id" + search={{ labelWidth: 100 }} + request={async (params) => { + const { current, pageSize, bussinessid, reviewStatus } = params; + const res = await getShowcaseReviewList({ + current, + pageSize, + bussinessid: bussinessid ? Number(bussinessid) : undefined, + reviewStatus, + }); + return { + data: res?.rows || [], + total: res?.total || 0, + success: res?.code === 200, + }; + }} + columns={columns} + scroll={{ x: 'max-content' }} + /> + + {/* 审核弹窗 */} + { + setApprovalVisible(false); + setApprovalRemark(''); + setCurrentRow(null); + }} + footer={null} + destroyOnClose + > +
+
+ 审核结果: + + +
+ {approvalStatus === '2' && ( +
+
驳回原因(必填):
+