风采审核功能开发
Some checks failed
Node CI / build (14.x, macOS-latest) (push) Has been cancelled
Node CI / build (14.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (14.x, windows-latest) (push) Has been cancelled
Node CI / build (16.x, macOS-latest) (push) Has been cancelled
Node CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (16.x, windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
coverage CI / build (push) Has been cancelled
Node pnpm CI / build (16.x, macOS-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, windows-latest) (push) Has been cancelled
Some checks failed
Node CI / build (14.x, macOS-latest) (push) Has been cancelled
Node CI / build (14.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (14.x, windows-latest) (push) Has been cancelled
Node CI / build (16.x, macOS-latest) (push) Has been cancelled
Node CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (16.x, windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
coverage CI / build (push) Has been cancelled
Node pnpm CI / build (16.x, macOS-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, windows-latest) (push) Has been cancelled
This commit is contained in:
@@ -199,6 +199,11 @@ export default [
|
|||||||
path: '/management/interview-list',
|
path: '/management/interview-list',
|
||||||
component: './Management/InterviewList',
|
component: './Management/InterviewList',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: '风采审核',
|
||||||
|
path: '/management/showcase-review',
|
||||||
|
component: './Management/Showcase',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import {
|
|||||||
message,
|
message,
|
||||||
Typography,
|
Typography,
|
||||||
Modal,
|
Modal,
|
||||||
|
Tag,
|
||||||
|
Tooltip,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import {
|
import {
|
||||||
UploadOutlined,
|
UploadOutlined,
|
||||||
@@ -29,6 +31,9 @@ interface ShowcaseItem {
|
|||||||
type: string;
|
type: string;
|
||||||
url: string;
|
url: string;
|
||||||
createTime: string;
|
createTime: string;
|
||||||
|
id: number;
|
||||||
|
reviewStatus: string; // '0' | '1' | '2'
|
||||||
|
reviewRemark?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 从 getInfoCache 缓存获取 userId */
|
/** 从 getInfoCache 缓存获取 userId */
|
||||||
@@ -75,11 +80,16 @@ const serverFileToItem = (row: {
|
|||||||
id: number;
|
id: number;
|
||||||
fileUrl: string;
|
fileUrl: string;
|
||||||
createTime?: string;
|
createTime?: string;
|
||||||
|
reviewStatus?: string;
|
||||||
|
reviewRemark?: string;
|
||||||
}): ShowcaseItem => ({
|
}): ShowcaseItem => ({
|
||||||
uid: `server-${row.id}`,
|
uid: `server-${row.id}`,
|
||||||
type: guessType(row.fileUrl),
|
type: guessType(row.fileUrl),
|
||||||
url: getFileDisplayUrl(row.fileUrl),
|
url: getFileDisplayUrl(row.fileUrl),
|
||||||
createTime: formatTime(row.createTime),
|
createTime: formatTime(row.createTime),
|
||||||
|
id: row.id,
|
||||||
|
reviewStatus: row.reviewStatus || '0',
|
||||||
|
reviewRemark: row.reviewRemark,
|
||||||
});
|
});
|
||||||
|
|
||||||
const isVideo = (type: string): boolean => type.startsWith('video/');
|
const isVideo = (type: string): boolean => type.startsWith('video/');
|
||||||
@@ -214,34 +224,60 @@ const ShowcasePage: React.FC = () => {
|
|||||||
<Text type="secondary">共 {items.length} 条记录</Text>
|
<Text type="secondary">共 {items.length} 条记录</Text>
|
||||||
</div>
|
</div>
|
||||||
<div className="gallery-grid">
|
<div className="gallery-grid">
|
||||||
{items.map((item) => (
|
{items.map((item) => {
|
||||||
<Card
|
const isPending = item.reviewStatus === '0';
|
||||||
key={item.uid}
|
const isRejected = item.reviewStatus === '2';
|
||||||
className="gallery-card"
|
return (
|
||||||
hoverable
|
<Card
|
||||||
cover={
|
key={item.uid}
|
||||||
isVideo(item.type) ? (
|
className={`gallery-card${isPending || isRejected ? ' gallery-card--dimmed' : ''}`}
|
||||||
<div className="video-cover" onClick={() => setPreviewItem(item)}>
|
hoverable={!isPending}
|
||||||
<video src={item.url} className="gallery-video" />
|
cover={
|
||||||
<div className="video-play-mask">
|
isVideo(item.type) ? (
|
||||||
<VideoCameraOutlined />
|
<div
|
||||||
|
className="video-cover"
|
||||||
|
onClick={() => !isPending && setPreviewItem(item)}
|
||||||
|
style={isPending || isRejected ? { pointerEvents: 'none', opacity: 0.5 } : undefined}
|
||||||
|
>
|
||||||
|
<video src={item.url} className="gallery-video" />
|
||||||
|
<div className="video-play-mask">
|
||||||
|
<VideoCameraOutlined />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
) : (
|
||||||
) : (
|
<div className="image-cover" style={isPending || isRejected ? { opacity: 0.5 } : undefined}>
|
||||||
<div className="image-cover">
|
<Image
|
||||||
<Image
|
src={item.url}
|
||||||
src={item.url}
|
alt="风采图片"
|
||||||
alt="风采图片"
|
className="gallery-image"
|
||||||
className="gallery-image"
|
preview={isPending || isRejected ? false : { mask: <CameraOutlined /> }}
|
||||||
preview={{ mask: <CameraOutlined /> }}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
)
|
||||||
)
|
}
|
||||||
}
|
>
|
||||||
>
|
<Card.Meta
|
||||||
<Card.Meta description={<Text type="secondary">上传时间:{item.createTime}</Text>} />
|
description={
|
||||||
</Card>
|
<div>
|
||||||
))}
|
<Text type="secondary">上传时间:{item.createTime}</Text>
|
||||||
|
{isPending && (
|
||||||
|
<div style={{ marginTop: 8 }}>
|
||||||
|
<Tag color="orange">审核中</Tag>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{isRejected && (
|
||||||
|
<div style={{ marginTop: 8 }}>
|
||||||
|
<Tooltip title={`驳回原因:${item.reviewRemark || '无'}`}>
|
||||||
|
<Tag color="error">审核未通过</Tag>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import {
|
|||||||
message,
|
message,
|
||||||
Typography,
|
Typography,
|
||||||
Modal,
|
Modal,
|
||||||
|
Tag,
|
||||||
|
Tooltip,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import {
|
import {
|
||||||
UploadOutlined,
|
UploadOutlined,
|
||||||
@@ -29,6 +31,9 @@ interface ShowcaseItem {
|
|||||||
type: string;
|
type: string;
|
||||||
url: string;
|
url: string;
|
||||||
createTime: string;
|
createTime: string;
|
||||||
|
id: number;
|
||||||
|
reviewStatus: string; // '0' | '1' | '2'
|
||||||
|
reviewRemark?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 从 getInfoCache 缓存获取 userId */
|
/** 从 getInfoCache 缓存获取 userId */
|
||||||
@@ -75,11 +80,16 @@ const serverFileToItem = (row: {
|
|||||||
id: number;
|
id: number;
|
||||||
fileUrl: string;
|
fileUrl: string;
|
||||||
createTime?: string;
|
createTime?: string;
|
||||||
|
reviewStatus?: string;
|
||||||
|
reviewRemark?: string;
|
||||||
}): ShowcaseItem => ({
|
}): ShowcaseItem => ({
|
||||||
uid: `server-${row.id}`,
|
uid: `server-${row.id}`,
|
||||||
type: guessType(row.fileUrl),
|
type: guessType(row.fileUrl),
|
||||||
url: getFileDisplayUrl(row.fileUrl),
|
url: getFileDisplayUrl(row.fileUrl),
|
||||||
createTime: formatTime(row.createTime),
|
createTime: formatTime(row.createTime),
|
||||||
|
id: row.id,
|
||||||
|
reviewStatus: row.reviewStatus || '0',
|
||||||
|
reviewRemark: row.reviewRemark,
|
||||||
});
|
});
|
||||||
|
|
||||||
const isVideo = (type: string): boolean => type.startsWith('video/');
|
const isVideo = (type: string): boolean => type.startsWith('video/');
|
||||||
@@ -209,34 +219,60 @@ const EnterpriseShowcase: React.FC = () => {
|
|||||||
<Text type="secondary">共 {items.length} 条记录</Text>
|
<Text type="secondary">共 {items.length} 条记录</Text>
|
||||||
</div>
|
</div>
|
||||||
<div className="es-gallery-grid">
|
<div className="es-gallery-grid">
|
||||||
{items.map((item) => (
|
{items.map((item) => {
|
||||||
<Card
|
const isPending = item.reviewStatus === '0';
|
||||||
key={item.uid}
|
const isRejected = item.reviewStatus === '2';
|
||||||
className="es-gallery-card"
|
return (
|
||||||
hoverable
|
<Card
|
||||||
cover={
|
key={item.uid}
|
||||||
isVideo(item.type) ? (
|
className={`es-gallery-card${isPending || isRejected ? ' es-gallery-card--dimmed' : ''}`}
|
||||||
<div className="es-video-cover" onClick={() => setPreviewItem(item)}>
|
hoverable={!isPending}
|
||||||
<video src={item.url} className="es-gallery-video" />
|
cover={
|
||||||
<div className="es-video-play-mask">
|
isVideo(item.type) ? (
|
||||||
<VideoCameraOutlined />
|
<div
|
||||||
|
className="es-video-cover"
|
||||||
|
onClick={() => !isPending && setPreviewItem(item)}
|
||||||
|
style={isPending || isRejected ? { pointerEvents: 'none', opacity: 0.5 } : undefined}
|
||||||
|
>
|
||||||
|
<video src={item.url} className="es-gallery-video" />
|
||||||
|
<div className="es-video-play-mask">
|
||||||
|
<VideoCameraOutlined />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
) : (
|
||||||
) : (
|
<div className="es-image-cover" style={isPending || isRejected ? { opacity: 0.5 } : undefined}>
|
||||||
<div className="es-image-cover">
|
<Image
|
||||||
<Image
|
src={item.url}
|
||||||
src={item.url}
|
alt="企业风采图片"
|
||||||
alt="企业风采图片"
|
className="es-gallery-image"
|
||||||
className="es-gallery-image"
|
preview={isPending || isRejected ? false : { mask: <CameraOutlined /> }}
|
||||||
preview={{ mask: <CameraOutlined /> }}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
)
|
||||||
)
|
}
|
||||||
}
|
>
|
||||||
>
|
<Card.Meta
|
||||||
<Card.Meta description={<Text type="secondary">上传时间:{item.createTime}</Text>} />
|
description={
|
||||||
</Card>
|
<div>
|
||||||
))}
|
<Text type="secondary">上传时间:{item.createTime}</Text>
|
||||||
|
{isPending && (
|
||||||
|
<div style={{ marginTop: 8 }}>
|
||||||
|
<Tag color="orange">审核中</Tag>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{isRejected && (
|
||||||
|
<div style={{ marginTop: 8 }}>
|
||||||
|
<Tooltip title={`驳回原因:${item.reviewRemark || '无'}`}>
|
||||||
|
<Tag color="error">审核未通过</Tag>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
325
src/pages/Management/Showcase/index.tsx
Normal file
325
src/pages/Management/Showcase/index.tsx
Normal file
@@ -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<ActionType>();
|
||||||
|
|
||||||
|
const [approvalVisible, setApprovalVisible] = useState(false);
|
||||||
|
const [currentRow, setCurrentRow] = useState<ShowcaseReviewItem | null>(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<ShowcaseReviewItem>[] = [
|
||||||
|
{
|
||||||
|
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 (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 80,
|
||||||
|
height: 60,
|
||||||
|
background: '#000',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
cursor: 'pointer',
|
||||||
|
borderRadius: 4,
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
setPreviewUrl(url);
|
||||||
|
setPreviewVisible(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<video src={url} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
|
||||||
|
<EyeOutlined style={{ position: 'absolute', color: '#fff', fontSize: 20 }} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
src={url}
|
||||||
|
width={80}
|
||||||
|
height={60}
|
||||||
|
style={{ objectFit: 'cover', borderRadius: 4 }}
|
||||||
|
preview={{ mask: <EyeOutlined /> }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '类型',
|
||||||
|
dataIndex: 'fileUrl',
|
||||||
|
width: 80,
|
||||||
|
search: false,
|
||||||
|
render: (_, record) => (
|
||||||
|
<Tag>{isVideo(record.fileUrl) ? '视频' : '图片'}</Tag>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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<string, { color: string; text: string }> = {
|
||||||
|
'0': { color: 'orange', text: '待审核' },
|
||||||
|
'1': { color: 'green', text: '已通过' },
|
||||||
|
'2': { color: 'red', text: '已驳回' },
|
||||||
|
};
|
||||||
|
const info = map[status] || map['0'];
|
||||||
|
return <Tag color={info.color}>{info.text}</Tag>;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '审核备注',
|
||||||
|
dataIndex: 'reviewRemark',
|
||||||
|
width: 200,
|
||||||
|
search: false,
|
||||||
|
ellipsis: true,
|
||||||
|
render: (_, record) => {
|
||||||
|
if (!record.reviewRemark) return '-';
|
||||||
|
return (
|
||||||
|
<Tooltip title={record.reviewRemark}>
|
||||||
|
<span>{record.reviewRemark}</span>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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 (
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
hidden={!access.hasPerms('cms:showcase:review')}
|
||||||
|
onClick={() => handleReview(record)}
|
||||||
|
>
|
||||||
|
审核
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ProTable<ShowcaseReviewItem>
|
||||||
|
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' }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 审核弹窗 */}
|
||||||
|
<Modal
|
||||||
|
title="风采审核"
|
||||||
|
open={approvalVisible}
|
||||||
|
width={520}
|
||||||
|
onCancel={() => {
|
||||||
|
setApprovalVisible(false);
|
||||||
|
setApprovalRemark('');
|
||||||
|
setCurrentRow(null);
|
||||||
|
}}
|
||||||
|
footer={null}
|
||||||
|
destroyOnClose
|
||||||
|
>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
||||||
|
<div>
|
||||||
|
<span style={{ marginRight: 12 }}>审核结果:</span>
|
||||||
|
<label style={{ marginRight: 16 }}>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="approvalStatus"
|
||||||
|
checked={approvalStatus === '1'}
|
||||||
|
onChange={() => setApprovalStatus('1')}
|
||||||
|
/>
|
||||||
|
<span style={{ marginLeft: 6 }}>通过</span>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="approvalStatus"
|
||||||
|
checked={approvalStatus === '2'}
|
||||||
|
onChange={() => setApprovalStatus('2')}
|
||||||
|
/>
|
||||||
|
<span style={{ marginLeft: 6 }}>驳回</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{approvalStatus === '2' && (
|
||||||
|
<div>
|
||||||
|
<div style={{ marginBottom: 6 }}>驳回原因(必填):</div>
|
||||||
|
<textarea
|
||||||
|
style={{ width: '100%', minHeight: 100, padding: '8px 12px', borderRadius: 6, border: '1px solid #d9d9d9' }}
|
||||||
|
placeholder="请输入驳回原因"
|
||||||
|
value={approvalRemark}
|
||||||
|
onChange={(e) => setApprovalRemark(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div style={{ textAlign: 'right', marginTop: 8 }}>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setApprovalVisible(false);
|
||||||
|
setApprovalRemark('');
|
||||||
|
}}
|
||||||
|
style={{ marginRight: 8 }}
|
||||||
|
>
|
||||||
|
取消
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
danger={approvalStatus === '2'}
|
||||||
|
loading={submitting}
|
||||||
|
onClick={handleSubmit}
|
||||||
|
>
|
||||||
|
确认
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
{/* 视频预览弹窗 */}
|
||||||
|
<Modal
|
||||||
|
title="视频预览"
|
||||||
|
open={previewVisible}
|
||||||
|
footer={null}
|
||||||
|
onCancel={() => setPreviewVisible(false)}
|
||||||
|
width={800}
|
||||||
|
destroyOnClose
|
||||||
|
>
|
||||||
|
{previewUrl && (
|
||||||
|
<video
|
||||||
|
src={previewUrl}
|
||||||
|
controls
|
||||||
|
autoPlay
|
||||||
|
style={{ width: '100%', display: 'block' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ShowcaseReview;
|
||||||
46
src/services/Management/showcaseReview.ts
Normal file
46
src/services/Management/showcaseReview.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { request } from '@umijs/max';
|
||||||
|
|
||||||
|
/** 风采审核列表项 */
|
||||||
|
export interface ShowcaseReviewItem {
|
||||||
|
id: number;
|
||||||
|
fileUrl: string;
|
||||||
|
bussinessid: number;
|
||||||
|
reviewStatus: string; // '0'=待审核, '1'=审核通过, '2'=审核未通过
|
||||||
|
reviewRemark?: string;
|
||||||
|
reviewBy?: string;
|
||||||
|
reviewTime?: string;
|
||||||
|
createTime: string;
|
||||||
|
updateTime?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 风采审核列表查询参数 */
|
||||||
|
export interface ShowcaseReviewListParams {
|
||||||
|
current?: number;
|
||||||
|
pageSize?: number;
|
||||||
|
bussinessid?: number;
|
||||||
|
reviewStatus?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 风采审核操作参数 */
|
||||||
|
export interface ShowcaseApprovalParams {
|
||||||
|
id: number;
|
||||||
|
reviewStatus: '1' | '2'; // 1=通过, 2=驳回
|
||||||
|
reviewRemark?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取风采审核列表 GET /api/cms/file/review/list */
|
||||||
|
export async function getShowcaseReviewList(params: ShowcaseReviewListParams) {
|
||||||
|
return request<{ code: number; total: number; rows: ShowcaseReviewItem[] }>(
|
||||||
|
'/api/cms/file/review/list',
|
||||||
|
{ method: 'GET', params },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 审核风采(通过/驳回) PUT /api/cms/file/review/{id} */
|
||||||
|
export async function reviewShowcase(params: ShowcaseApprovalParams) {
|
||||||
|
const { id, ...data } = params;
|
||||||
|
return request<{ code: number; msg: string }>(`/api/cms/file/review/${id}`, {
|
||||||
|
method: 'PUT',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user