Files
danyang-match/miniapp/constants/profileLabels.js
T
WorkBuddy c0298c27a5 fix(miniapp): 小程序界面全量中文化,消除英文/非中文枚举码上屏
- 新增 miniapp/constants/profileLabels.js 作为「枚举码→中文简体」唯一字典
  (婚姻/子女/学历/职业/吸烟饮酒/择偶子女/红娘状态),覆盖表单值与种子
  实际值两套并集,保证详情页无论后端返回哪种码都显示中文
- 修复「择偶条件-子女」下拉英文选项(any/accept/reject→不限/可接受/不接受),
  改用 value/label 数组 + range-key="label"
- 修复 recommend-card / user-card / profile-detail / profile-confirm 直接渲染
  后端枚举码(educationCode/maritalStatus/occupationCode…)的问题,改由
  observers 派生中文 label 上屏
- 清理残留英文文案:Required 条件→必须符合的条件、喜欢TA/向Ta→喜欢对方/向对方、
  U51 服务预约→服务预约、U64 公益服务记录→公益服务记录
- 修复 7 个英文窗口标题与 3 个英文占位页正文
- matchmaker 历史服务状态消除原始码兜底,统一走字典
- 加固 scripts/audit-miniapp-language.mjs(A 整行先剥离 mustache、B 排除
  bind:action 处理器、F 窗口标题、JPG/PNG 入白名单)
- 新增 ui-tests/miniapp-language-contracts.mjs 语种守卫(复用审计脚本,断言 0 命中),
  UI 契约门禁 MIN_GUARDS 21→22;已做负向注入验证判别力
2026-09-23 11:19:17 +08:00

