杂项配置面板管理本地Mock自定义店铺支持增删改名
This commit is contained in:
@@ -1,11 +1,27 @@
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { App, Button, Card, Form, Input, Space, Switch, Typography } from 'antd'
|
||||
import { App, Button, Card, Form, Input, Popconfirm, Space, Switch, Typography } from 'antd'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import { fetchAdminWorkerAnnouncement, saveAdminWorkerAnnouncement } from '@/services/admin'
|
||||
import {
|
||||
addAdminMockCustomShop,
|
||||
deleteAdminMockCustomShop,
|
||||
fetchAdminMockCustomShops,
|
||||
fetchAdminWorkerAnnouncement,
|
||||
renameAdminMockCustomShop,
|
||||
saveAdminWorkerAnnouncement,
|
||||
} from '@/services/admin'
|
||||
import type { WorkerAnnouncementConfig } from '@/types/worker-platform'
|
||||
|
||||
export default function AnnouncementPanel() {
|
||||
return (
|
||||
<Space direction="vertical" size={16} style={{ width: '100%' }}>
|
||||
<AnnouncementCard />
|
||||
<MockCustomShopsCard />
|
||||
</Space>
|
||||
)
|
||||
}
|
||||
|
||||
function AnnouncementCard() {
|
||||
const { message } = App.useApp()
|
||||
const queryClient = useQueryClient()
|
||||
const [form] = Form.useForm<WorkerAnnouncementConfig>()
|
||||
@@ -59,3 +75,116 @@ export default function AnnouncementPanel() {
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
function MockCustomShopsCard() {
|
||||
const { message, modal } = App.useApp()
|
||||
const queryClient = useQueryClient()
|
||||
const [adding, setAdding] = useState(false)
|
||||
const [addForm] = Form.useForm<{ name: string }>()
|
||||
const customShopsQuery = useQuery({
|
||||
queryKey: ['admin-mock-custom-shops'],
|
||||
queryFn: fetchAdminMockCustomShops,
|
||||
})
|
||||
const shops = customShopsQuery.data?.data.items || []
|
||||
|
||||
async function refresh() {
|
||||
await queryClient.invalidateQueries({ queryKey: ['admin-mock-custom-shops'] })
|
||||
}
|
||||
|
||||
async function runShopAction(action: () => Promise<unknown>, successMessage: string) {
|
||||
try {
|
||||
await action()
|
||||
await refresh()
|
||||
message.success(successMessage)
|
||||
} catch (error) {
|
||||
message.error(error instanceof Error ? error.message : '操作失败')
|
||||
}
|
||||
}
|
||||
|
||||
async function addShop(values: { name: string }) {
|
||||
setAdding(true)
|
||||
try {
|
||||
await runShopAction(
|
||||
() => addAdminMockCustomShop(String(values.name || '').trim()),
|
||||
'自定义店铺已新增',
|
||||
)
|
||||
addForm.resetFields()
|
||||
} finally {
|
||||
setAdding(false)
|
||||
}
|
||||
}
|
||||
|
||||
function renameShop(name: string) {
|
||||
let nextName = ''
|
||||
modal.confirm({
|
||||
title: '重命名自定义店铺',
|
||||
content: (
|
||||
<Input
|
||||
defaultValue={name}
|
||||
maxLength={64}
|
||||
placeholder="请输入新的店铺名称"
|
||||
onChange={(event) => {
|
||||
nextName = String(event.target.value || '')
|
||||
}}
|
||||
/>
|
||||
),
|
||||
onOk: async () => {
|
||||
const trimmed = nextName.trim()
|
||||
if (!trimmed || trimmed === name) return
|
||||
await runShopAction(() => renameAdminMockCustomShop(name, trimmed), '自定义店铺已重命名')
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Card title="本地 Mock 自定义店铺" bordered={false}>
|
||||
<Typography.Paragraph type="secondary" style={{ marginBottom: 12 }}>
|
||||
在接单工单「本地 Mock」中录入过的外部平台店铺会自动记忆到这里;也可以直接维护,
|
||||
维护后的店铺会出现在 Mock 表单的下拉选项中。
|
||||
</Typography.Paragraph>
|
||||
<Form form={addForm} layout="inline" onFinish={addShop} style={{ marginBottom: 12 }}>
|
||||
<Form.Item
|
||||
name="name"
|
||||
rules={[{ required: true, whitespace: true, message: '请输入店铺名称' }]}
|
||||
style={{ minWidth: 260 }}
|
||||
>
|
||||
<Input maxLength={64} placeholder="输入店铺名称,如:抖音-某某小店" />
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit" loading={adding}>
|
||||
新增店铺
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
{shops.length === 0 ? (
|
||||
<Typography.Text type="secondary">
|
||||
还没有自定义店铺,先在上方新增或通过本地 Mock 录入。
|
||||
</Typography.Text>
|
||||
) : (
|
||||
<Space size={[8, 8]} wrap>
|
||||
{shops.map((name) => (
|
||||
<Space key={name} size={4} wrap>
|
||||
<Typography.Text>{name}</Typography.Text>
|
||||
<Button size="small" type="text" onClick={() => renameShop(name)}>
|
||||
重命名
|
||||
</Button>
|
||||
<Popconfirm
|
||||
title={`删除自定义店铺「${name}」?`}
|
||||
description="不影响已用它生成的工单,仅从 Mock 下拉选项移除。"
|
||||
okText="删除"
|
||||
okButtonProps={{ danger: true }}
|
||||
onConfirm={() =>
|
||||
runShopAction(() => deleteAdminMockCustomShop(name), '自定义店铺已删除')
|
||||
}
|
||||
>
|
||||
<Button size="small" type="text" danger>
|
||||
删除
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
))}
|
||||
</Space>
|
||||
)}
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user