# Shangyu Pricing Field Adjustment Frontend Implementation Plan > **For agentic workers:** Follow this repository's `AGENTS.md`: do not invoke `using-superpowers` or subagents during implementation unless the user explicitly requests them. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Update the personal and corporate workflow create dialogs so the displayed fields, dynamic options, required `couponRate`, and submitted payload match the approved Shangyu pricing spec. **Architecture:** Keep the existing Vue 2 create-dialog components and static Node assertion tests. Update each dialog in place, using computed properties for customer-type-specific collateral options and the `质押 + 存单质押` coupon-rate condition; verify with static tests, production build, and a real Playwright browser check. **Tech Stack:** Vue 2, Element UI, RuoYi request wrapper, Node static tests, npm scripts, nvm-controlled frontend runtime, Playwright real browser verification. --- ## File Structure - Modify: `ruoyi-ui/src/views/loanPricing/workflow/components/PersonalCreateDialog.vue` - Change `businessType` options. - Remove `loanPurpose` and `bizProof` UI, form fields, rules, reset values, and submit payload handling. - Change personal `collateralTypeOptions`. - Add `couponRate` conditional field and submit cleanup. - Modify: `ruoyi-ui/src/views/loanPricing/workflow/components/CorporateCreateDialog.vue` - Change `businessType` options. - Change corporate `collateralTypeOptions`. - Add `couponRate` conditional field and submit cleanup. - Modify: `ruoyi-ui/tests/business-type-history-rate.test.js` - Update business-type assertions from `新客` to `新增`. - Add `couponRate` assertions. - Modify: `ruoyi-ui/tests/personal-create-input-params.test.js` - Assert personal removed fields are absent. - Assert personal collateral options match the new spec. - Modify: `ruoyi-ui/tests/corporate-create-input-params.test.js` - Assert corporate collateral options match the new spec. - Modify: `doc/implementation-report-2026-05-11-shangyu-pricing-field-adjustment.md` - Add frontend implementation and Playwright verification notes after execution. ## Task 1: Update Frontend Static Assertions First **Files:** - Modify: `ruoyi-ui/tests/business-type-history-rate.test.js` - Modify: `ruoyi-ui/tests/personal-create-input-params.test.js` - Modify: `ruoyi-ui/tests/corporate-create-input-params.test.js` - [ ] **Step 1: Update business-type assertions** In `business-type-history-rate.test.js`, replace old assertions for `新客` with: ```js ;[ ['个人新增弹窗', personalCreate], ['企业新增弹窗', corporateCreate] ].forEach(([name, source]) => { assert(source.includes('label="业务种类"'), `${name} 缺少业务种类`) assert(source.includes('value="新增"'), `${name} 缺少新增选项`) assert(source.includes('value="存量新增"'), `${name} 缺少存量新增选项`) assert(source.includes('value="存量转贷"'), `${name} 缺少存量转贷选项`) assert(!source.includes('value="新客"'), `${name} 仍保留旧业务种类 新客`) assert(source.includes("if (value === '存量转贷')"), `${name} 未保持仅存量转贷查询历史合同`) }) ``` - [ ] **Step 2: Add coupon-rate assertions** In the same test file, add: ```js ;[ ['个人新增弹窗', personalCreate], ['企业新增弹窗', corporateCreate] ].forEach(([name, source]) => { assert(source.includes('label="存单票面利率"'), `${name} 缺少存单票面利率字段`) assert(source.includes('prop="couponRate"'), `${name} 缺少 couponRate prop`) assert(source.includes('isCertificatePledge'), `${name} 缺少存单质押条件计算`) assert(source.includes("this.form.guarType === '质押'") && source.includes("this.form.collType === '存单质押'"), `${name} couponRate 条件不正确`) assert(source.includes('delete data.couponRate'), `${name} 未在非适用条件删除 couponRate`) assert(source.includes('存单票面利率不能为空'), `${name} 缺少 couponRate 必填提示`) }) ``` This shared `business-type-history-rate.test.js` is expected to remain failing until both personal and corporate dialogs are updated. Do not use it as a passing checkpoint after only the personal dialog is changed. - [ ] **Step 3: Update personal-field assertions** In `personal-create-input-params.test.js`, replace old required assertions for `loanPurpose` and `bizProof` with absence checks: ```js assert( !personalCreateDialog.includes('label="贷款用途"') && !personalCreateDialog.includes('prop="loanPurpose"') && !personalCreateDialog.includes('loanPurpose:'), '个人新增弹窗不应继续保留贷款用途字段' ) assert( !personalCreateDialog.includes('label="是否有经营佐证"') && !personalCreateDialog.includes('prop="bizProof"') && !personalCreateDialog.includes('bizProof:'), '个人新增弹窗不应继续保留是否有经营佐证字段' ) ``` Update personal collateral assertion: ```js assert( personalCreateDialog.includes("return ['一线', '一类', '二类', '三类']") && personalCreateDialog.includes("return ['存单质押', '其他质押']"), '个人新增弹窗抵质押类型选项未按新口径动态切换' ) ``` - [ ] **Step 4: Update corporate collateral assertions** In `corporate-create-input-params.test.js`, replace old collateral assertion with: ```js assert( corporateCreateDialog.includes("return ['一类', '二类', '三类', '四类', '排污权抵押', '设备等其他不动产抵押']") && corporateCreateDialog.includes("return ['存单质押', '股权质押', '其他质押']"), '企业新增弹窗抵质押类型选项未按新口径动态切换' ) ``` - [ ] **Step 5: Run frontend static tests and confirm failure** Run: ```bash zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:business-type-history-rate && npm --prefix ruoyi-ui run test:personal-create-input-params && npm --prefix ruoyi-ui run test:corporate-create-input-params' ``` Expected: FAIL because the UI is not updated yet. ## Task 2: Update Personal Create Dialog **Files:** - Modify: `ruoyi-ui/src/views/loanPricing/workflow/components/PersonalCreateDialog.vue` - [ ] **Step 1: Change business type options** Replace the first option: ```vue ``` - [ ] **Step 2: Remove personal fields from template** Delete the `贷款用途` form item and its surrounding column. Delete the `是否有经营佐证` form item. Keep `借款期限(年)` and `循环功能`. If a row becomes single-column, leave it as a normal `el-row` with one `el-col :span="12"`; do not restructure the whole dialog. - [ ] **Step 3: Remove personal fields from data, rules, and submit payload** Remove these from `form` initial state and `reset()`: ```js loanPurpose: undefined, bizProof: false, ``` Remove `loanPurpose` from `rules`. Remove this submit conversion: ```js bizProof: this.form.bizProof ? '1' : '0', ``` Keep: ```js loanLoop: this.form.loanLoop ? '1' : '0' ``` - [ ] **Step 4: Update personal collateral options** Change `collateralTypeOptions()` to: ```js collateralTypeOptions() { if (this.form.guarType === '抵押') { return ['一线', '一类', '二类', '三类'] } if (this.form.guarType === '质押') { return ['存单质押', '其他质押'] } return [] } ``` - [ ] **Step 5: Add coupon-rate field** Add under the collateral row: ```vue ``` If the row already has two columns, put this field in the same `抵质押信息` area and keep the existing `900px` dialog. - [ ] **Step 6: Add computed condition and validator** Add: ```js isCertificatePledge() { return this.form.guarType === '质押' && this.form.collType === '存单质押' } ``` Add a validator in `data()`: ```js const validateCouponRate = (rule, value, callback) => { if (this.isCertificatePledge && !value) { callback(new Error('存单票面利率不能为空')) return } callback() } ``` Add rule: ```js couponRate: [ {validator: validateCouponRate, trigger: "blur"} ] ``` - [ ] **Step 7: Add coupon-rate state cleanup** Add `couponRate: undefined` to `form` initial state and `reset()`. Add watcher: ```js 'form.collType'() { this.resetCouponRateIfNotCertificatePledge() } ``` Add method: ```js resetCouponRateIfNotCertificatePledge() { if (!this.isCertificatePledge) { this.form.couponRate = undefined this.$nextTick(() => { if (this.$refs.form) { this.$refs.form.clearValidate(['couponRate']) } }) } } ``` Call it at the end of `resetCollateralFields()`. - [ ] **Step 8: Add submit cleanup and front-end guard** In `submitForm`, before `this.submitting = true`, add: ```js if (this.isCertificatePledge && !this.form.couponRate) { this.$modal.msgWarning("存单票面利率不能为空") return } ``` After collateral handling: ```js if (!this.isCertificatePledge) { delete data.couponRate } ``` - [ ] **Step 9: Run personal static tests** Run: ```bash zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:personal-create-input-params' ``` Expected: PASS. The shared `test:business-type-history-rate` is intentionally not run here because it also asserts corporate changes that are implemented in Task 3. - [ ] **Step 10: Commit personal frontend changes** ```bash git add ruoyi-ui/src/views/loanPricing/workflow/components/PersonalCreateDialog.vue \ ruoyi-ui/tests/personal-create-input-params.test.js git commit -m "调整上虞对私新增字段口径" ``` ## Task 3: Update Corporate Create Dialog **Files:** - Modify: `ruoyi-ui/src/views/loanPricing/workflow/components/CorporateCreateDialog.vue` - Modify: `ruoyi-ui/tests/corporate-create-input-params.test.js` - Modify: `ruoyi-ui/tests/business-type-history-rate.test.js` - [ ] **Step 1: Change business type options** Use: ```vue ``` - [ ] **Step 2: Update corporate collateral options** Change `collateralTypeOptions()` to: ```js collateralTypeOptions() { if (this.form.guarType === '抵押') { return ['一类', '二类', '三类', '四类', '排污权抵押', '设备等其他不动产抵押'] } if (this.form.guarType === '质押') { return ['存单质押', '股权质押', '其他质押'] } return [] } ``` - [ ] **Step 3: Add coupon-rate field and state** Mirror the personal dialog implementation: ```vue ``` Add: ```js couponRate: undefined ``` to initial `form` and `reset()`. - [ ] **Step 4: Add computed condition, validator, watcher, and submit cleanup** Use the same names as personal dialog: ```js isCertificatePledge() { return this.form.guarType === '质押' && this.form.collType === '存单质押' } ``` Use the same `validateCouponRate`, `couponRate` rule, `form.collType` watcher, `resetCouponRateIfNotCertificatePledge`, front-end guard, and: ```js if (!this.isCertificatePledge) { delete data.couponRate } ``` - [ ] **Step 5: Run corporate static tests** Run: ```bash zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:corporate-create-input-params && npm --prefix ruoyi-ui run test:business-type-history-rate' ``` Expected: PASS. - [ ] **Step 6: Commit corporate frontend changes** ```bash git add ruoyi-ui/src/views/loanPricing/workflow/components/CorporateCreateDialog.vue \ ruoyi-ui/tests/corporate-create-input-params.test.js \ ruoyi-ui/tests/business-type-history-rate.test.js git commit -m "调整上虞对公新增字段口径" ``` ## Task 4: Frontend Build and Real Page Verification **Files:** - Modify: `doc/implementation-report-2026-05-11-shangyu-pricing-field-adjustment.md` - [ ] **Step 1: Run all related static tests** Run: ```bash zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:business-type-history-rate && npm --prefix ruoyi-ui run test:personal-create-input-params && npm --prefix ruoyi-ui run test:corporate-create-input-params' ``` Expected: PASS. - [ ] **Step 2: Run production build** Run: ```bash zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run build:prod' ``` Expected: PASS and `ruoyi-ui/dist` generated. - [ ] **Step 3: Start the local app stack** Use the repository's existing startup scripts if available. If a frontend dev server is needed, run it with Node controlled by `nvm`: ```bash zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run dev' ``` Record the PID and URL. If the backend also needs restart, use the existing repository backend restart script rather than inventing a new start path. - [ ] **Step 4: Use Playwright on the real page** Open the actual local workflow page, not a prototype. Verify: - Personal create dialog: - `业务种类` shows `新增/存量新增/存量转贷`. - `新客` is absent. - `贷款用途` is absent. - `是否有经营佐证` is absent. - `抵押` shows `一线/一类/二类/三类`. - `质押 + 存单质押` shows `存单票面利率`. - Leaving `存单票面利率` empty blocks submit. - Corporate create dialog: - `业务种类` shows `新增/存量新增/存量转贷`. - `抵押` shows `一类/二类/三类/四类/排污权抵押/设备等其他不动产抵押`. - `质押` shows `存单质押/股权质押/其他质押`. - `质押 + 存单质押` shows `存单票面利率`. - Leaving `存单票面利率` empty blocks submit. - History-rate behavior: - `存量转贷` triggers historical-contract query. - `新增` and `存量新增` do not trigger historical-contract query. - [ ] **Step 5: Stop test processes** Stop any frontend/backend processes started in this task. Verify with: ```bash ps -ef | rg 'vue-cli-service|ruoyi-admin|RuoYiApplication' ``` Expected: no leftover processes from this test run. - [ ] **Step 6: Update implementation record** Append: ```markdown ## 前端实现 - 调整个人/企业新增弹窗业务种类选项为 `新增/存量新增/存量转贷`。 - 个人新增弹窗剔除 `loanPurpose`、`bizProof`。 - 按客户类型和担保方式调整抵质押类型选项。 - 新增 `质押 + 存单质押` 下的 `couponRate` 存单票面利率字段、必填校验和提交清理。 ## 前端验证 - `npm --prefix ruoyi-ui run test:business-type-history-rate` - `npm --prefix ruoyi-ui run test:personal-create-input-params` - `npm --prefix ruoyi-ui run test:corporate-create-input-params` - `npm --prefix ruoyi-ui run build:prod` - Playwright 真实页面验证:通过 ``` - [ ] **Step 7: Commit frontend verification record** ```bash git add doc/implementation-report-2026-05-11-shangyu-pricing-field-adjustment.md git commit -m "记录上虞字段调整前端验证" ```