feat(order-service): 增加客户页自定义公告

This commit is contained in:
yml2213
2026-11-04 12:10:51 +08:00
parent b83741cbf7
commit d0e0d32ff3
12 changed files with 332 additions and 4 deletions
@@ -40,6 +40,7 @@ import {
saveAdminOrderServiceProfile,
type AdminOrderServiceAutoPublishJob,
type AdminOrderServiceProfile,
type OrderServiceAnnouncement,
type OrderServiceField,
} from '@/services/admin/worker-platform'
import { uploadFile } from '@/services/files'
@@ -71,6 +72,7 @@ type OrderServiceFormValues = {
successText: string
screenshots: ScreenshotForm
autoPublish: AutoPublishForm
announcement: OrderServiceAnnouncement
}
const DEFAULT_SCREENSHOTS: ScreenshotForm = {
@@ -88,6 +90,17 @@ const DEFAULT_AUTO_PUBLISH: AutoPublishForm = {
retryMax: 3,
}
const DEFAULT_ANNOUNCEMENT: OrderServiceAnnouncement = {
enabled: true,
title: '公告',
content: '由于个人资料填写错误,导致的赠送错误,店铺概不负责!',
fontSize: 14,
color: '#8a4b00',
backgroundColor: '#fff7e6',
fontWeight: 'bold',
textAlign: 'left',
}
export default function OrderServicePanel() {
const { message } = App.useApp()
const queryClient = useQueryClient()
@@ -141,6 +154,7 @@ export default function OrderServicePanel() {
(file: File, scene: string) => uploadFile(file, scene, 'admin'),
[],
)
const announcementPreview = Form.useWatch('announcement', form) || DEFAULT_ANNOUNCEMENT
useEffect(() => {
if (selectedCategoryId !== null || categories.length === 0) return
@@ -160,6 +174,7 @@ export default function OrderServicePanel() {
successText: nextProfile?.successText || '资料已提交,请等待处理',
screenshots: nextProfile?.screenshots || DEFAULT_SCREENSHOTS,
autoPublish: nextProfile?.autoPublish || DEFAULT_AUTO_PUBLISH,
announcement: nextProfile?.announcement || DEFAULT_ANNOUNCEMENT,
})
setFields(normalizeFieldOrder(nextProfile?.fields || []))
setGuideImage(nextProfile?.guideImage || null)
@@ -232,6 +247,7 @@ export default function OrderServicePanel() {
fields: normalizedFields,
screenshots: values.screenshots,
autoPublish: values.autoPublish,
announcement: values.announcement,
submitText: values.submitText,
successText: values.successText,
})
@@ -509,6 +525,83 @@ export default function OrderServicePanel() {
</div>
</section>
<section className="order-service-section">
<div className="order-service-section-head">
<div>
<Text strong>页面公告</Text>
<Text type="secondary">显示在客户资料页顶部,可自定义内容和文字样式。</Text>
</div>
<Space size={8}>
<Text type="secondary">显示公告</Text>
<Form.Item
name={['announcement', 'enabled']}
valuePropName="checked"
noStyle
>
<Switch />
</Form.Item>
</Space>
</div>
<Row gutter={[12, 0]}>
<Col xs={24} md={10}>
<Form.Item label="公告标题" name={['announcement', 'title']}>
<Input maxLength={30} placeholder="例如:公告" />
</Form.Item>
</Col>
<Col xs={12} md={4}>
<Form.Item label="字号" name={['announcement', 'fontSize']}>
<InputNumber
min={12}
max={24}
addonAfter="px"
style={{ width: '100%' }}
/>
</Form.Item>
</Col>
<Col xs={12} md={5}>
<Form.Item label="文字颜色" name={['announcement', 'color']}>
<Input type="color" className="order-service-color-input" />
</Form.Item>
</Col>
<Col xs={12} md={5}>
<Form.Item label="背景颜色" name={['announcement', 'backgroundColor']}>
<Input type="color" className="order-service-color-input" />
</Form.Item>
</Col>
<Col xs={12} md={4}>
<Form.Item label="字重" name={['announcement', 'fontWeight']}>
<Select
options={[
{ value: 'normal', label: '正常' },
{ value: 'bold', label: '加粗' },
]}
/>
</Form.Item>
</Col>
<Col xs={12} md={4}>
<Form.Item label="对齐" name={['announcement', 'textAlign']}>
<Select
options={[
{ value: 'left', label: '左对齐' },
{ value: 'center', label: '居中' },
]}
/>
</Form.Item>
</Col>
<Col span={24}>
<Form.Item label="公告内容" name={['announcement', 'content']}>
<Input.TextArea
autoSize={{ minRows: 2, maxRows: 5 }}
maxLength={500}
showCount
placeholder="请输入需要客户注意的公告内容"
/>
</Form.Item>
</Col>
</Row>
<AnnouncementPreview announcement={announcementPreview} />
</section>
<section className="order-service-section">
<div className="order-service-section-head">
<div>
@@ -809,3 +902,29 @@ function resolveProfileStatus(profile: AdminOrderServiceProfile | undefined) {
}
return { label: '已归档', tone: 'muted' }
}
function AnnouncementPreview({ announcement }: { announcement: OrderServiceAnnouncement }) {
return (
<div
className={`order-service-announcement-preview${announcement.enabled ? '' : ' is-disabled'}`}
style={{
color: announcement.color,
backgroundColor: announcement.backgroundColor,
textAlign: announcement.textAlign,
}}
>
<Text strong className="order-service-announcement-preview-title">
{announcement.title || '公告'}
</Text>
<div
style={{
fontSize: announcement.fontSize,
fontWeight: announcement.fontWeight,
}}
>
{announcement.content || '公告内容'}
</div>
{!announcement.enabled ? <span>当前已关闭,不会在客户页显示</span> : null}
</div>
)
}
@@ -261,6 +261,31 @@ export default function OrderServicePage() {
</Button>
</div>
{pageConfig?.announcement?.enabled && pageConfig.announcement.content ? (
<section
aria-label={pageConfig.announcement.title || '页面公告'}
className="collect-link-announcement"
style={{
color: pageConfig.announcement.color,
backgroundColor: pageConfig.announcement.backgroundColor,
textAlign: pageConfig.announcement.textAlign,
}}
>
<strong className="collect-link-announcement-title">
{pageConfig.announcement.title || '公告'}
</strong>
<div
className="collect-link-announcement-content"
style={{
fontSize: pageConfig.announcement.fontSize,
fontWeight: pageConfig.announcement.fontWeight,
}}
>
{pageConfig.announcement.content}
</div>
</section>
) : null}
{submittedNames.length > 0 ? (
<Alert
type="success"
@@ -1120,6 +1120,17 @@ export type OrderServiceField = {
sortOrder?: number
}
export type OrderServiceAnnouncement = {
enabled: boolean
title: string
content: string
fontSize: number
color: string
backgroundColor: string
fontWeight: 'normal' | 'bold'
textAlign: 'left' | 'center'
}
export type AdminOrderServiceProfile = {
id: number
categoryId: number
@@ -1141,6 +1152,7 @@ export type AdminOrderServiceProfile = {
requireVoucherConsume: boolean
retryMax: number
}
announcement: OrderServiceAnnouncement
submitText: string
successText: string
status: 'draft' | 'published' | 'archived' | string
@@ -1187,6 +1199,7 @@ export function saveAdminOrderServiceProfile(payload: {
requireVoucherConsume: boolean
retryMax: number
}
announcement: OrderServiceAnnouncement
submitText?: string
successText?: string
}) {
+12
View File
@@ -576,6 +576,17 @@ export type OrderServiceScreenshots = {
helpText?: string
}
export type OrderServiceAnnouncement = {
enabled: boolean
title: string
content: string
fontSize: number
color: string
backgroundColor: string
fontWeight: 'normal' | 'bold'
textAlign: 'left' | 'center'
}
export type OrderServiceItem = {
workOrderId: number
productName: string
@@ -589,6 +600,7 @@ export type OrderServiceItem = {
message: string
canSubmit: boolean
blockedReason: '' | 'already_submitted' | 'status' | 'assigned' | 'shares'
announcement?: OrderServiceAnnouncement
fields?: OrderServiceField[]
values?: Record<string, string>
screenshots?: UploadedFile[]
+28
View File
@@ -1843,6 +1843,34 @@
margin-top: 6px;
}
.order-service-color-input {
height: 32px;
padding: 2px 3px;
cursor: pointer;
}
.order-service-announcement-preview {
display: grid;
gap: 4px;
padding: 12px 14px;
border: 1px solid rgba(138, 75, 0, 0.16);
border-left-width: 4px;
border-radius: 9px;
}
.order-service-announcement-preview-title {
color: inherit !important;
font-size: 13px;
}
.order-service-announcement-preview.is-disabled {
opacity: 0.55;
}
.order-service-announcement-preview > span:last-child {
font-size: 11px;
}
.order-service-field-list {
display: grid;
gap: 8px;
+19
View File
@@ -515,6 +515,25 @@
gap: 12px;
}
.collect-link-announcement {
padding: 12px 14px;
border: 1px solid rgba(138, 75, 0, 0.16);
border-left-width: 4px;
border-radius: 9px;
}
.collect-link-announcement-title {
display: block;
margin-bottom: 4px;
font-size: 13px;
}
.collect-link-announcement-content {
line-height: 1.65;
white-space: pre-wrap;
overflow-wrap: anywhere;
}
/* 商品名与订单号放在同一个信息头里,避免标题和灰色信息块分离 */
.collect-link-order-head {
display: flex;