diff --git a/config/routes.ts b/config/routes.ts index 906f106..9378221 100644 --- a/config/routes.ts +++ b/config/routes.ts @@ -110,7 +110,26 @@ export default [ hideInMenu: true, component: './RequirementAudits/detail', }, - ], + ], + }, + { + name: '采购员审核', + path: '/purchase-agent', + icon: 'verified', + access: 'purchaseAgentQuery', + routes: [ + { + path: '', + name: '采购员审核', + component: './PurchaseAgentList', + }, + { + name: '详情', + path: 'detail/:id', + hideInMenu: true, + component: './PurchaseAgentList/detail', + }, + ], }, { name: '商家管理', diff --git a/src/pages/FashionTrend/components/UpdateForm.tsx b/src/pages/FashionTrend/components/UpdateForm.tsx index 8f02a20..a104303 100644 --- a/src/pages/FashionTrend/components/UpdateForm.tsx +++ b/src/pages/FashionTrend/components/UpdateForm.tsx @@ -1,7 +1,8 @@ -import React, { useRef, useState } from 'react'; -import { DrawerForm, ProFormInstance, ProFormText, ProFormUploadButton, ProFormRadio, ProFormTextArea } from '@ant-design/pro-components'; +import React, { useEffect, useRef, useState } from 'react'; +import { DrawerForm, ProFormInstance, ProFormText, ProFormUploadButton, ProFormRadio, ProFormTextArea, ProForm } from '@ant-design/pro-components'; import { message } from 'antd'; import Upload, { RcFile } from 'antd/es/upload'; +import { Editor } from '@/components/Editor'; export type FormValueType = { target?: string; @@ -20,7 +21,68 @@ export type UpdateFormProps = { const UpdateForm: React.FC = (props) => { const formRef = useRef(); - const [pbcType, setPbcType] = useState(props.values.pbcType || 1) + const [pbcType, setPbcType] = useState(1); + const [videoThumbnail, setVideoThumbnail] = useState(""); + + useEffect(() => { + setPbcType(props.values.pbcType || 1) + setVideoThumbnail(props.values.pbcThumbNail || "") + }, [props.values.pbcId]); + + // 生成视频缩略图的函数 + const generateVideoThumbnail = async (videoUrl: string) => { + try { + // 创建视频元素 + const video = document.createElement('video'); + video.crossOrigin = 'anonymous'; + video.src = videoUrl; + video.muted = true; + + // 监听视频加载完成事件 + await new Promise((resolve, reject) => { + video.onloadeddata = resolve; + video.onerror = reject; + // 设置超时 + setTimeout(reject, 5000); + }); + + // 播放视频并暂停在第一帧 + video.currentTime = 0; + await new Promise(resolve => {setTimeout(resolve, 200)}); + + // 创建canvas并绘制视频帧 + const canvas = document.createElement('canvas'); + canvas.width = video.videoWidth; + canvas.height = video.videoHeight; + const ctx = canvas.getContext('2d'); + ctx?.drawImage(video, 0, 0, canvas.width, canvas.height); + + // 将canvas转为blob + const blob = await new Promise((resolve) => { + canvas.toBlob((b) => resolve(b as Blob), 'image/jpeg', 0.95); + }); + + // 创建FormData并上传 + const formData = new FormData(); + formData.append('file', blob, 'thumbnail.jpg'); + + // 发送请求上传缩略图 + const response = await fetch(`${process.env.BASE_URL}/oss/imgUpload`, { + method: 'POST', + headers: { + authorization: localStorage.getItem('token') ?? '', + }, + body: formData, + }); + + const result = await response.json(); + if (result.retcode) { + setVideoThumbnail(result.data); + } + } catch (error) { + console.error('生成视频缩略图失败:', error); + } + }; return ( = (props) => { formRef={formRef} onFinish={async (value: any) => { let pbcPicAddress = "" + let pbcThumbNail = "" if (value.pbcType === 1 && value.pbcImage.length > 0) { + pbcThumbNail = value.pbcImage[0].url || value.pbcImage[0].response.data; pbcPicAddress = value.pbcImage.map((e: any) => { return e.url || e.response.data; }).join(','); } else if (value.pbcType === 2 && value.pbcVideo.length > 0) { pbcPicAddress = value.pbcVideo[0].url || value.pbcVideo[0].response.data; + pbcThumbNail = videoThumbnail; } - return props.onSubmit({ ...value, pbcPicAddress, pbcId: props.values.pbcId }) + return props.onSubmit({ ...value, pbcPicAddress, pbcThumbNail, pbcId: props.values.pbcId }) }} drawerProps={{ destroyOnClose: true, @@ -104,6 +169,7 @@ const UpdateForm: React.FC = (props) => { setPbcType(e.target.value) formRef.current?.setFieldValue('pbcImage', []); formRef.current?.setFieldValue('pbcVideo', []); + formRef.current?.setFieldValue('pbcContent', ''); }, }} /> @@ -123,7 +189,7 @@ const UpdateForm: React.FC = (props) => { case 'done': if (info.file.response.retcode === 0) { message.error(info.file.response.retmsg); - formRef.current?.setFieldValue('pbcContent', []) + formRef.current?.setFieldValue('pbcImage', []) } break; default: @@ -169,6 +235,10 @@ const UpdateForm: React.FC = (props) => { if (info.file.response.retcode === 0) { message.error(info.file.response.retmsg); formRef.current?.setFieldValue('pbcVideo', []) + } else if (info.file.response && info.file.response.retcode) { + // 视频上传成功后,获取视频首帧作为缩略图 + const videoUrl = info.file.response.data; + generateVideoThumbnail(videoUrl); } break; default: @@ -197,12 +267,24 @@ const UpdateForm: React.FC = (props) => { { required: true, message: '请上传视频' }, ]} />} + {pbcType === 1 ? + + : + ]} />} ); }; diff --git a/src/pages/PurchaseAgentList/detail.tsx b/src/pages/PurchaseAgentList/detail.tsx new file mode 100644 index 0000000..6b1f40a --- /dev/null +++ b/src/pages/PurchaseAgentList/detail.tsx @@ -0,0 +1,125 @@ +import { + judgePurchaseAgentForAdminUsingGet, + purchaseAgentDetailForAdminUsingGet, +} from '@/services/pop-b2b2c/pbcPurchaseAgentInfoController'; +import { ProCard } from '@ant-design/pro-components'; +import { PageContainer } from '@ant-design/pro-layout'; +import { Access, useAccess, useParams } from '@umijs/max'; +import { Button, Descriptions, Image, message } from 'antd'; +import React, { useEffect, useState } from 'react'; + +const Detail: React.FC = () => { + const params = useParams(); + const access: any = useAccess(); + + const [info, setInfo] = useState({}); + + const getInfo = () => { + if (params.id) { + purchaseAgentDetailForAdminUsingGet({ pbcId: parseInt(params.id) }).then((res) => { + if (res.retcode && res.data) { + setInfo(res.data); + } + }); + } + }; + + useEffect(() => { + getInfo(); + }, []); + + return ( + { + history.back(); + }} + > + 返回 + , + + + , + + + , + ] + : [ + , + ] + } + > + + + {info.pbcPurchaseAgentName} + {info.pbcPurchaseAgentAge} + {info.pbcPurchaseAgentMobile} + {info.pbcPurchaseAgentWorkingAge}年 + {info.pbcPurchaseAgentResidentArea} + {info.pbcCreateAt} + + {info.pbcPurchaseAgentFabricUse} + + + + + + + + ); +}; + +export default Detail; \ No newline at end of file diff --git a/src/pages/PurchaseAgentList/index.tsx b/src/pages/PurchaseAgentList/index.tsx new file mode 100644 index 0000000..b39ad5b --- /dev/null +++ b/src/pages/PurchaseAgentList/index.tsx @@ -0,0 +1,141 @@ +import React, { useRef, useState } from 'react'; +import { PageContainer } from '@ant-design/pro-layout'; +import Constants from '@/constants'; +import { Image } from 'antd'; +import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components'; +import { handlePageQuery } from '@/utils/utils'; +import { getPurchaseAgentPageForAdminUsingPost } from '@/services/pop-b2b2c/pbcPurchaseAgentInfoController'; +import { Link } from '@umijs/max'; + +/** + * 查询表格 + * @param param0 + */ +const fetchData = async (params: API.PbcPurchaseAgentInfo_) => { + const msg = await getPurchaseAgentPageForAdminUsingPost(params); + return { + data: msg.data?.records, + total: msg.data?.total, + success: msg.retcode, + } as any; +}; + +// eslint-disable-next-line @typescript-eslint/ban-types +const TableList: React.FC<{}> = () => { + const actionRef = useRef(); + const [tabActiveKey, setTabActiveKey] = useState('0') + + const columns: ProColumns[] = [ + { + title: '采购员姓名', + dataIndex: 'pbcPurchaseAgentName', + }, + { + title: '年龄', + dataIndex: 'pbcPurchaseAgentAge', + search: false, + }, + { + title: '联系电话', + dataIndex: 'pbcPurchaseAgentMobile', + }, + { + title: '从业年数', + dataIndex: 'pbcPurchaseAgentWorkingAge', + search: false, + render: (text) => text ? `${text}年` : '-' + }, + { + title: '常驻区域', + dataIndex: 'pbcPurchaseAgentResidentArea', + search: false, + }, + { + title: '擅长面料用途', + dataIndex: 'pbcPurchaseAgentFabricUse', + ellipsis: true, + search: false, + }, + { + title: '头像', + dataIndex: 'pbcPurchaseAgentImage', + search: false, + render: (text: any) => text ? : '-' + }, + { + title: '申请日期', + dataIndex: 'pbcCreateAt', + valueType: 'dateTimeRange', + render: (text, record) => record.pbcCreateAt + }, + { + title: '状态', + dataIndex: 'pbcReviewStatus', + valueEnum: Constants.pbcApprovalStatus, + search: false + }, + { + title: '操作', + fixed: 'right', + valueType: 'option', + render: (text, record) => ( + + 详情 + + ), + }, + ]; + return ( + setTabActiveKey(key)} + tabList={[ + { + tab: "待审核", + key: "0" + }, + { + tab: "审核通过", + key: "1" + }, + { + tab: "审核驳回", + key: "2" + }, + ]} + > + + columns={columns} + actionRef={actionRef} + request={(param: any) => { + const queryParam = handlePageQuery(param); + return fetchData(queryParam); + }} + rowKey="pbcId" + size="small" + bordered + search={{ + labelWidth: 'auto', + span: 6 + }} + params={{ pbcPurchaseAgentStatus: tabActiveKey }} + pagination={{ + defaultPageSize: 20, + showSizeChanger: true, + }} + scroll={{ + y: 'calc(100vh - 320px)', + }} + dateFormatter="string" + options={false} + toolBarRender={() => []} + /> + + ); +}; + +export default TableList; \ No newline at end of file