fix(admin): contract preview, package audit detail, empty packages, winery status
Allow HQ to save stores with zero packages, preview contract images/PDFs, inspect package audit images/content, and show gray 无需打款 when winery payable is 0. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -59,7 +59,7 @@ const AdminStorePackagesSection = forwardRef<AdminStorePackagesHandle, { storeId
|
||||
sortOrder: i,
|
||||
};
|
||||
})
|
||||
: [emptyRow()],
|
||||
: [],
|
||||
);
|
||||
})
|
||||
.catch((e) => message.error(e instanceof Error ? e.message : '加载套餐失败'))
|
||||
@@ -124,7 +124,13 @@ const AdminStorePackagesSection = forwardRef<AdminStorePackagesHandle, { storeId
|
||||
sortOrder: index,
|
||||
};
|
||||
})
|
||||
.filter((item) => item.name || item.dishes || item.price || item.imageUrls.length > 0);
|
||||
// 允许整店无套餐:忽略空白占位行(默认 price=0 不算已填)
|
||||
.filter((item) => {
|
||||
const hasText = !!(item.name || item.dishes || item.usableTime || item.otherNotes);
|
||||
const hasImages = item.imageUrls.length > 0;
|
||||
const hasNonZeroPrice = item.price !== '' && Number(item.price) !== 0;
|
||||
return hasText || hasImages || hasNonZeroPrice;
|
||||
});
|
||||
|
||||
for (let i = 0; i < filled.length; i++) {
|
||||
const item = filled[i];
|
||||
@@ -168,7 +174,7 @@ const AdminStorePackagesSection = forwardRef<AdminStorePackagesHandle, { storeId
|
||||
sortOrder: i,
|
||||
};
|
||||
})
|
||||
: [emptyRow()],
|
||||
: [],
|
||||
);
|
||||
} catch (e) {
|
||||
if (!opts?.quiet) message.error(e instanceof Error ? e.message : '保存失败');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { Button, Image, Input, Space, Upload, message } from 'antd';
|
||||
import { UploadOutlined } from '@ant-design/icons';
|
||||
import { Button, Image, Input, Modal, Space, Upload, message } from 'antd';
|
||||
import { EyeOutlined, FilePdfOutlined, UploadOutlined } from '@ant-design/icons';
|
||||
import type { UploadProps } from 'antd';
|
||||
import { uploadFileToOss, type OssMediaType, type UploadFileResult } from '../lib/upload';
|
||||
|
||||
@@ -15,6 +15,14 @@ type OssUploadProps = {
|
||||
placeholder?: string;
|
||||
};
|
||||
|
||||
function isImageUrl(url: string) {
|
||||
return /\.(png|jpe?g|gif|webp|bmp|svg)(\?|#|$)/i.test(url);
|
||||
}
|
||||
|
||||
function isPdfUrl(url: string) {
|
||||
return /\.pdf(\?|#|$)/i.test(url);
|
||||
}
|
||||
|
||||
export default function OssUpload({
|
||||
value,
|
||||
onChange,
|
||||
@@ -25,6 +33,7 @@ export default function OssUpload({
|
||||
placeholder = '上传后自动填入,或手动粘贴 URL',
|
||||
}: OssUploadProps) {
|
||||
const [uploading, setUploading] = useState(false);
|
||||
const [pdfPreviewOpen, setPdfPreviewOpen] = useState(false);
|
||||
|
||||
const resolvedAccept =
|
||||
accept ?? (mediaType === 'VIDEO' ? 'video/*' : mediaType === 'FILE' ? undefined : 'image/*');
|
||||
@@ -47,6 +56,57 @@ export default function OssUpload({
|
||||
}
|
||||
};
|
||||
|
||||
const filePreview =
|
||||
value && mediaType === 'FILE' ? (
|
||||
isImageUrl(value) ? (
|
||||
<Image src={value} width={120} height={120} style={{ objectFit: 'cover', borderRadius: 4 }} />
|
||||
) : isPdfUrl(value) ? (
|
||||
<Space direction="vertical" size={8}>
|
||||
<div
|
||||
style={{
|
||||
width: 120,
|
||||
height: 120,
|
||||
borderRadius: 4,
|
||||
border: '1px solid #f0f0f0',
|
||||
background: '#fafafa',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
gap: 8,
|
||||
color: '#cf1322',
|
||||
}}
|
||||
>
|
||||
<FilePdfOutlined style={{ fontSize: 36 }} />
|
||||
<span style={{ fontSize: 12, color: 'rgba(0,0,0,0.45)' }}>PDF 合同</span>
|
||||
</div>
|
||||
<Space wrap>
|
||||
<Button type="link" size="small" icon={<EyeOutlined />} onClick={() => setPdfPreviewOpen(true)}>
|
||||
预览
|
||||
</Button>
|
||||
<Button type="link" size="small" href={value} target="_blank" rel="noreferrer">
|
||||
新窗口打开
|
||||
</Button>
|
||||
</Space>
|
||||
<Modal
|
||||
title="签约合同预览"
|
||||
open={pdfPreviewOpen}
|
||||
onCancel={() => setPdfPreviewOpen(false)}
|
||||
footer={null}
|
||||
width="90vw"
|
||||
styles={{ body: { height: '75vh', padding: 0 } }}
|
||||
destroyOnClose
|
||||
>
|
||||
<iframe title="合同 PDF 预览" src={value} style={{ width: '100%', height: '100%', border: 0 }} />
|
||||
</Modal>
|
||||
</Space>
|
||||
) : (
|
||||
<Button type="link" href={value} target="_blank" rel="noreferrer" style={{ paddingLeft: 0 }}>
|
||||
打开已上传文件
|
||||
</Button>
|
||||
)
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<Space direction="vertical" style={{ width: '100%' }} size="small">
|
||||
{value && mediaType === 'IMAGE' && (
|
||||
@@ -55,6 +115,7 @@ export default function OssUpload({
|
||||
{value && mediaType === 'VIDEO' && (
|
||||
<video src={value} controls style={{ maxWidth: '100%', maxHeight: 160, borderRadius: 4 }} />
|
||||
)}
|
||||
{filePreview}
|
||||
<Space wrap>
|
||||
<Upload
|
||||
accept={resolvedAccept}
|
||||
|
||||
Reference in New Issue
Block a user