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
-122
View File
@@ -1,122 +0,0 @@
import { useEffect, useState } from 'react';
import { View, Text, Image, Button } from '@tarojs/components';
import Taro, { useRouter } from '@tarojs/taro';
import HqHeader from '../../components/HqHeader';
import { request, toast } from '../../lib/api';
import { STORE_STATUS_LABELS, badgeClass, fmtTime } from '../../lib/constants';
type StoreDetail = {
id: string;
name: string;
phone: string;
status: string;
province?: string;
cityName?: string;
district?: string;
address?: string;
intro?: string | null;
coverUrl?: string | null;
redeemCount?: number;
createdAt: string;
partner?: { companyName: string };
account?: { name: string; phone: string };
};
const ACTIONS: Array<{ status: string; label: string }> = [
{ status: 'OPEN', label: '通过 / 营业' },
{ status: 'PAUSED', label: '暂停营业' },
{ status: 'CLOSED', label: '关闭门店' },
];
export default function StoreDetailPage() {
const router = useRouter();
const id = router.params.id;
const [store, setStore] = useState<StoreDetail | null>(null);
const [saving, setSaving] = useState(false);
function load() {
if (!id) return;
request<StoreDetail>(`/admin/stores/${id}`).then(setStore).catch(() => undefined);
}
useEffect(load, [id]);
async function changeStatus(status: string) {
if (!id || saving) return;
setSaving(true);
try {
await request(`/admin/stores/${id}/status`, { method: 'PUT', data: { status } });
toast('状态已更新', 'success');
setStore((s) => (s ? { ...s, status } : s));
} catch (e) {
toast(e instanceof Error ? e.message : '更新失败');
} finally {
setSaving(false);
}
}
return (
<View className="hq-page" style="padding-bottom:calc(96px + var(--hq-safe-bottom))">
<HqHeader title="门店详情" back />
{!store && <View className="hq-empty"></View>}
{store && (
<>
{store.coverUrl ? (
<Image className="store-cover" src={store.coverUrl} mode="aspectFill" />
) : null}
<View className="hq-card">
<View className="hq-row">
<Text style="font-size:18px;font-weight:700">{store.name}</Text>
<Text className={`hq-badge ${badgeClass(store.status)}`}>
{STORE_STATUS_LABELS[store.status] || store.status}
</Text>
</View>
<Text className="hq-muted" style="display:block;margin-top:8px;font-size:13px">
{store.province || ''}{store.cityName || ''}{store.district || ''}{store.address || ''}
</Text>
<Text className="hq-muted" style="display:block;margin-top:4px;font-size:13px">{store.phone}</Text>
{store.intro ? (
<Text style="display:block;margin-top:8px;font-size:13px;line-height:1.6">{store.intro}</Text>
) : null}
</View>
<View className="hq-card">
<View className="hq-row" style="margin-bottom:8px">
<Text className="hq-muted" style="font-size:13px"></Text>
<Text style="font-size:14px">{store.partner?.companyName || '—'}</Text>
</View>
<View className="hq-row" style="margin-bottom:8px">
<Text className="hq-muted" style="font-size:13px"></Text>
<Text style="font-size:14px">{store.account?.name || '—'} {store.account?.phone || ''}</Text>
</View>
<View className="hq-row" style="margin-bottom:8px">
<Text className="hq-muted" style="font-size:13px"></Text>
<Text style="font-size:14px">{store.redeemCount ?? 0} </Text>
</View>
<View className="hq-row">
<Text className="hq-muted" style="font-size:13px"></Text>
<Text style="font-size:14px">{fmtTime(store.createdAt)}</Text>
</View>
</View>
<Text className="hq-section-title"></Text>
<View className="hq-card" style="display:flex;flex-direction:column;gap:10px">
{ACTIONS.map((a) => (
<Button
key={a.status}
className={`hq-btn hq-btn--block ${a.status === 'OPEN' ? 'hq-btn--primary' : 'hq-btn--outline'}`}
disabled={saving || store.status === a.status}
onClick={() => changeStatus(a.status)}
>
{a.label}
</Button>
))}
</View>
</>
)}
</View>
);
}