hookehuyr

refactor(plan): 优化计划书字段配置管理

- 提取计划书字段定义到独立配置文件 (plan-fields.js)
  - 定义字段类型枚举 (TEXT, NUMBER, AMOUNT, SELECT, RADIO, DATE, NAME)
  - 配置字段属性 (label, type, required, api_field, component)
  - 支持字段验证规则和显示条件
  - 支持字段依赖关系 (affects, depends_on)
- 新增字段值转换工具 (planFieldTransformers.js)
  - 分转元: fenToYuan (10000 → "100.00")
  - 元转分: yuanToFen ("100.00" → 10000)
  - 年龄格式化: formatAge (25 → "25岁")
  - 批量转换: batchTransformFields
  - 反向转换: reverseTransformFields
- 新增测试目录 (src/utils/__tests__)

影响文件:
- src/config/plan-fields.js (新增)
- src/utils/planFieldTransformers.js (新增)
- src/utils/__tests__/planFieldTransformers.test.js (新增)

技术栈: Vue 3, Taro 4

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 +/**
2 + * 计划书字段配置
3 + *
4 + * @description 统一管理所有计划书字段的配置信息,包括字段类型、验证规则、API 映射等
5 + * @module config/plan-fields
6 + * @author Claude Code
7 + * @created 2026-02-14
8 + */
9 +
10 +/**
11 + * 字段类型枚举
12 + * @enum {string}
13 + */
14 +export const FIELD_TYPES = {
15 + TEXT: 'text',
16 + NUMBER: 'number',
17 + AMOUNT: 'amount',
18 + PERCENTAGE: 'percentage',
19 + SELECT: 'select',
20 + RADIO: 'radio',
21 + DATE: 'date',
22 + NAME: 'name'
23 +}
24 +
25 +/**
26 + * 数据转换类型枚举
27 + * @enum {string}
28 + */
29 +export const TRANSFORM_TYPES = {
30 + FEN_TO_YUAN: 'fen_to_yuan', // 分转元
31 + YUAN_TO_FEN: 'yuan_to_fen', // 元转分
32 + NONE: 'none' // 无需转换
33 +}
34 +
35 +/**
36 + * 计划书字段定义
37 + * @type {Object<string, FieldDefinition>}
38 + * @property {Object} customer_name - 申请人姓名
39 + * @property {Object} gender - 性别
40 + * @property {Object} birthday - 出生日期
41 + * @property {Object} smoker - 是否吸烟
42 + * @property {Object} coverage - 保额
43 + * @property {Object} payment_period - 缴费年期
44 + * @property {Object} withdrawal_enabled - 是否启用提取
45 + * @property {Object} withdrawal_mode - 提取模式
46 + * @property {Object} withdrawal_start_age - 开始提取年龄
47 + * @property {Object} withdrawal_period - 提取年期
48 + * @property {Object} withdrawal_method - 提取方式
49 + * @property {Object} annual_withdrawal_amount - 年提取金额
50 + * @property {Object} annual_increase_percentage - 年递增比例
51 + * @property {Object} total_amount - 总保费
52 + */
53 +export const PLAN_FIELD_DEFINITIONS = {
54 + /**
55 + * 申请人姓名
56 + */
57 + customer_name: {
58 + label: '申请人',
59 + type: FIELD_TYPES.TEXT,
60 + required: true,
61 + api_field: 'customer_name',
62 + placeholder: '请输入申请人姓名',
63 + component: 'PlanFieldName',
64 + validation: {
65 + required: (value) => value?.trim()?.length >= 2
66 + }
67 + },
68 +
69 + /**
70 + * 性别
71 + */
72 + gender: {
73 + label: '性别',
74 + type: FIELD_TYPES.RADIO,
75 + required: true,
76 + api_field: 'customer_gender',
77 + component: 'PlanFieldRadio',
78 + options: [
79 + { label: '男', value: 'male' },
80 + { label: '女', value: 'female' }
81 + ],
82 + default: 'male'
83 + },
84 +
85 + /**
86 + * 出生日期
87 + */
88 + birthday: {
89 + label: '出生年月日',
90 + type: FIELD_TYPES.DATE,
91 + required: true,
92 + api_field: 'customer_birthday',
93 + component: 'PlanFieldDatePicker',
94 + placeholder: '请选择出生年月日'
95 + },
96 +
97 + /**
98 + * 是否吸烟
99 + */
100 + smoker: {
101 + label: '是否吸烟',
102 + type: FIELD_TYPES.RADIO,
103 + required: true,
104 + api_field: 'smoking_status',
105 + component: 'PlanFieldRadio',
106 + options: [
107 + { label: '是', value: 'yes' },
108 + { label: '否', value: 'no' }
109 + ],
110 + default: 'no'
111 + },
112 +
113 + /**
114 + * 保额(年缴)
115 + */
116 + coverage: {
117 + label: '保额',
118 + type: FIELD_TYPES.AMOUNT,
119 + required: true,
120 + api_field: 'annual_premium',
121 + transform: TRANSFORM_TYPES.FEN_TO_YUAN,
122 + component: 'PlanFieldAmount',
123 + placeholder: '请输入保额',
124 + validation: {
125 + required: (value) => value > 0,
126 + min: (value, config) => value >= (config?.min_coverage || 1000),
127 + max: (value, config) => value <= (config?.max_coverage || 10000000)
128 + }
129 + },
130 +
131 + /**
132 + * 缴费年期
133 + */
134 + payment_period: {
135 + label: '缴费年期',
136 + type: FIELD_TYPES.SELECT,
137 + required: true,
138 + api_field: 'payment_years',
139 + component: 'PlanFieldSelect',
140 + options_from: 'payment_periods', // 从模板配置获取选项
141 + placeholder: '请选择缴费年期'
142 + },
143 +
144 + /**
145 + * 是否启用提取
146 + */
147 + withdrawal_enabled: {
148 + label: '启用提取计划',
149 + type: FIELD_TYPES.RADIO,
150 + required: false,
151 + api_field: 'allow_reduce_amount',
152 + component: 'PlanFieldRadio',
153 + options: [
154 + { label: '是', value: true },
155 + { label: '否', value: false }
156 + ],
157 + default: false,
158 + affects: ['withdrawal_mode', 'withdrawal_start_age', 'withdrawal_period', 'withdrawal_method', 'annual_withdrawal_amount']
159 + },
160 +
161 + /**
162 + * 提取模式
163 + */
164 + withdrawal_mode: {
165 + label: '提取模式',
166 + type: FIELD_TYPES.SELECT,
167 + required: false,
168 + api_field: 'withdrawal_option',
169 + component: 'PlanFieldSelect',
170 + options_from: 'withdrawal_plan.withdrawal_modes',
171 + depends_on: 'withdrawal_enabled',
172 + show_when: { withdrawal_enabled: true }
173 + },
174 +
175 + /**
176 + * 开始提取年龄
177 + */
178 + withdrawal_start_age: {
179 + label: '开始提取年龄',
180 + type: FIELD_TYPES.NUMBER,
181 + required: false,
182 + api_field: 'withdrawal_start_age',
183 + component: 'PlanFieldAgePicker',
184 + depends_on: 'withdrawal_enabled',
185 + show_when: { withdrawal_enabled: true },
186 + default_from: 'age_range.min'
187 + },
188 +
189 + /**
190 + * 提取年期
191 + */
192 + withdrawal_period: {
193 + label: '提取年期',
194 + type: FIELD_TYPES.SELECT,
195 + required: false,
196 + api_field: 'withdrawal_period',
197 + component: 'PlanFieldSelect',
198 + options_from: 'withdrawal_plan.withdrawal_periods',
199 + depends_on: 'withdrawal_enabled',
200 + show_when: { withdrawal_enabled: true }
201 + },
202 +
203 + /**
204 + * 提取方式
205 + */
206 + withdrawal_method: {
207 + label: '提取方式',
208 + type: FIELD_TYPES.SELECT,
209 + required: false,
210 + api_field: 'withdrawal_method',
211 + component: 'PlanFieldSelect',
212 + options: ['现金', '抵缴保费'],
213 + depends_on: 'withdrawal_enabled',
214 + show_when: { withdrawal_enabled: true }
215 + },
216 +
217 + /**
218 + * 年提取金额
219 + */
220 + annual_withdrawal_amount: {
221 + label: '年提取金额',
222 + type: FIELD_TYPES.AMOUNT,
223 + required: false,
224 + api_field: 'annual_withdrawal_amount',
225 + transform: TRANSFORM_TYPES.FEN_TO_YUAN,
226 + component: 'PlanFieldAmount',
227 + depends_on: 'withdrawal_enabled',
228 + show_when: { withdrawal_enabled: true },
229 + placeholder: '请输入年提取金额'
230 + },
231 +
232 + /**
233 + * 年递增比例
234 + */
235 + annual_increase_percentage: {
236 + label: '年递增比例',
237 + type: FIELD_TYPES.PERCENTAGE,
238 + required: false,
239 + api_field: 'annual_increase_percentage',
240 + transform: TRANSFORM_TYPES.NONE,
241 + component: 'PlanFieldAmount',
242 + validation: {
243 + range: (value) => {
244 + const num = parseFloat(value)
245 + return !Number.isNaN(num) && num >= 0 && num <= 100
246 + }
247 + }
248 + },
249 +
250 + /**
251 + * 总保费
252 + */
253 + total_amount: {
254 + label: '总保费',
255 + type: FIELD_TYPES.AMOUNT,
256 + required: false,
257 + api_field: 'total_premium',
258 + transform: TRANSFORM_TYPES.FEN_TO_YUAN,
259 + component: 'PlanFieldAmount',
260 + placeholder: '请输入总保费'
261 + }
262 +}
263 +
264 +/**
265 + * 获取字段定义
266 + * @param {string} fieldKey - 字段键名
267 + * @returns {FieldDefinition|null} 字段定义
268 + */
269 +export function getFieldDefinition(fieldKey) {
270 + return PLAN_FIELD_DEFINITIONS[fieldKey] || null
271 +}
272 +
273 +/**
274 + * 获取字段对应的所有依赖字段
275 + * @param {string} fieldKey - 字段键名
276 + * @returns {string[]} 依赖字段的键名数组
277 + */
278 +export function getFieldDependencies(fieldKey) {
279 + const definition = getFieldDefinition(fieldKey)
280 + return definition?.affects || []
281 +}
282 +
283 +/**
284 + * 获取字段的 API 字段名
285 + * @param {string} fieldKey - 字段键名
286 + * @returns {string} API 字段名
287 + */
288 +export function getFieldApiField(fieldKey) {
289 + const definition = getFieldDefinition(fieldKey)
290 + return definition?.api_field || fieldKey
291 +}
292 +
293 +/**
294 + * 检查字段是否需要值转换
295 + * @param {string} fieldKey - 字段键名
296 + * @returns {boolean} 是否需要转换
297 + */
298 +export function fieldNeedsTransform(fieldKey) {
299 + const definition = getFieldDefinition(fieldKey)
300 + return definition?.transform && definition.transform !== TRANSFORM_TYPES.NONE
301 +}
302 +
303 +/**
304 + * 字段定义类型
305 + * @typedef {Object} FieldDefinition
306 + * @property {string} label - 字段显示名称
307 + * @property {string} type - 字段类型(见 FIELD_TYPES)
308 + * @property {boolean} required - 是否必填
309 + * @property {string} api_field - API 字段名
310 + * @property {string} [component] - 对应组件名
311 + * @property {string} [placeholder] - 占位符文本
312 + * @property {Array} [options] - 选项列表(select/radio 类型)
313 + * @property {string} [options_from] - 选项来源(从模板配置获取)
314 + * @property {*} [default] - 默认值
315 + * @property {string} [transform] - 值转换类型(见 TRANSFORM_TYPES)
316 + * @property {Object} [validation] - 验证规则
317 + * @property {Function} [validation.required] - 必填验证函数
318 + * @property {string[]} [affects] - 影响的字段列表
319 + * @property {string} [depends_on] - 依赖的字段
320 + * @property {Object} [show_when] - 显示条件
321 + * @property {string} [default_from] - 默认值来源(从其他字段获取)
322 + */
1 +/**
2 + * planFieldTransformers 单元测试
3 + * @description 测试字段值转换工具函数
4 + * @module utils/__tests__/planFieldTransformers.test
5 + */
6 +
7 +import { describe, it, expect } from 'vitest'
8 +import {
9 + fenToYuan,
10 + yuanToFen,
11 + formatAge,
12 + noneTransform,
13 + transformFieldValue,
14 + batchTransformFields,
15 + reverseTransformFields
16 +} from '../planFieldTransformers'
17 +import { TRANSFORM_TYPES } from '@/config/plan-fields'
18 +
19 +describe('fenToYuan', () => {
20 + it('should convert fen to yuan correctly', () => {
21 + expect(fenToYuan(10000)).toBe('100.00')
22 + expect(fenToYuan(100)).toBe('1.00')
23 + expect(fenToYuan(1)).toBe('0.01')
24 + })
25 +
26 + it('should handle zero', () => {
27 + expect(fenToYuan(0)).toBe('0.00')
28 + })
29 +
30 + it('should handle null and undefined', () => {
31 + expect(fenToYuan(null)).toBe(null)
32 + expect(fenToYuan(undefined)).toBe(undefined) // 保持原值
33 + })
34 +
35 + it('should handle string numbers', () => {
36 + expect(fenToYuan('10000')).toBe('100.00')
37 + expect(fenToYuan('100')).toBe('1.00')
38 + })
39 +
40 + it('should handle invalid values', () => {
41 + expect(fenToYuan('invalid')).toBe(null)
42 + expect(fenToYuan(NaN)).toBe(null)
43 + })
44 +})
45 +
46 +describe('yuanToFen', () => {
47 + it('should convert yuan to fen correctly', () => {
48 + expect(yuanToFen('100.00')).toBe(10000)
49 + expect(yuanToFen('1.00')).toBe(100)
50 + expect(yuanToFen('0.01')).toBe(1)
51 + })
52 +
53 + it('should handle zero', () => {
54 + expect(yuanToFen('0.00')).toBe(0)
55 + expect(yuanToFen(0)).toBe(0)
56 + })
57 +
58 + it('should handle null and undefined', () => {
59 + expect(yuanToFen(null)).toBe(null)
60 + expect(yuanToFen(undefined)).toBe(null)
61 + })
62 +
63 + it('should handle string numbers', () => {
64 + expect(yuanToFen('100.00')).toBe(10000)
65 + expect(yuanToFen('100')).toBe(10000)
66 + })
67 +})
68 +
69 +describe('formatAge', () => {
70 + it('should format age correctly', () => {
71 + expect(formatAge(25)).toBe('25岁')
72 + expect(formatAge(0)).toBe('0岁')
73 + })
74 +
75 + it('should handle null and undefined', () => {
76 + expect(formatAge(null)).toBe(null)
77 + expect(formatAge(undefined)).toBe(null)
78 + })
79 +})
80 +
81 +describe('transformFieldValue', () => {
82 + it('should transform fen to yuan', () => {
83 + expect(transformFieldValue(10000, TRANSFORM_TYPES.FEN_TO_YUAN)).toBe('100.00')
84 + })
85 +
86 + it('should transform yuan to fen', () => {
87 + expect(transformFieldValue('100.00', TRANSFORM_TYPES.YUAN_TO_FEN)).toBe(10000)
88 + })
89 +
90 + it('should pass through for none transform', () => {
91 + expect(transformFieldValue('test', TRANSFORM_TYPES.NONE)).toBe('test')
92 + })
93 +
94 + it('should handle null values', () => {
95 + expect(transformFieldValue(null, TRANSFORM_TYPES.FEN_TO_YUAN)).toBe(null)
96 + })
97 +})
98 +
99 +describe('batchTransformFields', () => {
100 + it('should transform multiple fields according to definitions', () => {
101 + const formData = {
102 + coverage: 10000,
103 + annual_withdrawal_amount: 5000,
104 + name: 'Test'
105 + }
106 +
107 + const fieldDefinitions = {
108 + coverage: {
109 + transform: TRANSFORM_TYPES.FEN_TO_YUAN
110 + },
111 + annual_withdrawal_amount: {
112 + transform: TRANSFORM_TYPES.FEN_TO_YUAN
113 + },
114 + name: {
115 + // 无 transform 属性
116 + }
117 + }
118 +
119 + const result = batchTransformFields(formData, fieldDefinitions)
120 +
121 + expect(result.coverage).toBe('100.00')
122 + expect(result.annual_withdrawal_amount).toBe('50.00')
123 + expect(result.name).toBe('Test') // 保持原值
124 + })
125 +
126 + it('should skip undefined values', () => {
127 + const formData = {
128 + coverage: undefined,
129 + name: 'Test'
130 + }
131 +
132 + const fieldDefinitions = {
133 + coverage: {
134 + transform: TRANSFORM_TYPES.FEN_TO_YUAN
135 + },
136 + name: {}
137 + }
138 +
139 + const result = batchTransformFields(formData, fieldDefinitions)
140 +
141 + // coverage 是 undefined,转换后应该仍然是 undefined
142 + expect(result.coverage).toBeUndefined()
143 + // name 没有变化,应该保持原值
144 + expect(result.name).toBe('Test')
145 + })
146 +})
147 +
148 +describe('reverseTransformFields', () => {
149 + it('should convert API data back to form format', () => {
150 + const apiData = {
151 + annual_premium: '100.00',
152 + annual_withdrawal_amount: '50.00',
153 + name: 'Test'
154 + }
155 +
156 + const fieldDefinitions = {
157 + annual_premium: {
158 + api_field: 'annual_premium',
159 + transform: TRANSFORM_TYPES.FEN_TO_YUAN
160 + },
161 + annual_withdrawal_amount: {
162 + api_field: 'annual_withdrawal_amount',
163 + transform: TRANSFORM_TYPES.FEN_TO_YUAN
164 + },
165 + name: {
166 + api_field: 'name'
167 + }
168 + }
169 +
170 + const result = reverseTransformFields(apiData, fieldDefinitions)
171 +
172 + // formKey 是 annual_premium,所以结果键是 annual_premium
173 + // 反向转换:yuan -> fen,返回整数(分)
174 + expect(result.annual_premium).toBe(10000)
175 + expect(result.annual_withdrawal_amount).toBe(5000)
176 + expect(result.name).toBe('Test')
177 + })
178 +
179 + it('should handle missing fields', () => {
180 + const apiData = {
181 + annual_premium: '100.00'
182 + }
183 +
184 + const fieldDefinitions = {
185 + annual_premium: {
186 + api_field: 'annual_premium',
187 + transform: TRANSFORM_TYPES.FEN_TO_YUAN
188 + },
189 + name: {
190 + api_field: 'name'
191 + }
192 + }
193 +
194 + const result = reverseTransformFields(apiData, fieldDefinitions)
195 +
196 + // annual_premium 反向转换:yuan -> fen,返回整数(分)
197 + expect(result.annual_premium).toBe(10000)
198 + // name 在 apiData 中不存在,所以 result.name 是 undefined
199 + expect(result.name).toBeUndefined()
200 + })
201 +})
1 +/**
2 + * 计划书字段值转换工具
3 + *
4 + * @description 提供各种数据格式的转换函数,用于表单数据提交前的格式化
5 + * @module utils/planFieldTransformers
6 + * @author Claude Code
7 + * @created 2026-02-14
8 + */
9 +
10 +import { TRANSFORM_TYPES } from '@/config/plan-fields'
11 +
12 +/**
13 + * 分转元
14 + * @description 将分(整数)转换为元(浮点数,保留2位小数)
15 + * @param {number|string} value - 分值(如 10000)
16 + * @returns {string|null} 元值(如 "100.00")
17 + *
18 + * @example
19 + * fenToYuan(10000) // "100.00"
20 + * fenToYuan(0) // "0.00"
21 + * fenToYuan(null) // null
22 + */
23 +export function fenToYuan(value) {
24 + // 空字符串返回 null
25 + if (value === null || value === '') {
26 + return null
27 + }
28 + // undefined 保持原值(不转换)
29 + if (value === undefined) {
30 + return undefined
31 + }
32 +
33 + const numValue = parseFloat(value)
34 + if (Number.isNaN(numValue)) {
35 + return null
36 + }
37 +
38 + return (numValue / 100).toFixed(2)
39 +}
40 +
41 +/**
42 + * 元转分
43 + * @description 将元(浮点数)转换为分(整数)
44 + * @param {number|string} value - 元值(如 "100.00")
45 + * @returns {number|null} 分值(如 10000)
46 + *
47 + * @example
48 + * yuanToFen("100.00") // 10000
49 + * yuanToFen(0) // 0
50 + * yuanToFen(null) // null
51 + */
52 +export function yuanToFen(value) {
53 + if (value === null || value === undefined || value === '') {
54 + return null
55 + }
56 +
57 + const numValue = parseFloat(value)
58 + if (Number.isNaN(numValue)) {
59 + return null
60 + }
61 +
62 + return Math.round(numValue * 100)
63 +}
64 +
65 +/**
66 + * 年龄格式化
67 + * @description 将数字年龄格式化为 "XX岁" 字符串
68 + * @param {number} value - 年龄数字
69 + * @returns {string|null} 格式化后的年龄
70 + *
71 + * @example
72 + * formatAge(25) // "25岁"
73 + * formatAge(null) // null
74 + */
75 +export function formatAge(value) {
76 + if (value === null || value === undefined) {
77 + return null
78 + }
79 + return `${value}岁`
80 +}
81 +
82 +/**
83 + * 无需转换
84 + * @description 直接返回原值
85 + * @param {*} value - 任意值
86 + * @returns {*} 返回原值
87 + */
88 +export function noneTransform(value) {
89 + return value
90 +}
91 +
92 +/**
93 + * 转换器映射表
94 + * @type {Object<string, Function>}
95 + */
96 +export const FIELD_TRANSFORMERS = {
97 + [TRANSFORM_TYPES.FEN_TO_YUAN]: fenToYuan,
98 + [TRANSFORM_TYPES.YUAN_TO_FEN]: yuanToFen,
99 + [TRANSFORM_TYPES.NONE]: noneTransform
100 +}
101 +
102 +/**
103 + * 执行字段值转换
104 + * @param {*} value - 原始值
105 + * @param {string} transformType - 转换类型
106 + * @returns {*} 转换后的值
107 + *
108 + * @example
109 + * transformFieldValue(10000, 'fen_to_yuan') // "100.00"
110 + * transformFieldValue("100.00", 'none') // "100.00"
111 + */
112 +export function transformFieldValue(value, transformType) {
113 + if (!transformType || transformType === TRANSFORM_TYPES.NONE) {
114 + return value
115 + }
116 +
117 + const transformer = FIELD_TRANSFORMERS[transformType]
118 +
119 + if (!transformer) {
120 + console.warn(`[planFieldTransformers] 未知的转换类型: ${transformType}`)
121 + return value
122 + }
123 +
124 + return transformer(value)
125 +}
126 +
127 +/**
128 + * 批量转换字段值
129 + * @param {Object} formData - 表单数据
130 + * @param {Object} fieldDefinitions - 字段定义映射
131 + * @returns {Object} 转换后的数据
132 + *
133 + * @example
134 + * batchTransformFields(
135 + * { coverage: 10000, name: 'Test' },
136 + * { coverage: { transform: 'fen_to_yuan' } }
137 + * ) // { coverage: '100.00', name: 'Test' }
138 + */
139 +export function batchTransformFields(formData, fieldDefinitions) {
140 + const result = { ...formData }
141 +
142 + for (const [key, value] of Object.entries(result)) {
143 + const definition = fieldDefinitions[key]
144 +
145 + if (!definition || !definition.transform) {
146 + continue
147 + }
148 +
149 + result[key] = transformFieldValue(value, definition.transform)
150 + }
151 +
152 + return result
153 +}
154 +
155 +/**
156 + * 反向转换(从 API 响应转换回表单格式)
157 + * @param {Object} data - API 返回的数据
158 + * @param {Object} fieldDefinitions - 字段定义映射
159 + * @returns {Object} 转换后的表单数据
160 + *
161 + * @example
162 + * reverseTransformFields(
163 + * { annual_premium: '100.00', name: 'Test' },
164 + * { annual_premium: { api_field: 'annual_premium', transform: 'fen_to_yuan' } }
165 + * ) // { annual_premium: 10000, name: 'Test' }
166 + */
167 +export function reverseTransformFields(data, fieldDefinitions) {
168 + const result = {}
169 +
170 + for (const [formKey, definition] of Object.entries(fieldDefinitions)) {
171 + // 跳过没有 api_field 的字段
172 + if (!definition.api_field) {
173 + continue
174 + }
175 +
176 + const apiValue = data[definition.api_field]
177 + if (apiValue === undefined || apiValue === null) {
178 + continue
179 + }
180 +
181 + // 没有转换类型,直接使用原值
182 + if (!definition.transform || definition.transform === TRANSFORM_TYPES.NONE) {
183 + result[formKey] = apiValue
184 + continue
185 + }
186 +
187 + // 获取反向转换器
188 + let reverseTransform = definition.transform
189 +
190 + if (reverseTransform === TRANSFORM_TYPES.FEN_TO_YUAN) {
191 + reverseTransform = TRANSFORM_TYPES.YUAN_TO_FEN
192 + } else if (reverseTransform === TRANSFORM_TYPES.YUAN_TO_FEN) {
193 + reverseTransform = TRANSFORM_TYPES.FEN_TO_YUAN
194 + } else {
195 + // 未知转换类型,使用原值
196 + result[formKey] = apiValue
197 + continue
198 + }
199 +
200 + result[formKey] = transformFieldValue(apiValue, reverseTransform)
201 + }
202 +
203 + return result
204 +}