```
feat(shopro_huifu): 完善汇付进件功能的表单验证和错误处理 - 增加支行搜索功能的城市筛选支持,优化搜索逻辑 - 添加前端表单验证机制,包括身份证、银行卡、区域等必填字段校验 - 改进支行选择验证,确保必须从搜索结果中选择带联行号的支行 - 优化后端保存逻辑,添加强制保存参数控制 - 统一异常处理机制,增加HttpResponseException的正确抛出 - 完善用户界面提示信息,明确操作指引和错误反馈 - 修复表单提交前的数据准备逻辑,确保数据完整性 ```
这个提交包含在:
@@ -147,14 +147,19 @@ class Onboard extends Base
|
||||
$service = new HuifuOnboardAdminService();
|
||||
$onboardId = $row ? intval($row['id']) : 0;
|
||||
$saved = $service->saveDraft($userId, $roleType, $roleRefId, $form, $onboardId);
|
||||
$this->success('进件资料已保存,状态为待后台审核', null, [
|
||||
'id' => $saved ? $saved['id'] : 0,
|
||||
]);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$this->error($e->getMessage());
|
||||
} catch (\think\exception\HttpResponseException $e) {
|
||||
throw $e;
|
||||
} catch (\Throwable $e) {
|
||||
$this->error(HuifuOnboardError::translate($e->getMessage()));
|
||||
}
|
||||
if (!$saved) {
|
||||
$this->error('进件资料保存失败,请检查汇付分账配置是否已启用');
|
||||
}
|
||||
$this->success('进件资料已保存,状态为待后台审核', null, [
|
||||
'id' => intval($saved['id']),
|
||||
]);
|
||||
}
|
||||
|
||||
public function retry($ids = null)
|
||||
|
||||
@@ -389,8 +389,9 @@
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="开户银行支行" required>
|
||||
<el-input v-model="branchKeyword" class="form-input" placeholder="搜索支行名称" @input="onBranchInput"></el-input>
|
||||
<div class="field-tip" v-if="form.branch_name">已选:{{ form.branch_name }}({{ form.branch_code }})</div>
|
||||
<el-input v-model="branchKeyword" class="form-input" placeholder="输入支行名称搜索,并从下方结果中点击选择" @input="onBranchInput"></el-input>
|
||||
<div class="field-tip">须从搜索结果中点击选择支行,仅输入文字无法保存</div>
|
||||
<div class="field-tip" v-if="form.branch_code" style="color:#7536D0;">已选:{{ form.branch_name }}(联行号 {{ form.branch_code }})</div>
|
||||
<div class="branch-panel" v-if="branchResults.length">
|
||||
<div class="branch-item" v-for="(item, idx) in branchResults" :key="idx" @click="selectBranch(item)">
|
||||
<div>{{ item.branch_name }}</div>
|
||||
|
||||
@@ -31,7 +31,7 @@ class HuifuOnboardAdminService
|
||||
}
|
||||
|
||||
$service = new HuifuOnboardService();
|
||||
return $service->saveDraft($userId, $roleType, $roleRefId, $formData, $onboardId);
|
||||
return $service->saveDraft($userId, $roleType, $roleRefId, $formData, $onboardId, true);
|
||||
}
|
||||
|
||||
protected function assertRoleBinding($userId, $roleType, $roleRefId)
|
||||
|
||||
@@ -72,15 +72,20 @@ class HuifuOnboardBankBranch
|
||||
}
|
||||
}
|
||||
|
||||
protected static function searchJson($keyword, $limit)
|
||||
protected static function searchJson($keyword, $cityCode = '', $limit = 20)
|
||||
{
|
||||
$limit = max(0, (int) $limit);
|
||||
if ($limit <= 0) {
|
||||
return [];
|
||||
}
|
||||
$cityCode = HuifuOnboardAreaHelper::toCode($cityCode);
|
||||
$all = self::loadJson();
|
||||
$keywordLower = mb_strtolower($keyword, 'UTF-8');
|
||||
$rows = [];
|
||||
foreach ($all as $item) {
|
||||
if ($cityCode !== '' && HuifuOnboardAreaHelper::toCode($item['area_id'] ?? '') !== $cityCode) {
|
||||
continue;
|
||||
}
|
||||
$hay = mb_strtolower(
|
||||
($item['branch_name'] ?? '') . ' ' . ($item['bank_name'] ?? '') . ' ' . ($item['branch_code'] ?? ''),
|
||||
'UTF-8'
|
||||
|
||||
@@ -31,9 +31,9 @@ class HuifuOnboardService
|
||||
/**
|
||||
* 用户申请时仅保存进件资料,待后台业务审核通过后再提交汇付
|
||||
*/
|
||||
public function saveDraft($userId, $roleType, $roleRefId, array $formData, $onboardId = 0)
|
||||
public function saveDraft($userId, $roleType, $roleRefId, array $formData, $onboardId = 0, $force = false)
|
||||
{
|
||||
if (!HuifuOnboardGate::isOnboardRequired()) {
|
||||
if (!$force && !HuifuOnboardGate::isOnboardRequired()) {
|
||||
return null;
|
||||
}
|
||||
if (!in_array($roleType, ['promoter', 'regional_agent'], true)) {
|
||||
|
||||
@@ -93,6 +93,9 @@ class HuifuOnboardValidator
|
||||
if (empty($data['branch_code']) && empty($data['branch_name'])) {
|
||||
throw new \InvalidArgumentException('请选择开户银行支行');
|
||||
}
|
||||
if (empty($data['branch_code']) && !empty($data['branch_name'])) {
|
||||
throw new \InvalidArgumentException('请从搜索结果中点击选择开户银行支行(需联行号)');
|
||||
}
|
||||
if (empty($data['prov_id']) || empty($data['area_id'])) {
|
||||
throw new \InvalidArgumentException('请选择所在区域');
|
||||
}
|
||||
|
||||
@@ -233,17 +233,24 @@ define(['jquery', 'bootstrap', 'backend'], function ($, undefined, Backend) {
|
||||
},
|
||||
onBranchInput: function () {
|
||||
var vm = this;
|
||||
var keyword = (vm.branchKeyword || '').trim();
|
||||
if (keyword !== vm.form.branch_name) {
|
||||
vm.form.branch_code = '';
|
||||
vm.form.branch_name = keyword;
|
||||
}
|
||||
clearTimeout(branchTimer);
|
||||
branchTimer = setTimeout(function () {
|
||||
if (!vm.branchKeyword) {
|
||||
if (!keyword) {
|
||||
vm.branchResults = [];
|
||||
vm.form.branch_code = '';
|
||||
vm.form.branch_name = '';
|
||||
return;
|
||||
}
|
||||
Fast.api.ajax({
|
||||
url: 'shopro_huifu/onboard/searchBranch',
|
||||
type: 'GET',
|
||||
data: {
|
||||
keyword: vm.branchKeyword,
|
||||
keyword: keyword,
|
||||
area_id: vm.form.area_id || vm.form.shopro_city_id
|
||||
}
|
||||
}, function (ret, res) {
|
||||
@@ -252,6 +259,47 @@ define(['jquery', 'bootstrap', 'backend'], function ($, undefined, Backend) {
|
||||
});
|
||||
}, 300);
|
||||
},
|
||||
prepareFormBeforeSubmit: function () {
|
||||
var keyword = (this.branchKeyword || '').trim();
|
||||
if (keyword) {
|
||||
this.form.branch_name = keyword;
|
||||
}
|
||||
this.form.mp = this.bankMobile;
|
||||
},
|
||||
validateFormBeforeSubmit: function () {
|
||||
var form = this.form;
|
||||
if (form.account_type === 'indv') {
|
||||
if (!form.name || !form.cert_no || !form.mobile_no || !form.reg_detail) {
|
||||
Toastr.error('请完整填写身份实名信息');
|
||||
return false;
|
||||
}
|
||||
if (!form.id_card_front_url || !form.id_card_back_url) {
|
||||
Toastr.error('请上传身份证人像面和国徽面');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!form.card_no) {
|
||||
Toastr.error('请填写银行卡号');
|
||||
return false;
|
||||
}
|
||||
if (!this.bankMobile) {
|
||||
Toastr.error('请填写银行预留手机号');
|
||||
return false;
|
||||
}
|
||||
if (!form.branch_code) {
|
||||
if ((this.branchKeyword || '').trim() || form.branch_name) {
|
||||
Toastr.error('请从支行搜索结果中点击选择开户银行(需联行号)');
|
||||
} else {
|
||||
Toastr.error('请搜索并选择开户银行支行');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!form.shopro_province_id && !form.prov_id) {
|
||||
Toastr.error('请选择所在区域');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
selectBranch: function (item) {
|
||||
this.form.branch_code = item.branch_code;
|
||||
this.form.branch_name = item.branch_name;
|
||||
@@ -282,6 +330,10 @@ define(['jquery', 'bootstrap', 'backend'], function ($, undefined, Backend) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
vm.prepareFormBeforeSubmit();
|
||||
if (!vm.validateFormBeforeSubmit()) {
|
||||
return;
|
||||
}
|
||||
vm.saving = true;
|
||||
var url = vm.isEdit
|
||||
? ('shopro_huifu/onboard/edit/ids/' + vm.editId)
|
||||
|
||||
@@ -149,14 +149,19 @@ class Onboard extends Base
|
||||
$service = new HuifuOnboardAdminService();
|
||||
$onboardId = $row ? intval($row['id']) : 0;
|
||||
$saved = $service->saveDraft($userId, $roleType, $roleRefId, $form, $onboardId);
|
||||
$this->success('进件资料已保存,状态为待后台审核', null, [
|
||||
'id' => $saved ? $saved['id'] : 0,
|
||||
]);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$this->error($e->getMessage());
|
||||
} catch (\think\exception\HttpResponseException $e) {
|
||||
throw $e;
|
||||
} catch (\Throwable $e) {
|
||||
$this->error(HuifuOnboardError::translate($e->getMessage()));
|
||||
}
|
||||
if (!$saved) {
|
||||
$this->error('进件资料保存失败,请检查汇付分账配置是否已启用');
|
||||
}
|
||||
$this->success('进件资料已保存,状态为待后台审核', null, [
|
||||
'id' => intval($saved['id']),
|
||||
]);
|
||||
}
|
||||
|
||||
public function retry($ids = null)
|
||||
|
||||
@@ -389,8 +389,9 @@
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="开户银行支行" required>
|
||||
<el-input v-model="branchKeyword" class="form-input" placeholder="搜索支行名称" @input="onBranchInput"></el-input>
|
||||
<div class="field-tip" v-if="form.branch_name">已选:{{ form.branch_name }}({{ form.branch_code }})</div>
|
||||
<el-input v-model="branchKeyword" class="form-input" placeholder="输入支行名称搜索,并从下方结果中点击选择" @input="onBranchInput"></el-input>
|
||||
<div class="field-tip">须从搜索结果中点击选择支行,仅输入文字无法保存</div>
|
||||
<div class="field-tip" v-if="form.branch_code" style="color:#7536D0;">已选:{{ form.branch_name }}(联行号 {{ form.branch_code }})</div>
|
||||
<div class="branch-panel" v-if="branchResults.length">
|
||||
<div class="branch-item" v-for="(item, idx) in branchResults" :key="idx" @click="selectBranch(item)">
|
||||
<div>{{ item.branch_name }}</div>
|
||||
|
||||
@@ -233,17 +233,24 @@ define(['jquery', 'bootstrap', 'backend'], function ($, undefined, Backend) {
|
||||
},
|
||||
onBranchInput: function () {
|
||||
var vm = this;
|
||||
var keyword = (vm.branchKeyword || '').trim();
|
||||
if (keyword !== vm.form.branch_name) {
|
||||
vm.form.branch_code = '';
|
||||
vm.form.branch_name = keyword;
|
||||
}
|
||||
clearTimeout(branchTimer);
|
||||
branchTimer = setTimeout(function () {
|
||||
if (!vm.branchKeyword) {
|
||||
if (!keyword) {
|
||||
vm.branchResults = [];
|
||||
vm.form.branch_code = '';
|
||||
vm.form.branch_name = '';
|
||||
return;
|
||||
}
|
||||
Fast.api.ajax({
|
||||
url: 'shopro_huifu/onboard/searchBranch',
|
||||
type: 'GET',
|
||||
data: {
|
||||
keyword: vm.branchKeyword,
|
||||
keyword: keyword,
|
||||
area_id: vm.form.area_id || vm.form.shopro_city_id
|
||||
}
|
||||
}, function (ret, res) {
|
||||
@@ -252,6 +259,47 @@ define(['jquery', 'bootstrap', 'backend'], function ($, undefined, Backend) {
|
||||
});
|
||||
}, 300);
|
||||
},
|
||||
prepareFormBeforeSubmit: function () {
|
||||
var keyword = (this.branchKeyword || '').trim();
|
||||
if (keyword) {
|
||||
this.form.branch_name = keyword;
|
||||
}
|
||||
this.form.mp = this.bankMobile;
|
||||
},
|
||||
validateFormBeforeSubmit: function () {
|
||||
var form = this.form;
|
||||
if (form.account_type === 'indv') {
|
||||
if (!form.name || !form.cert_no || !form.mobile_no || !form.reg_detail) {
|
||||
Toastr.error('请完整填写身份实名信息');
|
||||
return false;
|
||||
}
|
||||
if (!form.id_card_front_url || !form.id_card_back_url) {
|
||||
Toastr.error('请上传身份证人像面和国徽面');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!form.card_no) {
|
||||
Toastr.error('请填写银行卡号');
|
||||
return false;
|
||||
}
|
||||
if (!this.bankMobile) {
|
||||
Toastr.error('请填写银行预留手机号');
|
||||
return false;
|
||||
}
|
||||
if (!form.branch_code) {
|
||||
if ((this.branchKeyword || '').trim() || form.branch_name) {
|
||||
Toastr.error('请从支行搜索结果中点击选择开户银行(需联行号)');
|
||||
} else {
|
||||
Toastr.error('请搜索并选择开户银行支行');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!form.shopro_province_id && !form.prov_id) {
|
||||
Toastr.error('请选择所在区域');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
selectBranch: function (item) {
|
||||
this.form.branch_code = item.branch_code;
|
||||
this.form.branch_name = item.branch_name;
|
||||
@@ -282,6 +330,10 @@ define(['jquery', 'bootstrap', 'backend'], function ($, undefined, Backend) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
vm.prepareFormBeforeSubmit();
|
||||
if (!vm.validateFormBeforeSubmit()) {
|
||||
return;
|
||||
}
|
||||
vm.saving = true;
|
||||
var url = vm.isEdit
|
||||
? ('shopro_huifu/onboard/edit/ids/' + vm.editId)
|
||||
|
||||
在新工单中引用
屏蔽一个用户