feat: 首页的样式的调整

This commit is contained in:
zoujing committed 2026-07-30 22:00:37 +08:00
1 parent 76abf4a9f0
commit 0bb34f8aa7
3 files changed
+82 -70

No files matched your search

+22 -22
View File
@@ -35,17 +35,19 @@ test('provides coherent default visitor ticket data', async () => {
const productsById = new Map(PRODUCTS.map((product) => [product.id, product]))
assert.ok(GROUPS.every((group) => group.productIds.every((productId) => productsById.has(productId))))
assert.deepEqual(GROUPS.flatMap((group) => group.productIds).sort(), PRODUCTS.map(({ id }) => id).sort())
const productKeys = ['id', 'name', 'shortTitle', 'category', 'description', 'salePrice', 'marketPrice', 'stock', 'sold', 'status', 'highlights', 'ageRule', 'included', 'excluded', 'detail', 'purchaseNotice', 'images', 'reservation', 'entitlements']
const productKeys = ['id', 'name', 'shortTitle', 'category', 'description', 'salePrice', 'marketPrice', 'stock', 'sold', 'status', 'clientVisible', 'highlights', 'ageRule', 'included', 'excluded', 'detail', 'purchaseNotice', 'images', 'reservation', 'entitlements']
const reservationKeys = ['requiresDate', 'advanceDays', 'requiresTimeSlot', 'timeSlots', 'realNameRequired', 'idTypes', 'maxQuantity', 'contactPhoneRequired']
const entitlementKeys = ['id', 'name', 'fulfillment', 'quantity', 'unit', 'refundAllocation']
assert.ok(PRODUCTS.every((product) => productKeys.every((key) => key in product) && product.status === 'on_sale' && Number.isFinite(product.salePrice) && Number.isFinite(product.stock) && Number.isFinite(product.sold) && product.images.length === 1 && product.images[0] === PLACEHOLDER_IMAGE && reservationKeys.every((key) => key in product.reservation) && product.entitlements.length && product.entitlements.every((entitlement) => entitlementKeys.every((key) => key in entitlement))))
assert.ok(PRODUCTS.every((product) => productKeys.every((key) => key in product) && ['on_sale', 'draft'].includes(product.status) && Number.isFinite(product.salePrice) && Number.isFinite(product.stock) && Number.isFinite(product.sold) && product.images.length === 1 && product.images[0] === PLACEHOLDER_IMAGE && reservationKeys.every((key) => key in product.reservation) && product.entitlements.length && product.entitlements.every((entitlement) => entitlementKeys.every((key) => key in entitlement))))
assert.deepEqual(PRODUCTS.filter(({ status, clientVisible }) => status !== 'on_sale' || clientVisible === false).map(({ id }) => id), ['guide'])
assert.deepEqual(PRODUCTS.map(({ id, salePrice, marketPrice, sold }) => [id, salePrice, marketPrice, sold]), [
['adult', 160, 170, 2386], ['elderly', 100, 160, 816], ['minor', 100, 160, 629], ['free', 40, 80, 346], ['vip-fast', 98, 128, 126], ['direct-bus', 68, 88, 92], ['classic', 188, 210, 184], ['day-tour', 188, 228, 68], ['boat', 50, 60, 326], ['guide', 68, 88, 40],
['adult', 160, 160, 2386], ['elderly', 100, 100, 816], ['minor', 100, 100, 629], ['free', 40, 40, 346], ['vip-fast', 98, 98, 126], ['direct-bus', 68, 68, 92], ['classic', 188, 210, 184], ['day-tour', 188, 188, 68], ['boat', 50, 60, 326], ['guide', 68, 88, 0],
])
assert.deepEqual(productsById.get('elderly').ageRule, { min: 60, max: 120 })
assert.deepEqual(productsById.get('elderly').ageRule, { min: 60, max: 999 })
assert.deepEqual(productsById.get('minor').ageRule, { min: 6, max: 17 })
assert.deepEqual(productsById.get('free').ageRule, { min: 0, max: 120 })
assert.deepEqual(productsById.get('adult').entitlements.map(({ fulfillment, refundAllocation }) => [fulfillment, refundAllocation]), [['third_party', 120], ['third_party', 40]])
assert.deepEqual(productsById.get('classic').entitlements.map(({ fulfillment, refundAllocation }) => [fulfillment, refundAllocation]), [['third_party', 160], ['self', 28]])
assert.deepEqual(productsById.get('classic').entitlements.map(({ fulfillment, refundAllocation }) => [fulfillment, refundAllocation]), [['third_party', 120], ['third_party', 40], ['self', 28]])
for (const productId of ['vip-fast', 'day-tour', 'boat', 'guide']) assert.ok(productsById.get(productId).entitlements.every(({ fulfillment }) => fulfillment === 'self'))
for (const productId of ['direct-bus', 'free', 'elderly', 'minor']) assert.ok(productsById.get(productId).entitlements.every(({ fulfillment }) => fulfillment === 'third_party'))
const standardSlots = ['08:00—09:30', '09:30—11:30', '11:30—13:30', '13:30—15:00', '15:00—16:00']
@@ -64,17 +66,15 @@ test('provides coherent default visitor ticket data', async () => {
assert.deepEqual(INITIAL_TRAVELERS, [
{ id: 'traveler-lin-xiao', name: '林晓', idType: '身份证', idNumber: '110101199001020010', phone: '13800138000' }, { id: 'traveler-zhou-ning', name: '周宁', idType: '身份证', idNumber: '110101196001020017', phone: '13900139000' },
])
assert.deepEqual(productsById.get('adult'), {
id: 'adult', name: '成人门票+观光车', shortTitle: '成人门票+观光车', category: '景点门票', description: '荔波小七孔景区成人入园门票。', salePrice: 160, marketPrice: 170, stock: 120, sold: 2386, status: 'on_sale', highlights: ['实名预约入园', '覆盖核心景区'], ageRule: null, included: ['成人景区门票', '景区观光车'], excluded: ['餐饮及个人消费'], detail: '凭本人有效证件在预约时段入园。', purchaseNotice: '请至少提前一天预约,订单当天不可退改。', images: [PLACEHOLDER_IMAGE], reservation: { requiresDate: true, advanceDays: 1, requiresTimeSlot: true, timeSlots: standardSlots, realNameRequired: true, idTypes: ['身份证', '护照', '港澳居民来往内地通行证'], maxQuantity: 5, contactPhoneRequired: true }, entitlements: [{ id: 'adult-ticket', name: '成人门票', fulfillment: 'third_party', quantity: 1, unit: '张', refundAllocation: 120 }, { id: 'shuttle', name: '观光车票', fulfillment: 'third_party', quantity: 1, unit: '张', refundAllocation: 40 }],
})
assert.deepEqual(productsById.get('classic'), {
id: 'classic', name: '门票+观光车+鸳鸯湖游船', shortTitle: '门票+观光车+鸳鸯湖游船', category: '门票+观光车', description: '景区成人门票与观光车组合套餐。', salePrice: 188, marketPrice: 210, stock: 90, sold: 184, status: 'on_sale', highlights: ['门票观光车联票', '比单买更优惠'], ageRule: { min: 18, max: 59 }, included: ['成人景区门票', '景区观光车', '鸳鸯湖游船'], excluded: ['餐饮及个人消费'], detail: '一次预约即可享受门票、观光车与鸳鸯湖游船。', purchaseNotice: '各权益可分别核销,未使用部分可按规则申请退款。', images: [PLACEHOLDER_IMAGE], reservation: { requiresDate: true, advanceDays: 1, requiresTimeSlot: true, timeSlots: standardSlots, realNameRequired: true, idTypes: ['身份证'], maxQuantity: 5, contactPhoneRequired: true }, entitlements: [{ id: 'classic-ticket-shuttle', name: '成人门票+观光车', fulfillment: 'third_party', quantity: 1, unit: '张', refundAllocation: 160 }, { id: 'classic-boat', name: '鸳鸯湖游船', fulfillment: 'self', quantity: 1, unit: '张', refundAllocation: 28 }],
})
assert.deepEqual(productsById.get('adult').reservation, { requiresDate: true, advanceDays: 30, requiresTimeSlot: true, timeSlots: standardSlots, realNameRequired: true, idTypes: ['身份证', '护照'], maxQuantity: 5, contactPhoneRequired: true })
assert.deepEqual(productsById.get('adult').highlights, ['官方', '可订明日', '随时退', '无需取票'])
assert.deepEqual(productsById.get('classic').reservation, { requiresDate: true, advanceDays: 30, requiresTimeSlot: true, timeSlots: standardSlots, realNameRequired: true, idTypes: ['身份证', '护照'], maxQuantity: 5, contactPhoneRequired: true })
assert.deepEqual(productsById.get('classic').highlights, ['官方', '实名预约', '整包退', '双凭证'])
assert.deepEqual(INITIAL_TRAVELERS[0], { id: 'traveler-lin-xiao', name: '林晓', idType: '身份证', idNumber: '110101199001020010', phone: '13800138000' })
assert.equal(INITIAL_ORDERS.length, 2)
assert.deepEqual(INITIAL_ORDERS.map(({ productId, visitDate, timeSlot, quantity, travelers, insurance, gateCredential, selfCredential, entitlements }) => ({ productId, visitDate, timeSlot, quantity, travelers, insurance, hasGateCredential: Boolean(gateCredential), hasSelfCredential: Boolean(selfCredential), fulfillment: entitlements.map(({ fulfillment }) => fulfillment) })), [
{ productId: 'adult', visitDate: '2026-08-01', timeSlot: '08:00—09:30', quantity: 1, travelers: [{ id: 'traveler-lin-xiao', name: '林晓', idType: '身份证', idNumber: '110101199001020010', phone: '13800138000' }], insurance: { name: '出行意外险', price: 5, quantity: 1, status: 'active' }, hasGateCredential: true, hasSelfCredential: false, fulfillment: ['third_party', 'third_party'] },
{ productId: 'classic', visitDate: '2026-08-02', timeSlot: '09:30—11:30', quantity: 1, travelers: [{ id: 'traveler-lin-xiao', name: '林晓', idType: '身份证', idNumber: '110101199001020010', phone: '13800138000' }], insurance: null, hasGateCredential: true, hasSelfCredential: true, fulfillment: ['third_party', 'self'] },
{ productId: 'classic', visitDate: '2026-08-02', timeSlot: '09:30—11:30', quantity: 1, travelers: [{ id: 'traveler-lin-xiao', name: '林晓', idType: '身份证', idNumber: '110101199001020010', phone: '13800138000' }], insurance: null, hasGateCredential: true, hasSelfCredential: true, fulfillment: ['third_party', 'third_party', 'self'] },
])
for (const order of INITIAL_ORDERS) {
assert.notEqual(order.travelers[0], INITIAL_TRAVELERS[0])
@@ -118,26 +118,26 @@ test('keeps ticket source prototypes, valid traveler IDs, and entitlement alloca
const productsById = new Map(PRODUCTS.map((product) => [product.id, product]))
assert.equal(productsById.get('adult').ageRule, null)
assert.deepEqual(productsById.get('adult').name, '成人门票+观光车')
assert.deepEqual(productsById.get('elderly').name, '老年人门票+观光车')
assert.deepEqual(productsById.get('minor').name, '未成年门票+观光车')
assert.deepEqual(productsById.get('free').name, '免门票+观光车实名预约')
assert.deepEqual(productsById.get('classic').name, '门票+观光车+鸳鸯湖游船')
assert.deepEqual(productsById.get('adult').name, '荔波小七孔成人票+观光车')
assert.deepEqual(productsById.get('elderly').name, '荔波小七孔老年人票+观光车')
assert.deepEqual(productsById.get('minor').name, '荔波小七孔未成年票+观光车')
assert.deepEqual(productsById.get('free').name, '荔波小七孔免门票+观光车')
assert.deepEqual(productsById.get('classic').name, '小七孔经典畅游套餐')
assert.deepEqual(productsById.get('boat').name, '鸳鸯湖游船票')
assert.deepEqual(productsById.get('day-tour').name, '荔波小七孔精品一日游')
assert.deepEqual(productsById.get('guide').name, '小七孔精品讲解服务')
assert.deepEqual(productsById.get('direct-bus').name, '贵阳往返小七孔直通车')
assert.deepEqual(productsById.get('direct-bus').name, '贵阳往返小七孔景区直通车')
assert.deepEqual(productsById.get('elderly').reservation.idTypes, ['身份证'])
assert.deepEqual(productsById.get('minor').reservation.idTypes, ['身份证'])
assert.ok(PRODUCTS.filter((product) => product.ageRule).every((product) => product.reservation.idTypes.length === 1 && product.reservation.idTypes[0] === '身份证'))
assert.ok(productsById.get('direct-bus').included.every((item) => item.includes('往返')))
assert.match(productsById.get('direct-bus').detail, /往返/)
assert.match(productsById.get('direct-bus').purchaseNotice, /往返/)
assert.deepEqual(productsById.get('adult').entitlements.map(({ name, fulfillment, refundAllocation }) => [name, fulfillment, refundAllocation]), [['成人门票', 'third_party', 120], ['观光车票', 'third_party', 40]])
assert.match(productsById.get('direct-bus').detail, /乘车凭证/)
assert.match(productsById.get('direct-bus').purchaseNotice, /提前20分钟/)
assert.deepEqual(productsById.get('adult').entitlements.map(({ name, fulfillment, refundAllocation }) => [name, fulfillment, refundAllocation]), [['小七孔成人门票', 'third_party', 120], ['小七孔观光车票', 'third_party', 40]])
assert.deepEqual(productsById.get('elderly').entitlements.map(({ refundAllocation }) => refundAllocation), [60, 40])
assert.deepEqual(productsById.get('minor').entitlements.map(({ refundAllocation }) => refundAllocation), [60, 40])
assert.deepEqual(productsById.get('free').entitlements.map(({ refundAllocation }) => refundAllocation), [0, 40])
assert.deepEqual(productsById.get('classic').entitlements.map(({ name, fulfillment, refundAllocation }) => [name, fulfillment, refundAllocation]), [['成人门票+观光车', 'third_party', 160], ['鸳鸯湖游船', 'self', 28]])
assert.deepEqual(productsById.get('classic').entitlements.map(({ name, fulfillment, refundAllocation }) => [name, fulfillment, refundAllocation]), [['小七孔成人门票', 'third_party', 120], ['观光车票', 'third_party', 40], ['鸳鸯湖游船', 'self', 28]])
assert.ok(PRODUCTS.every((product) => product.entitlements.every((entitlement) => Number.isFinite(entitlement.quantity) && entitlement.quantity > 0 && Number.isFinite(entitlement.refundAllocation)) && product.entitlements.reduce((total, entitlement) => total + entitlement.refundAllocation, 0) === product.salePrice))
assert.deepEqual(INITIAL_TRAVELERS[1], { id: 'traveler-zhou-ning', name: '周宁', idType: '身份证', idNumber: '110101196001020017', phone: '13900139000' })
})