This commit is contained in:
笔记本里的永平
2025-07-16 11:06:09 +08:00
parent 1bb34b4932
commit b8b86598d8
2 changed files with 110 additions and 71 deletions

View File

@@ -161,4 +161,35 @@ class RequestCancelManager {
// 导出单例实例
export const requestDeduplicator = new RequestDeduplicator();
export const requestCancelManager = new RequestCancelManager();
export const requestCancelManager = new RequestCancelManager();
/**
* 通用文件上传方法(支持图片、文件)
* @param {File} file - 要上传的文件对象
* @param {string} [uploadUrl='/v1/attachment/upload'] - 上传接口地址
* @returns {Promise<string>} - 上传成功后返回文件url
*/
export async function uploadFile(file: File, uploadUrl: string = '/v1/attachment/upload'): Promise<string> {
const formData = new FormData();
formData.append('file', file);
const token = typeof window !== 'undefined' ? localStorage.getItem('token') : '';
const headers: Record<string, string> = {};
if (token) headers['Authorization'] = `Bearer ${token}`;
try {
const response = await fetch(uploadUrl, {
method: 'POST',
headers,
body: formData,
});
const res = await response.json();
if (res?.url) {
return res.url;
}
if (res?.data?.url) {
return res.data.url;
}
throw new Error(res?.msg || '文件上传失败');
} catch (e: any) {
throw new Error(e?.message || '文件上传失败');
}
}

View File

@@ -304,6 +304,7 @@ export function BasicSettings({
// 新增用于文件选择的ref
const uploadInputRef = useRef<HTMLInputElement>(null);
const uploadOrderInputRef = useRef<HTMLInputElement>(null);
// 更新电话获客设置
const handlePhoneSettingsUpdate = () => {
@@ -648,6 +649,9 @@ export function BasicSettings({
transition: "border 0.2s",
textAlign: "center",
position: "relative",
height: 180 + 12, // 图片高度180+上下padding
overflow: "hidden",
minHeight: 192,
}}
onClick={() => handleMaterialSelect(material)}
>
@@ -675,40 +679,31 @@ export function BasicSettings({
</button>
{/* 删除自定义海报按钮 */}
{isCustom && (
<button
type="button"
<div
style={{
position: "absolute",
top: 8,
right: 8,
width: 24,
height: 24,
width: 28,
height: 28,
background: "rgba(0,0,0,0.5)",
border: "none",
borderRadius: "50%",
padding: 0,
zIndex: 2,
cursor: "pointer",
display: "flex",
alignItems: "center",
justifyContent: "center",
lineHeight: 20,
color: "#ffffff",
}}
onClick={(e) => {
e.stopPropagation();
handleRemoveCustomPoster(material.id);
}}
>
<span
style={{
color: "#fff",
fontWeight: 700,
fontSize: 16,
lineHeight: "24px",
}}
>
×
</span>
</button>
×
</div>
)}
<img
src={material.preview}
@@ -719,12 +714,14 @@ export function BasicSettings({
objectFit: "cover",
borderRadius: 4,
marginBottom: 0,
display: "block",
}}
/>
<div
style={{
position: "relative",
top: "-32px",
position: "absolute",
left: 0,
bottom: 0,
width: "100%",
background: "rgba(0,0,0,0.5)",
color: "#fff",
@@ -733,6 +730,7 @@ export function BasicSettings({
borderBottomLeftRadius: 4,
borderBottomRightRadius: 4,
textAlign: "center",
zIndex: 3,
}}
>
{material.name}
@@ -753,7 +751,7 @@ export function BasicSettings({
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
height: 220,
height: 190,
}}
onClick={() => uploadInputRef.current?.click()}
>
@@ -801,62 +799,75 @@ export function BasicSettings({
index={0}
/>
</div>
{/* 订单导入区块 */}
{/* 订单导入区块优化 */}
<div style={openOrder} className="my-4">
<Button theme="default" onClick={() => setIsImportDialogOpen(true)}>
{importedTags.length
? `已导入订单(${importedTags.length}`
: "导入订单"}
</Button>
<Dialog visible={isImportDialogOpen} onClose={handleImportDialogClose}>
<div style={{ fontWeight: 600, fontSize: 16, marginBottom: 12 }}>
</div>
<div style={{ marginBottom: 12 }}>
<Button
theme="primary"
onClick={handleDownloadTemplate}
style={{ marginRight: 8 }}
>
</Button>
<div style={{ fontWeight: 500, marginBottom: 8 }}></div>
<div style={{ display: "flex", gap: 12, marginBottom: 4 }}>
<Button
type="button"
style={{ display: "flex", alignItems: "center", gap: 4 }}
theme="default"
onClick={handleDownloadTemplate}
>
<span className="iconfont" style={{ fontSize: 18 }}>
</span>{" "}
</Button>
<Button
type="button"
style={{ display: "flex", alignItems: "center", gap: 4 }}
theme="default"
onClick={() => uploadOrderInputRef.current?.click()}
>
<span className="iconfont" style={{ fontSize: 18 }}>
</span>{" "}
<input
ref={uploadOrderInputRef}
type="file"
accept=".csv"
accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
style={{ display: "none" }}
onChange={handleFileImport}
style={{ display: "inline-block" }}
/>
</div>
{importedTags.length > 0 && (
<Table
columns={[
{ colKey: "phone", title: "手机号" },
{ colKey: "wechat", title: "微信号" },
{ colKey: "source", title: "来源" },
{ colKey: "orderAmount", title: "订单金额" },
{ colKey: "orderDate", title: "下单日期" },
]}
data={importedTags}
rowKey="phone"
style={{ marginTop: 12 }}
/>
)}
</Dialog>
</Button>
</div>
<div style={{ color: "#888", fontSize: 13, marginBottom: 8 }}>
CSVExcel
</div>
{/* 已导入数据表格可复用原有Table渲染 */}
{importedTags.length > 0 && (
<Table
columns={[
{ colKey: "phone", title: "手机号" },
{ colKey: "wechat", title: "微信号" },
{ colKey: "source", title: "来源" },
{ colKey: "orderAmount", title: "订单金额" },
{ colKey: "orderDate", title: "下单日期" },
]}
data={importedTags}
rowKey="phone"
style={{ marginTop: 12 }}
/>
)}
</div>
{/* 电话获客设置区块,仅在选择电话获客场景时显示 */}
{formData.scenario === "phone" && (
{formData.scenario === 5 && (
<div style={{ margin: "16px 0" }}>
<Button theme="default" onClick={() => setIsPhoneSettingsOpen(true)}>
</Button>
<Dialog
visible={isPhoneSettingsOpen}
onClose={handlePhoneSettingsDialogClose}
<div
style={{
background: "#f7f8fa",
borderRadius: 10,
padding: 20,
boxShadow: "0 2px 8px rgba(0,0,0,0.03)",
marginBottom: 12,
}}
>
<div style={{ fontWeight: 600, fontSize: 16, marginBottom: 12 }}>
<div style={{ fontWeight: 600, fontSize: 16, marginBottom: 16 }}>
</div>
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
<div style={{ display: "flex", flexDirection: "column", gap: 18 }}>
<div
style={{
display: "flex",
@@ -902,15 +913,12 @@ export function BasicSettings({
}
/>
</div>
<Button block theme="primary" onClick={handlePhoneSettingsUpdate}>
</Button>
</div>
</Dialog>
</div>
</div>
)}
{/* 微信群设置区块,仅在选择微信群场景时显示 */}
{formData.scenario === "weixinqun" && (
{formData.scenario === 7 && (
<div style={{ margin: "16px 0" }}>
<div style={{ marginBottom: 8 }}>
<Input
@@ -932,7 +940,7 @@ export function BasicSettings({
</div>
</div>
)}
<Button block theme="primary" onClick={onNext}>
<Button className="mt-4" block theme="primary" onClick={onNext}>
</Button>
</div>