663 lines
21 KiB
Markdown
663 lines
21 KiB
Markdown
# Customer Map Selection Frontend Implementation Plan
|
|
|
|
> **For agentic workers:** Steps use checkbox (`- [ ]`) syntax for tracking. Follow this repository's AGENTS.md rule: do not enable subagents or superpowers execution modes unless the user explicitly requests them for the implementation session.
|
|
|
|
**Goal:** Add the frontend customer-id query and customer-internal-code selection step before opening personal or corporate workflow creation dialogs.
|
|
|
|
**Architecture:** Keep the existing list page and personal/corporate creation dialogs. Insert a shared customer-map selector dialog between customer-type selection and workflow creation, then pass the selected underscore-field record into the existing create dialogs. Existing workflow create APIs stay unchanged and still receive `custIsn` and `custName` in camelCase.
|
|
|
|
**Tech Stack:** Vue 2, Element UI, existing RuoYi request wrapper, Node static assertion tests, nvm-managed frontend runtime, Playwright/browser verification after implementation.
|
|
|
|
---
|
|
|
|
## File Structure
|
|
|
|
- Modify: `ruoyi-ui/src/api/loanPricing/workflow.js`
|
|
- Adds personal/corporate customer-map query functions.
|
|
- Create: `ruoyi-ui/src/views/loanPricing/workflow/components/CustomerMapSelector.vue`
|
|
- Owns customer-id input, query action, result table, loading state, and row selection.
|
|
- Modify: `ruoyi-ui/src/views/loanPricing/workflow/index.vue`
|
|
- Opens customer-map selector after customer type selection and then opens the correct create dialog after row selection.
|
|
- Modify: `ruoyi-ui/src/views/loanPricing/workflow/components/PersonalCreateDialog.vue`
|
|
- Accepts selected customer-map record, fills `custIsn` and `custName`, and makes both fields read-only.
|
|
- Modify: `ruoyi-ui/src/views/loanPricing/workflow/components/CorporateCreateDialog.vue`
|
|
- Same selected-record behavior for corporate creation.
|
|
- Modify: `ruoyi-ui/package.json`
|
|
- Adds a focused test script for the new customer-map selection checks.
|
|
- Create: `ruoyi-ui/tests/customer-map-selection.test.js`
|
|
- Static test coverage for API paths, selector fields, parent wiring, selected underscore fields, and read-only create dialog inputs.
|
|
|
|
## Task 1: Add Frontend API Methods
|
|
|
|
**Files:**
|
|
- Modify: `ruoyi-ui/src/api/loanPricing/workflow.js`
|
|
- Create: `ruoyi-ui/tests/customer-map-selection.test.js`
|
|
- Modify: `ruoyi-ui/package.json`
|
|
|
|
- [ ] **Step 1: Write failing API assertions**
|
|
|
|
Create the first version of `ruoyi-ui/tests/customer-map-selection.test.js`:
|
|
|
|
```js
|
|
const fs = require('fs')
|
|
const path = require('path')
|
|
const assert = require('assert')
|
|
|
|
function read(relativePath) {
|
|
return fs.readFileSync(path.join(__dirname, '..', relativePath), 'utf8')
|
|
}
|
|
|
|
const workflowApi = read('src/api/loanPricing/workflow.js')
|
|
|
|
assert(
|
|
workflowApi.includes('export function queryPersonalCustomerMap') &&
|
|
workflowApi.includes("url: '/loanPricing/workflow/customer-map/personal'") &&
|
|
workflowApi.includes('params: { custId: custId }'),
|
|
'缺少个人客户号映射查询 API'
|
|
)
|
|
|
|
assert(
|
|
workflowApi.includes('export function queryCorporateCustomerMap') &&
|
|
workflowApi.includes("url: '/loanPricing/workflow/customer-map/corporate'") &&
|
|
workflowApi.includes('params: { custId: custId }'),
|
|
'缺少企业客户号映射查询 API'
|
|
)
|
|
|
|
console.log('customer map selection assertions passed')
|
|
```
|
|
|
|
Add a script in `ruoyi-ui/package.json`:
|
|
|
|
```json
|
|
"test:customer-map-selection": "node tests/customer-map-selection.test.js"
|
|
```
|
|
|
|
- [ ] **Step 2: Run the test to verify it fails**
|
|
|
|
Run with the project Node version:
|
|
|
|
```bash
|
|
zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:customer-map-selection'
|
|
```
|
|
|
|
Expected: FAIL because the API methods do not exist.
|
|
|
|
- [ ] **Step 3: Implement the API methods**
|
|
|
|
Append to `workflow.js`:
|
|
|
|
```js
|
|
// 查询个人客户号映射
|
|
export function queryPersonalCustomerMap(custId) {
|
|
return request({
|
|
url: '/loanPricing/workflow/customer-map/personal',
|
|
method: 'get',
|
|
params: { custId: custId }
|
|
})
|
|
}
|
|
|
|
// 查询企业客户号映射
|
|
export function queryCorporateCustomerMap(custId) {
|
|
return request({
|
|
url: '/loanPricing/workflow/customer-map/corporate',
|
|
method: 'get',
|
|
params: { custId: custId }
|
|
})
|
|
}
|
|
```
|
|
|
|
- [ ] **Step 4: Run the API test**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:customer-map-selection'
|
|
```
|
|
|
|
Expected: PASS for API assertions.
|
|
|
|
## Task 2: Create Customer Map Selector Dialog
|
|
|
|
**Files:**
|
|
- Create: `ruoyi-ui/src/views/loanPricing/workflow/components/CustomerMapSelector.vue`
|
|
- Modify: `ruoyi-ui/tests/customer-map-selection.test.js`
|
|
|
|
- [ ] **Step 1: Extend the static test for selector requirements**
|
|
|
|
Add these assertions to `customer-map-selection.test.js`:
|
|
|
|
```js
|
|
const selector = read('src/views/loanPricing/workflow/components/CustomerMapSelector.vue')
|
|
|
|
assert(
|
|
selector.includes('title="客户号查询"') &&
|
|
selector.includes('v-model="queryForm.custId"') &&
|
|
selector.includes('handleQuery'),
|
|
'客户号查询弹窗缺少客户号输入或查询动作'
|
|
)
|
|
|
|
assert(
|
|
selector.includes("queryPersonalCustomerMap") &&
|
|
selector.includes("queryCorporateCustomerMap") &&
|
|
selector.includes("this.customerType === 'personal'"),
|
|
'客户号查询弹窗未按客户类型调用个人/企业接口'
|
|
)
|
|
|
|
;['cust_id', 'cust_isn', 'cust_name', 'faith_day', 'balance_avg', 'loan_count_his', 'last_loan_date'].forEach((field) => {
|
|
assert(selector.includes(`prop="${field}"`) || selector.includes(`row.${field}`), `查询结果表格缺少字段 ${field}`)
|
|
})
|
|
|
|
assert(
|
|
selector.includes("this.$emit('select', row)") &&
|
|
selector.includes('未查询到客户信息') &&
|
|
selector.includes('请输入客户号'),
|
|
'客户号查询弹窗缺少选择事件或关键提示'
|
|
)
|
|
```
|
|
|
|
- [ ] **Step 2: Run the test to verify it fails**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:customer-map-selection'
|
|
```
|
|
|
|
Expected: FAIL because `CustomerMapSelector.vue` does not exist.
|
|
|
|
- [ ] **Step 3: Implement `CustomerMapSelector.vue`**
|
|
|
|
Create the component:
|
|
|
|
```vue
|
|
<template>
|
|
<el-dialog title="客户号查询" :visible.sync="dialogVisible" width="900px" append-to-body
|
|
:close-on-click-modal="false" @close="handleClose">
|
|
<el-form :model="queryForm" inline size="small">
|
|
<el-form-item label="客户号">
|
|
<el-input v-model="queryForm.custId" placeholder="请输入客户号" clearable @keyup.enter.native="handleQuery"/>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" icon="el-icon-search" :loading="loading" @click="handleQuery">查询</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
|
|
<el-table v-loading="loading" :data="customerList">
|
|
<el-table-column label="客户号" prop="cust_id" align="center" :show-overflow-tooltip="true"/>
|
|
<el-table-column label="客户内码" prop="cust_isn" align="center" :show-overflow-tooltip="true"/>
|
|
<el-table-column label="客户名称" prop="cust_name" align="center" :show-overflow-tooltip="true"/>
|
|
<el-table-column label="用信天数" prop="faith_day" align="center"/>
|
|
<el-table-column label="存款年日均" prop="balance_avg" align="center"/>
|
|
<el-table-column label="历史贷款次数" prop="loan_count_his" align="center"/>
|
|
<el-table-column label="上次贷款日期" prop="last_loan_date" align="center" width="130"/>
|
|
<el-table-column label="操作" align="center" width="90">
|
|
<template slot-scope="scope">
|
|
<el-button type="text" size="mini" @click="handleSelect(scope.row)">选择</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</el-dialog>
|
|
</template>
|
|
|
|
<script>
|
|
import {queryPersonalCustomerMap, queryCorporateCustomerMap} from "@/api/loanPricing/workflow"
|
|
|
|
export default {
|
|
name: "CustomerMapSelector",
|
|
props: {
|
|
visible: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
customerType: {
|
|
type: String,
|
|
default: undefined
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
loading: false,
|
|
queryForm: {
|
|
custId: undefined
|
|
},
|
|
customerList: []
|
|
}
|
|
},
|
|
computed: {
|
|
dialogVisible: {
|
|
get() {
|
|
return this.visible
|
|
},
|
|
set(val) {
|
|
this.$emit('update:visible', val)
|
|
}
|
|
}
|
|
},
|
|
methods: {
|
|
handleQuery() {
|
|
if (!this.queryForm.custId) {
|
|
this.$modal.msgWarning("请输入客户号")
|
|
return
|
|
}
|
|
this.loading = true
|
|
const request = this.customerType === 'personal'
|
|
? queryPersonalCustomerMap
|
|
: queryCorporateCustomerMap
|
|
request(this.queryForm.custId).then(response => {
|
|
this.customerList = response.data || []
|
|
if (this.customerList.length === 0) {
|
|
this.$modal.msgWarning("未查询到客户信息")
|
|
}
|
|
}).finally(() => {
|
|
this.loading = false
|
|
})
|
|
},
|
|
handleSelect(row) {
|
|
this.$emit('select', row)
|
|
this.dialogVisible = false
|
|
},
|
|
handleClose() {
|
|
this.queryForm.custId = undefined
|
|
this.customerList = []
|
|
this.loading = false
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
```
|
|
|
|
- [ ] **Step 4: Run the selector test**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:customer-map-selection'
|
|
```
|
|
|
|
Expected: PASS through selector assertions.
|
|
|
|
## Task 3: Wire Selector Into Workflow List Page
|
|
|
|
**Files:**
|
|
- Modify: `ruoyi-ui/src/views/loanPricing/workflow/index.vue`
|
|
- Modify: `ruoyi-ui/tests/customer-map-selection.test.js`
|
|
|
|
- [ ] **Step 1: Extend the test for parent wiring**
|
|
|
|
Add assertions:
|
|
|
|
```js
|
|
const workflowIndex = read('src/views/loanPricing/workflow/index.vue')
|
|
|
|
assert(
|
|
workflowIndex.includes('CustomerMapSelector') &&
|
|
workflowIndex.includes('<customer-map-selector') &&
|
|
workflowIndex.includes(':customer-type="selectedCustomerType"') &&
|
|
workflowIndex.includes('@select="handleCustomerMapSelect"'),
|
|
'流程列表页未接入客户号查询选择弹窗'
|
|
)
|
|
|
|
assert(
|
|
workflowIndex.includes('selectedCustomerType') &&
|
|
workflowIndex.includes('selectedCustomerMap') &&
|
|
workflowIndex.includes('showCustomerMapSelector'),
|
|
'流程列表页缺少客户类型、客户映射选择状态'
|
|
)
|
|
|
|
assert(
|
|
workflowIndex.includes("this.selectedCustomerType = type") &&
|
|
workflowIndex.includes('this.showCustomerMapSelector = true') &&
|
|
!workflowIndex.includes("if (type === 'personal') {\\n this.showPersonalDialog = true"),
|
|
'选择客户类型后应先打开客户号查询弹窗,而不是直接打开新增弹窗'
|
|
)
|
|
|
|
assert(
|
|
workflowIndex.includes('handleCustomerMapSelect') &&
|
|
workflowIndex.includes('this.selectedCustomerMap = row') &&
|
|
workflowIndex.includes('this.showPersonalDialog = true') &&
|
|
workflowIndex.includes('this.showCorporateDialog = true'),
|
|
'选择客户内码后未打开对应新增弹窗'
|
|
)
|
|
```
|
|
|
|
- [ ] **Step 2: Run the test to verify it fails**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:customer-map-selection'
|
|
```
|
|
|
|
Expected: FAIL because the list page does not yet use the selector.
|
|
|
|
- [ ] **Step 3: Update `index.vue` template and script**
|
|
|
|
Add component usage after the customer type selector:
|
|
|
|
```vue
|
|
<customer-map-selector
|
|
:visible.sync="showCustomerMapSelector"
|
|
:customer-type="selectedCustomerType"
|
|
@select="handleCustomerMapSelect"
|
|
/>
|
|
```
|
|
|
|
Pass the selected record into both create dialogs:
|
|
|
|
```vue
|
|
<personal-create-dialog
|
|
:visible.sync="showPersonalDialog"
|
|
:customer-map="selectedCustomerMap"
|
|
@success="handleCreateSuccess"
|
|
/>
|
|
|
|
<corporate-create-dialog
|
|
:visible.sync="showCorporateDialog"
|
|
:customer-map="selectedCustomerMap"
|
|
@success="handleCreateSuccess"
|
|
/>
|
|
```
|
|
|
|
Import and register the selector:
|
|
|
|
```js
|
|
import CustomerMapSelector from "./components/CustomerMapSelector"
|
|
```
|
|
|
|
Add state:
|
|
|
|
```js
|
|
showCustomerMapSelector: false,
|
|
selectedCustomerType: undefined,
|
|
selectedCustomerMap: null,
|
|
```
|
|
|
|
Change `handleSelectType`:
|
|
|
|
```js
|
|
handleSelectType(type) {
|
|
this.selectedCustomerType = type
|
|
this.selectedCustomerMap = null
|
|
this.showCustomerMapSelector = true
|
|
}
|
|
```
|
|
|
|
Add selected-row handler:
|
|
|
|
```js
|
|
handleCustomerMapSelect(row) {
|
|
this.selectedCustomerMap = row
|
|
if (this.selectedCustomerType === 'personal') {
|
|
this.showPersonalDialog = true
|
|
} else if (this.selectedCustomerType === 'corporate') {
|
|
this.showCorporateDialog = true
|
|
}
|
|
}
|
|
```
|
|
|
|
Clear selected state when the create flow completes:
|
|
|
|
```js
|
|
handleCreateSuccess() {
|
|
this.selectedCustomerMap = null
|
|
this.selectedCustomerType = undefined
|
|
this.getList()
|
|
}
|
|
```
|
|
|
|
Add watchers for dialog close so cancellation also clears the selected record:
|
|
|
|
```js
|
|
watch: {
|
|
showPersonalDialog(val) {
|
|
if (!val && !this.showCorporateDialog) {
|
|
this.selectedCustomerMap = null
|
|
this.selectedCustomerType = undefined
|
|
}
|
|
},
|
|
showCorporateDialog(val) {
|
|
if (!val && !this.showPersonalDialog) {
|
|
this.selectedCustomerMap = null
|
|
this.selectedCustomerType = undefined
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
- [ ] **Step 4: Run the parent wiring test**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:customer-map-selection'
|
|
```
|
|
|
|
Expected: PASS through parent wiring assertions.
|
|
|
|
## Task 4: Make Create Dialog Customer Fields Read-Only and Auto-Filled
|
|
|
|
**Files:**
|
|
- Modify: `ruoyi-ui/src/views/loanPricing/workflow/components/PersonalCreateDialog.vue`
|
|
- Modify: `ruoyi-ui/src/views/loanPricing/workflow/components/CorporateCreateDialog.vue`
|
|
- Modify: `ruoyi-ui/tests/customer-map-selection.test.js`
|
|
|
|
- [ ] **Step 1: Extend test for create dialog behavior**
|
|
|
|
Add assertions:
|
|
|
|
```js
|
|
const personalCreateDialog = read('src/views/loanPricing/workflow/components/PersonalCreateDialog.vue')
|
|
const corporateCreateDialog = read('src/views/loanPricing/workflow/components/CorporateCreateDialog.vue')
|
|
|
|
;[
|
|
['个人新增弹窗', personalCreateDialog],
|
|
['企业新增弹窗', corporateCreateDialog]
|
|
].forEach(([name, source]) => {
|
|
assert(source.includes('customerMap'), `${name} 缺少 customerMap 入参`)
|
|
assert(source.includes(':readonly="true"') || source.includes('readonly'), `${name} 客户内码和客户名称应只读`)
|
|
assert(source.includes('this.customerMap.cust_isn'), `${name} 未从 cust_isn 自动带入客户内码`)
|
|
assert(source.includes('this.customerMap.cust_name'), `${name} 未从 cust_name 自动带入客户名称`)
|
|
assert(source.includes('clearValidate'), `${name} 应清空校验而不是用 resetFields 覆盖已选客户`)
|
|
assert(!source.includes('this.resetForm("form")'), `${name} 不应在 reset() 中调用 resetForm("form") 覆盖只读客户字段`)
|
|
})
|
|
```
|
|
|
|
- [ ] **Step 2: Run the test to verify it fails**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:customer-map-selection'
|
|
```
|
|
|
|
Expected: FAIL because dialogs do not yet consume `customerMap`.
|
|
|
|
- [ ] **Step 3: Update personal create dialog**
|
|
|
|
Add prop:
|
|
|
|
```js
|
|
customerMap: {
|
|
type: Object,
|
|
default: null
|
|
}
|
|
```
|
|
|
|
Make customer fields read-only:
|
|
|
|
```vue
|
|
<el-input v-model="form.custIsn" placeholder="请选择客户内码" :readonly="true"/>
|
|
<el-input v-model="form.custName" placeholder="请选择客户名称" :readonly="true"/>
|
|
```
|
|
|
|
In `reset()`, initialize from selected row and do not call `this.resetForm("form")`. The existing RuoYi helper delegates to Element UI `resetFields()`, which can restore stale initial values and overwrite the selected read-only customer fields. After assigning the new form object, only clear validation:
|
|
|
|
```js
|
|
reset() {
|
|
this.form = {
|
|
orgCode: '892000',
|
|
runType: '1',
|
|
custIsn: this.customerMap ? this.customerMap.cust_isn : undefined,
|
|
custName: this.customerMap ? this.customerMap.cust_name : undefined,
|
|
idType: undefined,
|
|
idNum: undefined,
|
|
guarType: undefined,
|
|
applyAmt: undefined,
|
|
loanPurpose: undefined,
|
|
loanTerm: undefined,
|
|
bizProof: false,
|
|
loanLoop: false,
|
|
collType: undefined,
|
|
collThirdParty: false
|
|
}
|
|
this.submitting = false
|
|
this.$nextTick(() => {
|
|
if (this.$refs.form) {
|
|
this.$refs.form.clearValidate()
|
|
}
|
|
})
|
|
}
|
|
```
|
|
|
|
Keep existing required validation for `custIsn` and `custName`.
|
|
|
|
- [ ] **Step 4: Update corporate create dialog**
|
|
|
|
Apply the same prop, read-only inputs, and `reset()` initialization to `CorporateCreateDialog.vue`. Do not call `this.resetForm("form")` in the corporate dialog reset path; assign the new form object with `custIsn` and `custName` from `customerMap`, then use `this.$refs.form.clearValidate()` inside `$nextTick()`.
|
|
|
|
- [ ] **Step 5: Run the create dialog test**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:customer-map-selection'
|
|
```
|
|
|
|
Expected: PASS through create dialog assertions.
|
|
|
|
## Task 5: Frontend Verification
|
|
|
|
**Files:**
|
|
- Verify only, no new source files.
|
|
|
|
- [ ] **Step 1: Run focused customer-map test**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:customer-map-selection'
|
|
```
|
|
|
|
Expected: PASS.
|
|
|
|
- [ ] **Step 2: Run affected existing frontend tests**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:personal-create-input-params && npm --prefix ruoyi-ui run test:corporate-create-input-params && node ruoyi-ui/tests/workflow-index-refresh.test.js'
|
|
```
|
|
|
|
Expected: PASS.
|
|
|
|
- [ ] **Step 3: Build frontend**
|
|
|
|
Run:
|
|
|
|
```bash
|
|
zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run build:prod'
|
|
```
|
|
|
|
Expected: build succeeds.
|
|
|
|
- [ ] **Step 4: Browser verification after backend and frontend are running**
|
|
|
|
Use the real application page, not a prototype page:
|
|
|
|
1. Open the workflow list page.
|
|
2. Click “新增”.
|
|
3. Select “个人客户”.
|
|
4. Confirm the customer-id query dialog opens.
|
|
5. Query any customer number.
|
|
6. Select one result row.
|
|
7. Confirm the personal create dialog opens and `客户内码` / `客户名称` are auto-filled and read-only.
|
|
8. Fill the remaining required fields and submit.
|
|
9. Repeat the same flow for “企业客户”.
|
|
10. Close and reopen the create flow at least once with a second selected row, and confirm the new row's `cust_isn` / `cust_name` replace the previous values in the create dialog.
|
|
11. Confirm both created records appear in the list or detail page.
|
|
|
|
Expected: both personal and corporate flows pass through customer-map selection before creation.
|
|
|
|
- [ ] **Step 5: Cleanup test processes**
|
|
|
|
Stop any backend or frontend processes started for verification before ending the task.
|
|
|
|
- [ ] **Step 6: Commit frontend work**
|
|
|
|
Use a Chinese commit message and avoid unrelated dirty files:
|
|
|
|
```bash
|
|
git status --short
|
|
git add ruoyi-ui/src/api/loanPricing/workflow.js \
|
|
ruoyi-ui/src/views/loanPricing/workflow/components/CustomerMapSelector.vue \
|
|
ruoyi-ui/src/views/loanPricing/workflow/index.vue \
|
|
ruoyi-ui/src/views/loanPricing/workflow/components/PersonalCreateDialog.vue \
|
|
ruoyi-ui/src/views/loanPricing/workflow/components/CorporateCreateDialog.vue \
|
|
ruoyi-ui/package.json \
|
|
ruoyi-ui/tests/customer-map-selection.test.js
|
|
git commit -m "新增客户号查询选择前端流程"
|
|
```
|
|
|
|
Do not commit screenshots, browser traces, temporary spreadsheets, or generated test data.
|
|
|
|
## Task 6: Final End-to-End Verification and Implementation Record
|
|
|
|
**Files:**
|
|
- Create: `doc/implementation-report-2026-04-29-customer-map-selection.md`
|
|
|
|
- [ ] **Step 1: Run backend and frontend verification together**
|
|
|
|
After backend and frontend implementation are both complete:
|
|
|
|
```bash
|
|
mvn -pl ruoyi-loan-pricing -am -Dtest=CustomerMapRecordVOTest,LoanPricingCustomerMapServiceTest,LoanRatePricingMockControllerCustomerMapTest,LoanPricingWorkflowControllerCustomerMapTest,LoanPricingModelServiceTest,LoanPricingWorkflowServiceImplTest -Dsurefire.failIfNoSpecifiedTests=false test
|
|
zsh -lic 'nvm use 14.21.3 >/dev/null && npm --prefix ruoyi-ui run test:customer-map-selection && npm --prefix ruoyi-ui run test:personal-create-input-params && npm --prefix ruoyi-ui run test:corporate-create-input-params && node ruoyi-ui/tests/workflow-index-refresh.test.js'
|
|
```
|
|
|
|
Expected: all tests pass.
|
|
|
|
- [ ] **Step 2: Complete browser verification**
|
|
|
|
Run the browser flow from Task 5 for both personal and corporate customers. Confirm the backend API response wrapper is still the existing RuoYi wrapper while records inside `data` keep underscore fields.
|
|
|
|
- [ ] **Step 3: Write implementation report**
|
|
|
|
Create `doc/implementation-report-2026-04-29-customer-map-selection.md` with:
|
|
|
|
```markdown
|
|
# 2026-04-29 客户号查询选择客户内码实施记录
|
|
|
|
## 修改内容
|
|
|
|
- 后端新增个人/企业客户号映射业务接口。
|
|
- 后端新增个人/企业客户号映射 mock 接口。
|
|
- 配置文件新增 `customer-map` 个人/企业地址并指向本项目 mock。
|
|
- 前端新增客户号查询选择弹窗。
|
|
- 个人/企业新增流程改为先查询客户号、选择客户内码,再打开新增弹窗。
|
|
- 新增弹窗客户内码和客户名称由选中记录自动带入并只读。
|
|
|
|
## 验证结果
|
|
|
|
- 后端测试:填写实际执行命令和通过/失败结果。
|
|
- 前端测试:填写实际执行命令和通过/失败结果。
|
|
- 真实页面验证:填写个人、企业两条浏览器验证流程和结果。
|
|
- 进程清理:填写本次启动的前后端进程是否已关闭。
|
|
```
|
|
|
|
- [ ] **Step 4: Commit implementation report**
|
|
|
|
```bash
|
|
git add doc/implementation-report-2026-04-29-customer-map-selection.md
|
|
git commit -m "补充客户号映射选择实施记录"
|
|
```
|