| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- /**
- * 活动费用展示口径(A3「活动费用展示层口径统一」共用工具)
- *
- * 数据契约(A2,字段名与取值对齐 A2 的 ActivityDTO,A2 未合入期间取默认值降级):
- * audienceScope: 'all'(默认)| 'member_only' —— 是否仅会员可参加
- * audienceType : 'adult'(默认)| 'include_child' | 'include_elder' | 'include_child_elder'
- *
- * 费用档位(A2 §2.1;长者复用成人价 —— D1 决策:不新增长者价格列):
- * 成人·非会员 price 成人·会员 memberPrice
- * 儿童·非会员 childFee 儿童·会员 childMemberFee
- *
- * 兼容存量(A2 §2.4):parentFee / parentMemberFee 降级为「成人非会员价」的历史别名
- * 成人非会员价 = price > 0 ? price : parentFee
- * 成人会员价 = memberPrice > 0 ? memberPrice : parentMemberFee
- * 老活动(只填 parent/parentMember 费用、price 为 0)在展示层仍要正确显示成人价。
- *
- * 注意:ActivityDTO.price 已被后端按会员等级解析(会员拿到 memberPrice),
- * memberPrice 仍是原始会员价。故本工具取"非会员列"用 price 优先 + parentFee 回落,
- * 取"会员列"用 memberPrice 优先 + parentMemberFee 回落。
- */
- export const AUDIENCE_SCOPE_ALL = 'all'
- export const AUDIENCE_SCOPE_MEMBER_ONLY = 'member_only'
- export const AUDIENCE_TYPE_ADULT = 'adult'
- export const AUDIENCE_TYPE_INCLUDE_CHILD = 'include_child'
- export const AUDIENCE_TYPE_INCLUDE_ELDER = 'include_elder'
- export const AUDIENCE_TYPE_INCLUDE_CHILD_ELDER = 'include_child_elder'
- const VALID_AUDIENCE_TYPES = [
- AUDIENCE_TYPE_ADULT,
- AUDIENCE_TYPE_INCLUDE_CHILD,
- AUDIENCE_TYPE_INCLUDE_ELDER,
- AUDIENCE_TYPE_INCLUDE_CHILD_ELDER
- ]
- export const IDENTITY_ADULT = 'adult'
- export const IDENTITY_CHILD = 'child'
- export const IDENTITY_ELDER = 'elder'
- const IDENTITY_LABELS = { adult: '成人', child: '儿童', elder: '长者' }
- /* eslint-disable no-restricted-globals */
- export function num(value) {
- if (value === null || value === undefined || value === '') return 0
- var n = Number(value)
- return isNaN(n) ? 0 : n
- }
- /* eslint-enable no-restricted-globals */
- /**
- * 归一化 audienceType:空值/非法值一律回落 adult(兼容存量活动与 A2 未合入期)
- * @param {string} type
- * @returns {string} 'adult' | 'include_child' | 'include_elder' | 'include_child_elder'
- */
- export function normalizeAudienceType(type) {
- var t = String(type == null ? '' : type).trim()
- if (VALID_AUDIENCE_TYPES.indexOf(t) >= 0) return t
- return AUDIENCE_TYPE_ADULT
- }
- /**
- * 归一化 audienceScope:空值/非法值一律回落 all
- * @param {string} scope
- * @returns {string} 'all' | 'member_only'
- */
- export function normalizeAudienceScope(scope) {
- return scope === AUDIENCE_SCOPE_MEMBER_ONLY ? AUDIENCE_SCOPE_MEMBER_ONLY : AUDIENCE_SCOPE_ALL
- }
- /** audienceType 是否含儿童人群 */
- export function audienceHasChild(type) {
- var t = normalizeAudienceType(type)
- return t === AUDIENCE_TYPE_INCLUDE_CHILD || t === AUDIENCE_TYPE_INCLUDE_CHILD_ELDER
- }
- /** audienceType 是否含长者人群 */
- export function audienceHasElder(type) {
- var t = normalizeAudienceType(type)
- return t === AUDIENCE_TYPE_INCLUDE_ELDER || t === AUDIENCE_TYPE_INCLUDE_CHILD_ELDER
- }
- /**
- * 成人档两列费用(分):{ regular, member }
- * 非会员列 price 优先、parentFee 回落;会员列 memberPrice 优先、parentMemberFee 回落
- */
- export function adultFees(activity) {
- var a = activity || {}
- var price = num(a.price)
- var memberPrice = num(a.memberPrice)
- return {
- regular: price > 0 ? price : num(a.parentFee),
- member: memberPrice > 0 ? memberPrice : num(a.parentMemberFee)
- }
- }
- /** 儿童档两列费用(分):{ regular, member } */
- export function childFees(activity) {
- var a = activity || {}
- return {
- regular: num(a.childFee),
- member: num(a.childMemberFee)
- }
- }
- /** 长者档费用:复用成人价(D1:不新增长者价格列) */
- export function elderFees(activity) {
- return adultFees(activity)
- }
- /** 身份标签文案:成人 / 儿童 / 长者 */
- export function identityLabel(identity) {
- return IDENTITY_LABELS[identity] || '成人'
- }
- /**
- * 身份判定(A2 §2.4 / D4):age < 18 → 儿童;age >= 60 → 长者;
- * 其余(含 age 为空/缺失)一律成人 —— 绝不可缺省判为儿童,否则会多收费。
- * @param {object} member FamilyMemberVO(需含 age)
- * @returns {string} 'adult' | 'child' | 'elder'
- */
- export function classifyIdentity(member) {
- var m = member || {}
- var age = num(m.age)
- if (age > 0 && age < 18) return IDENTITY_CHILD
- if (age >= 60) return IDENTITY_ELDER
- return IDENTITY_ADULT
- }
- /**
- * 当前用户在某身份下的生效单价(分)
- * 会员:取会员价列,会员价留空(0)→ 回落非会员价
- * 非会员:取非会员价列;长者复用成人价
- * @param {object} activity 活动对象(price/memberPrice/childFee/childMemberFee/parentFee/parentMemberFee)
- * @param {string} identity 'adult' | 'child' | 'elder'
- * @param {boolean} isMember 当前用户是否会员
- * @returns {number} 分值;0 表示免费
- */
- export function priceForIdentity(activity, identity, isMember) {
- var fees = identity === IDENTITY_CHILD ? childFees(activity) : adultFees(activity)
- if (isMember) {
- return fees.member > 0 ? fees.member : fees.regular
- }
- return fees.regular
- }
- /** 活动是否收费:任一人群任一档 > 0(纳入 price/memberPrice,修复"只填成人价误显免费") */
- export function hasAnyFee(activity) {
- var adult = adultFees(activity)
- var child = childFees(activity)
- return adult.regular > 0 || adult.member > 0 || child.regular > 0 || child.member > 0
- }
- /** 是否存在会员专享价(用于非会员引导开通会员) */
- export function hasAnyMemberFee(activity) {
- var adult = adultFees(activity)
- var child = childFees(activity)
- return adult.member > 0 || child.member > 0
- }
- /**
- * 当前用户可用档位的最小生效单价(分)
- * 可用档位 = 成人档(恒含)+ 儿童档(audienceType 含 child 时);长者复用成人价,不额外计档
- * @returns {number} 0 表示无可用付费档位(免费活动)
- */
- export function minAvailablePrice(activity, isMember) {
- var a = activity || {}
- var best = -1
- var adult = priceForIdentity(a, IDENTITY_ADULT, isMember)
- if (adult > 0) best = adult
- if (audienceHasChild(a.audienceType)) {
- var child = priceForIdentity(a, IDENTITY_CHILD, isMember)
- if (child > 0 && (best < 0 || child < best)) best = child
- }
- return best < 0 ? 0 : best
- }
- /**
- * 双价展示文案(与活动详情页原 feeText 口径一致)
- * 会员价更低时:「80.00(会员) / 100.00」;否则只显示主价;regular=0 且 member>0 →「会员免费」
- * @param {number} regularFee 非会员价(分)
- * @param {number} memberFee 会员价(分)
- * @returns {string} 如 "100.00" / "80.00(会员) / 100.00" / "0.00" / "会员免费"
- */
- export function feeText(regularFee, memberFee) {
- var regular = num(regularFee) / 100
- var member = num(memberFee) / 100
- if (member > 0 && member < regular) return member.toFixed(2) + '(会员) / ' + regular.toFixed(2)
- if (regular === 0 && member === 0) return '0.00'
- if (regular === 0) return '会员免费'
- return regular.toFixed(2)
- }
- /**
- * 海报价格文案信息:按 audienceType 选档位标签与价格
- * 1) 含儿童人群且儿童档有价 → 儿童价(儿童)
- * 2) 含长者人群 → 成人价(长者) ← 长者复用成人价
- * 3) 其余 → 成人价(成人)
- * @returns {{label:string, text:string}} label 为 '成人'/'儿童'/'长者'/'免费'
- */
- export function posterPriceInfo(activity) {
- var a = activity || {}
- var t = normalizeAudienceType(a.audienceType)
- var adult = adultFees(a)
- var child = childFees(a)
- if (!hasAnyFee(a)) return { label: '免费', text: '免费' }
- var label = '成人'
- var regular = adult.regular
- var member = adult.member
- if (audienceHasChild(t) && (child.regular > 0 || child.member > 0)) {
- label = '儿童'
- regular = child.regular
- member = child.member
- } else if (audienceHasElder(t)) {
- label = '长者'
- }
- return { label: label, text: feeText(regular, member) + '(' + label + ')' }
- }
- /**
- * audienceType → 后台多选勾选数组('adult' 恒选)
- * @param {string} type
- * @returns {string[]} 如 ['adult', 'child']
- */
- export function audienceTypeList(type) {
- var t = normalizeAudienceType(type)
- var list = ['adult']
- if (audienceHasChild(t)) list.push('child')
- if (audienceHasElder(t)) list.push('elder')
- return list
- }
- /**
- * 后台多选勾选数组 → audienceType 编码
- * @param {string[]} list 如 ['adult', 'child']
- * @returns {string} 'adult' | 'include_child' | 'include_elder' | 'include_child_elder'
- */
- export function encodeAudienceType(list) {
- var arr = list || []
- var hasChild = false
- var hasElder = false
- for (var i = 0; i < arr.length; i++) {
- if (arr[i] === 'child') hasChild = true
- else if (arr[i] === 'elder') hasElder = true
- }
- if (hasChild && hasElder) return AUDIENCE_TYPE_INCLUDE_CHILD_ELDER
- if (hasChild) return AUDIENCE_TYPE_INCLUDE_CHILD
- if (hasElder) return AUDIENCE_TYPE_INCLUDE_ELDER
- return AUDIENCE_TYPE_ADULT
- }
- /** audienceScope 展示文案 */
- export function audienceScopeLabel(scope) {
- return scope === AUDIENCE_SCOPE_MEMBER_ONLY ? '仅会员参加' : '全部用户'
- }
|