feat: 技术支持工单/企微权限/开发版本管理/消息推送等迭代

This commit is contained in:
2026-08-04 21:32:13 +08:00
parent c8ea5a3119
commit 9d96c73246
1341 changed files with 0 additions and 195605 deletions
-143
View File
@@ -1,143 +0,0 @@
import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import type { StorePackagesResponse } from '@dukang/shared-types';
import PullToRefresh from '@dukang/shared-ui/PullToRefresh';
import ShopPackagesForm from '../components/ShopPackagesForm';
import { request } from '../lib/api';
import { useStorePageView } from '../lib/usePageView';
import {
emptyPackage,
normalizePackageFormItems,
validatePackageFormItems,
type PackageFormItem,
} from '../lib/storePackages';
export default function PackagesPage() {
useStorePageView('store_packages_view');
const navigate = useNavigate();
const [items, setItems] = useState<PackageFormItem[]>([emptyPackage()]);
const [pending, setPending] = useState<StorePackagesResponse['pendingRequest']>(null);
const [loading, setLoading] = useState(true);
const [submitting, setSubmitting] = useState(false);
const [msg, setMsg] = useState('');
async function load() {
setLoading(true);
try {
const data = await request<StorePackagesResponse>('SHOP_H5', '/shop/store/packages');
const base = data.pendingRequest?.packages?.length
? data.pendingRequest.packages
: data.live?.length
? data.live
: [emptyPackage()];
setItems(base.map((p, i) => ({ ...p, price: String(p.price), sortOrder: i })));
setPending(data.pendingRequest ?? null);
setMsg('');
} catch (e) {
setMsg(e instanceof Error ? e.message : '加载失败');
} finally {
setLoading(false);
}
}
useEffect(() => {
void load();
}, []);
async function submitAudit() {
const validationMsg = validatePackageFormItems(items);
if (validationMsg) {
setMsg(validationMsg);
return;
}
if (pending?.status === 'PENDING') {
setMsg('已有套餐变更审核中,请等待总部处理');
return;
}
setSubmitting(true);
setMsg('');
try {
const packages = normalizePackageFormItems(items).map((p) => ({
...p,
price: Number(p.price).toFixed(2),
}));
await request('SHOP_H5', '/shop/store/packages', {
method: 'PUT',
body: JSON.stringify({ packages }),
});
setMsg('已提交审核,请等待总部处理');
await load();
} catch (e) {
setMsg(e instanceof Error ? e.message : '提交失败');
} finally {
setSubmitting(false);
}
}
const disabled = pending?.status === 'PENDING' || submitting;
return (
<PullToRefresh onRefresh={load} className="shop-records-page shop-packages-page">
<header className="shop-records-header" style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<button
type="button"
className="shop-withdraw-back"
onClick={() => navigate('/mine')}
aria-label="返回"
>
<span className="material-symbols-outlined" style={{ fontSize: 22 }}>
arrow_back
</span>
</button>
<h1 className="app-page-title" style={{ margin: 0 }}>
</h1>
</header>
<div className="shop-records-main">
{loading ? <p className="shop-records-empty"></p> : null}
{!loading && pending?.status === 'PENDING' ? (
<section className="shop-packages-notice">
<span className="material-symbols-outlined shop-fill-icon" style={{ fontSize: 18 }}>
hourglass_top
</span>
<p></p>
</section>
) : null}
{!loading && pending?.status === 'REJECTED' && pending.rejectReason ? (
<section className="shop-packages-notice shop-packages-notice--warn">
<span className="material-symbols-outlined shop-fill-icon" style={{ fontSize: 18 }}>
error
</span>
<p>{pending.rejectReason}</p>
</section>
) : null}
{!loading ? (
<>
<p className="shop-packages-intro">
</p>
<ShopPackagesForm items={items} onChange={setItems} disabled={disabled} />
</>
) : null}
{msg ? <p className="shop-withdraw-msg">{msg}</p> : null}
{!loading ? (
<button
type="button"
className="shop-withdraw-btn"
style={{ marginTop: 16 }}
disabled={disabled}
onClick={() => void submitAudit()}
>
{submitting ? '提交中…' : '提交审核'}
</button>
) : null}
</div>
</PullToRefresh>
);
}