142 lines
4.5 KiB
TypeScript
142 lines
4.5 KiB
TypeScript
import type { ChargeMode, QuantityKey, ScreenshotKey } from '@/features/listings/api/listingOptions'
|
|
import type { PublishDraft, PublishForm } from '@/types/publish'
|
|
|
|
export function defaultPublishForm(): PublishForm {
|
|
return {
|
|
server_region: '',
|
|
face_owner: '',
|
|
haf_coin_amount: '',
|
|
rank_level: '',
|
|
secret_kd: '',
|
|
fire_level: '',
|
|
daily_loss_m: 10,
|
|
accelerated_sale_ratio: '',
|
|
season_insurance: '',
|
|
stamina_level: '',
|
|
load_level: '',
|
|
login_method: '',
|
|
online_start: '',
|
|
online_end: '',
|
|
ban_record: '',
|
|
common_regions: [],
|
|
deposit_amount: '',
|
|
remark: '',
|
|
}
|
|
}
|
|
|
|
export function buildPublishDraft(options: {
|
|
form: PublishForm
|
|
quantityValues: Record<QuantityKey, number>
|
|
quantityModes: Record<QuantityKey, ChargeMode>
|
|
screenshotFiles: Record<ScreenshotKey, string[]>
|
|
selectedSkins: string[]
|
|
}): PublishDraft {
|
|
return {
|
|
form: {
|
|
...options.form,
|
|
common_regions: [...options.form.common_regions],
|
|
},
|
|
quantityValues: { ...options.quantityValues },
|
|
quantityModes: { ...options.quantityModes },
|
|
screenshotFiles: cloneScreenshotFiles(options.screenshotFiles),
|
|
selectedSkins: [...options.selectedSkins],
|
|
}
|
|
}
|
|
|
|
export function readPublishDraft(draftKey: string) {
|
|
const raw = localStorage.getItem(draftKey)
|
|
if (!raw) return null
|
|
try {
|
|
const draft = JSON.parse(raw) as Partial<PublishDraft>
|
|
return {
|
|
form: normalizeDraftForm(draft.form),
|
|
quantityValues: normalizeNumberRecord(draft.quantityValues),
|
|
quantityModes: normalizeQuantityModes(draft.quantityModes),
|
|
screenshotFiles: normalizeScreenshotFiles(draft.screenshotFiles),
|
|
selectedSkins: Array.isArray(draft.selectedSkins)
|
|
? draft.selectedSkins.filter((skin): skin is string => typeof skin === 'string')
|
|
: [],
|
|
}
|
|
} catch {
|
|
localStorage.removeItem(draftKey)
|
|
return null
|
|
}
|
|
}
|
|
|
|
export function writePublishDraft(draftKey: string, draft: PublishDraft) {
|
|
const nextValue = JSON.stringify(draft)
|
|
if (localStorage.getItem(draftKey) === nextValue) return
|
|
localStorage.setItem(draftKey, nextValue)
|
|
}
|
|
|
|
export function removePublishDraft(draftKey: string) {
|
|
localStorage.removeItem(draftKey)
|
|
}
|
|
|
|
export function clearRecord(record: Record<string, unknown>) {
|
|
for (const key of Object.keys(record)) delete record[key]
|
|
}
|
|
|
|
function normalizeDraftForm(value: unknown): PublishForm {
|
|
const next = defaultPublishForm()
|
|
if (!isRecord(value)) return next
|
|
for (const key of Object.keys(next) as Array<keyof PublishForm>) {
|
|
if (key === 'common_regions') continue
|
|
const draftValue = value[key]
|
|
if (draftValue !== undefined) next[key] = draftValue as never
|
|
}
|
|
next.common_regions = Array.isArray(value.common_regions)
|
|
? value.common_regions.filter((region): region is string => typeof region === 'string')
|
|
: []
|
|
// 默认使用参考比例:如果草稿中的 accelerated_sale_ratio 是 0 或未设置,重置为空字符串
|
|
if (!next.accelerated_sale_ratio || next.accelerated_sale_ratio === 0) {
|
|
next.accelerated_sale_ratio = ''
|
|
}
|
|
if (next.haf_coin_amount === 0) next.haf_coin_amount = ''
|
|
if (String(next.secret_kd).trim() === '0') next.secret_kd = ''
|
|
if (next.fire_level === 0) next.fire_level = ''
|
|
return next
|
|
}
|
|
|
|
function normalizeNumberRecord(value: unknown) {
|
|
const record: Record<string, number> = {}
|
|
if (!isRecord(value)) return record
|
|
for (const [key, item] of Object.entries(value)) {
|
|
const parsed = Number(item)
|
|
if (Number.isFinite(parsed)) record[key] = parsed
|
|
}
|
|
return record
|
|
}
|
|
|
|
function normalizeScreenshotFiles(value: unknown) {
|
|
const record: Record<string, string[]> = {}
|
|
if (!isRecord(value)) return record
|
|
for (const [key, item] of Object.entries(value)) {
|
|
if (typeof item === 'string') {
|
|
record[key] = item ? [item] : []
|
|
continue
|
|
}
|
|
if (Array.isArray(item)) {
|
|
record[key] = item.filter((url): url is string => typeof url === 'string' && Boolean(url))
|
|
}
|
|
}
|
|
return record
|
|
}
|
|
|
|
function cloneScreenshotFiles(value: Record<string, string[]>) {
|
|
return Object.fromEntries(Object.entries(value).map(([key, urls]) => [key, [...urls]]))
|
|
}
|
|
|
|
function normalizeQuantityModes(value: unknown) {
|
|
const record: Record<string, ChargeMode> = {}
|
|
if (!isRecord(value)) return record
|
|
for (const [key, item] of Object.entries(value)) {
|
|
if (item === '赠送' || item === '收费') record[key] = item
|
|
}
|
|
return record
|
|
}
|
|
|
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
return typeof value === 'object' && value !== null
|
|
}
|