190 lines
5.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 资料 / 择偶条件枚举码 → 中文简体 唯一字典
* ============================================================
* 铁律:界面上不允许出现任何英文枚举码(如 never_married / bachelor /
* government / any / accept / reject)。所有会展示给用户的状态码、选项码
* 都必须在本文件里有中文 label。
*
* 为什么要集中:
* - 小程序里最典型的缺陷是「后端枚举码直接当展示值」上屏(例如某卡片
* 直接渲染 educationCode=bachelor)。静态类型检查 / WXSS 编译 / 结构
* 守卫都发现不了,只有人眼在真机才看得见。
* - 后端 demo 种子与实际表单存的码存在历史不一致(表单用 occasional,
* 种子用 sometimes;表单用 yes/no,种子用 是/否)。labelOf 统一覆盖
* 两套并集,保证详情页无论后端返回哪种都显示中文。
*
* labelOf(group, code):
* - 空值返回 ''
* - 已知码返回中文
* - 未知码返回原值(便于排查;生产路径不应触发,否则说明字典需补)
*/
// ============ 婚姻状况 ============
const MARITAL = {
never_married: '未婚',
divorced: '离异',
widowed: '丧偶',
single: '未婚', // profile-confirm 旧别名
}
// ============ 子女情况 ============
const CHILDREN_STATUS = {
none: '无子女',
has: '有子女',
}
// ============ 学历 ============
// 覆盖表单值(high_school) 与种子实际值(senior_high/junior_high) 及别名
const EDUCATION = {
high_school: '高中/中专',
senior_high: '高中/中专',
junior_high: '初中',
college: '大专',
bachelor: '本科',
master: '硕士',
phd: '博士',
doctor: '博士', // profile-confirm 旧别名
}
// ============ 职业 ============
// 表单类目(生产路径)+ demo 种子实际值(自由英文词)
const OCCUPATION = {
government: '机关事业单位',
education: '教育',
medical: '医疗',
enterprise: '企业职员',
technical: '技术人员',
self_employed: '个体经营',
freelance: '自由职业',
service: '服务行业',
agriculture: '农业',
other: '其他',
// demo 种子实际值
clerical: '行政文职',
designer: '设计',
factory: '工厂生产',
nurse: '医护',
engineer: '工程师',
programmer: '程序员',
sales: '销售',
doctor: '医生',
researcher: '科研',
teacher: '教师',
}
// ============ 择偶条件:是否接受有孩(preference-editor 子女下拉) ============
const ACCEPT_CHILDREN = {
any: '不限',
accept: '可接受',
reject: '不接受',
}
// ============ 吸烟 / 饮酒 ============
// 覆盖表单值(occasional) 与种子实际值(sometimes)
const SMOKING = {
never: '不吸烟',
occasional: '偶尔吸烟',
sometimes: '偶尔吸烟',
often: '经常吸烟',
}
const DRINKING = {
never: '不喝酒',
occasional: '偶尔喝酒',
sometimes: '偶尔喝酒',
often: '经常喝酒',
}
// ============ 红娘服务状态(matchmaker 历史服务) ============
const MATCHMAKER_SERVICE_STATUS_LABEL = {
submitted: '已提交',
assigned: '已分配',
in_service: '服务中',
waiting_user: '待您确认',
completed: '已完成',
cancelled: '已取消',
}
const GROUPS = {
maritalStatus: MARITAL,
childrenStatus: CHILDREN_STATUS,
educationCode: EDUCATION,
occupationCode: OCCUPATION,
acceptChildren: ACCEPT_CHILDREN,
smokingStatus: SMOKING,
drinkingStatus: DRINKING,
}
/**
* 通用映射:已知码→中文,未知→原值
* @param {string} group GROUPS 的键
* @param {*} code 后端返回的原始码
* @returns {string}
*/
function labelOf(group, code) {
if (code === undefined || code === null || code === '') return ''
const map = GROUPS[group]
if (!map) return String(code)
return map[code] !== undefined ? map[code] : String(code)
}
/** 是/否类(长期居住丹阳等):兼容布尔、yes/no、是/否 三种来源 */
function yesNoLabel(v) {
if (v === true) return '是'
if (v === false) return '否'
if (v === 'yes') return '是'
if (v === 'no') return '否'
if (v === '是' || v === '否') return v
return v === undefined || v === null || v === '' ? '' : String(v)
}
/** 未来规划(未来是否愿意继续在丹阳):willing/uncertain/unwilling 或 是/否 */
function futureDanyangLabel(v) {
if (v === 'willing' || v === '是') return '愿意'
if (v === 'uncertain') return '不确定'
if (v === 'unwilling' || v === '否') return '不愿意'
return v === undefined || v === null || v === '' ? '' : String(v)
}
// ============ picker 选项数组(value/label 形式,供 wxml range + range-key 使用) ============
const ACCEPT_CHILDREN_OPTIONS = [
{ value: 'any', label: '不限' },
{ value: 'accept', label: '可接受' },
{ value: 'reject', label: '不接受' },
]
const MARITAL_OPTIONS = [
{ value: 'never_married', label: '未婚' },
{ value: 'divorced', label: '离异' },
{ value: 'widowed', label: '丧偶' },
]
const EDUCATION_OPTIONS = [
{ value: 'senior_high', label: '高中/中专' },
{ value: 'junior_high', label: '初中' },
{ value: 'college', label: '大专' },
{ value: 'bachelor', label: '本科' },
{ value: 'master', label: '硕士' },
{ value: 'phd', label: '博士' },
]
const OCCUPATION_OPTIONS = Object.keys(OCCUPATION).map((v) => ({ value: v, label: OCCUPATION[v] }))
module.exports = {
MARITAL,
CHILDREN_STATUS,
EDUCATION,
OCCUPATION,
ACCEPT_CHILDREN,
SMOKING,
DRINKING,
MATCHMAKER_SERVICE_STATUS_LABEL,
GROUPS,
labelOf,
yesNoLabel,
futureDanyangLabel,
ACCEPT_CHILDREN_OPTIONS,
MARITAL_OPTIONS,
EDUCATION_OPTIONS,
OCCUPATION_OPTIONS,
}