|
@@ -10,7 +10,7 @@ import {
|
|
|
type TemplateBasicInfo,
|
|
type TemplateBasicInfo,
|
|
|
type TemplateMakeTaskDetail,
|
|
type TemplateMakeTaskDetail,
|
|
|
} from '../../../services/api/templates'
|
|
} from '../../../services/api/templates'
|
|
|
-import { usePageContext } from '../../../shared/pageContext'
|
|
|
|
|
|
|
+import { type Locale, usePageContext } from '../../../shared/pageContext'
|
|
|
|
|
|
|
|
const FALLBACK_TASK_COPY = {
|
|
const FALLBACK_TASK_COPY = {
|
|
|
title: '模板制作任务', description: '查看模板制作与编辑状态。', badge: '模板任务', pendingName: '正在创建模板...', resourceFallback: '暂无预览',
|
|
title: '模板制作任务', description: '查看模板制作与编辑状态。', badge: '模板任务', pendingName: '正在创建模板...', resourceFallback: '暂无预览',
|
|
@@ -33,10 +33,11 @@ const FALLBACK_EDIT_COPY = {
|
|
|
badge: '模板编辑', info: { title: '发型模板基本信息', name: '模板名称', status: '状态', category: '分类', tags: '标签', tagsPlaceholder: '层次, 空气感', description: '说明' }, preview: { imageAlt: '模板封面预览', downloadBundle: '下载模板包' }, success: { saveSucceeded: '保存成功' }, errors: { saveFailed: '保存失败' }, submitTitle: '保存模板信息', submitLead: '保存模板名称、分类、状态、标签和说明。', statusOptions: { DRAFT: '草稿', PUBLIC: '公开中' }, categoryOptions: { LONG: '长发', MEDIUM: '中长发', SHORT: '短发', DYE: '染发' },
|
|
badge: '模板编辑', info: { title: '发型模板基本信息', name: '模板名称', status: '状态', category: '分类', tags: '标签', tagsPlaceholder: '层次, 空气感', description: '说明' }, preview: { imageAlt: '模板封面预览', downloadBundle: '下载模板包' }, success: { saveSucceeded: '保存成功' }, errors: { saveFailed: '保存失败' }, submitTitle: '保存模板信息', submitLead: '保存模板名称、分类、状态、标签和说明。', statusOptions: { DRAFT: '草稿', PUBLIC: '公开中' }, categoryOptions: { LONG: '长发', MEDIUM: '中长发', SHORT: '短发', DYE: '染发' },
|
|
|
} as const
|
|
} as const
|
|
|
|
|
|
|
|
-function formatTaskTime(locale: 'zh' | 'ja', value?: string) {
|
|
|
|
|
|
|
+function formatTaskTime(locale: Locale, value?: string) {
|
|
|
if (!value) return '--'
|
|
if (!value) return '--'
|
|
|
const date = new Date(value)
|
|
const date = new Date(value)
|
|
|
- return Number.isNaN(date.getTime()) ? value : new Intl.DateTimeFormat(locale === 'ja' ? 'ja-JP' : 'zh-CN', { dateStyle: 'medium', timeStyle: 'short' }).format(date)
|
|
|
|
|
|
|
+ const language = locale === 'ja' ? 'ja-JP' : locale === 'en' ? 'en-US' : 'zh-CN'
|
|
|
|
|
+ return Number.isNaN(date.getTime()) ? value : new Intl.DateTimeFormat(language, { dateStyle: 'medium', timeStyle: 'short' }).format(date)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function taskTone(status?: string) {
|
|
function taskTone(status?: string) {
|
|
@@ -188,7 +189,7 @@ export function TemplateMakeTaskPage() {
|
|
|
{complete && template ? <form id="template-edit-section" className="template-task-edit-section workbench-panel bg-white border-radius-8px box-shadow-extra-large p-30px mt-4" onSubmit={handleSave}>
|
|
{complete && template ? <form id="template-edit-section" className="template-task-edit-section workbench-panel bg-white border-radius-8px box-shadow-extra-large p-30px mt-4" onSubmit={handleSave}>
|
|
|
<div className="template-task-edit-head mb-25px"><div><span className="fs-14 fw-700 text-base-color text-uppercase">{editCopy.badge}</span><h2 className="fw-700 text-dark-gray fs-26 mb-0">{editCopy.info.title}</h2></div><span className="template-status-badge">{editCopy.statusOptions[status]}</span></div>
|
|
<div className="template-task-edit-head mb-25px"><div><span className="fs-14 fw-700 text-base-color text-uppercase">{editCopy.badge}</span><h2 className="fw-700 text-dark-gray fs-26 mb-0">{editCopy.info.title}</h2></div><span className="template-status-badge">{editCopy.statusOptions[status]}</span></div>
|
|
|
<div className="template-task-edit-layout">
|
|
<div className="template-task-edit-layout">
|
|
|
- <div><img className="template-task-cover-preview mt-0" src={template.coverUrl || task.step2.resultImage || task.refHairUrl} alt={editCopy.preview.imageAlt} />{template.templateUrl ? <a href={template.templateUrl} target="_blank" rel="noreferrer" className="btn btn-small btn-rounded btn-transparent-light-gray border border-1 border-color-dark-gray fw-700 w-100 mt-15px">{editCopy.preview.downloadBundle}</a> : null}</div>
|
|
|
|
|
|
|
+ <div><img className="template-task-cover-preview mt-0" src={template.coverUrl || task.step2.resultImage || task.refHairUrl} alt={editCopy.preview.imageAlt} /></div>
|
|
|
<div className="row g-3">
|
|
<div className="row g-3">
|
|
|
<div className="col-md-7"><label htmlFor="task-template-name" className="customer-edit-label">{editCopy.info.name}</label><input id="task-template-name" className="form-control customer-edit-control" value={templateName} onChange={(event) => setTemplateName(event.target.value)} required /></div>
|
|
<div className="col-md-7"><label htmlFor="task-template-name" className="customer-edit-label">{editCopy.info.name}</label><input id="task-template-name" className="form-control customer-edit-control" value={templateName} onChange={(event) => setTemplateName(event.target.value)} required /></div>
|
|
|
<div className="col-md-5"><label htmlFor="task-template-status" className="customer-edit-label">{editCopy.info.status}</label><select id="task-template-status" className="form-select customer-edit-control" value={status} onChange={(event) => setStatus(event.target.value as TemplateBasicInfo['status'])}><option value="DRAFT">{editCopy.statusOptions.DRAFT}</option><option value="PUBLIC">{editCopy.statusOptions.PUBLIC}</option></select></div>
|
|
<div className="col-md-5"><label htmlFor="task-template-status" className="customer-edit-label">{editCopy.info.status}</label><select id="task-template-status" className="form-select customer-edit-control" value={status} onChange={(event) => setStatus(event.target.value as TemplateBasicInfo['status'])}><option value="DRAFT">{editCopy.statusOptions.DRAFT}</option><option value="PUBLIC">{editCopy.statusOptions.PUBLIC}</option></select></div>
|
|
@@ -202,7 +203,7 @@ export function TemplateMakeTaskPage() {
|
|
|
</div>
|
|
</div>
|
|
|
</section>
|
|
</section>
|
|
|
|
|
|
|
|
- {deleteOpen ? <dialog className="template-delete-dialog" open aria-modal="true"><h2 className="fw-700 text-dark-gray fs-24">{pageCopy.delete?.title || '确认删除模板?'}</h2><p>{pageCopy.delete?.body || '删除后模板和生成任务将不再显示,且无法恢复。'}</p><div className="d-flex justify-content-end gap-2"><button type="button" className="btn btn-small btn-rounded btn-transparent-light-gray border" onClick={() => setDeleteOpen(false)}>{commonCopy.cancel}</button><button type="button" className="btn btn-small btn-rounded btn-base-color" onClick={() => void handleDelete()}>{pageCopy.delete?.confirm || '确认删除'}</button></div></dialog> : null}
|
|
|
|
|
|
|
+ {deleteOpen ? <div className="template-delete-modal" role="presentation"><section className="template-delete-dialog" role="dialog" aria-modal="true" aria-labelledby="template-delete-title"><h2 id="template-delete-title" className="fw-700 text-dark-gray fs-24">{pageCopy.delete?.title || '确认删除模板?'}</h2><p>{pageCopy.delete?.body || '删除后模板和生成任务将不再显示,且无法恢复。'}</p><div className="d-flex justify-content-end gap-2"><button type="button" className="btn btn-small btn-rounded btn-transparent-light-gray border" onClick={() => setDeleteOpen(false)}>{commonCopy.cancel}</button><button type="button" className="btn btn-small btn-rounded btn-base-color" onClick={() => void handleDelete()}>{pageCopy.delete?.confirm || '确认删除'}</button></div></section></div> : null}
|
|
|
</DashboardLayout>
|
|
</DashboardLayout>
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|