7ef3fc22 by 张猛

Merge remote-tracking branch 'origin/master'

2 parents ff58c49a bbc048f7
1 # CLAUDE.md
2
3 This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
5 ## Project Overview
6
7 This is a **uni-app** (Vue 3) WeChat mini-program project for the **China Taekwondo Association (中国跆拳道协会)** membership management system.
8
9 - **Platform**: mp-weixin (WeChat Mini-Program)
10 - **Vue Version**: Vue 3 with `<script setup>` syntax
11 - **State Management**: Pinia
12 - **UI Framework**: uni-ui (components in `uni_modules/`)
13 - **Key Dependencies**: dayjs, underscore, lodash, crypto-js
14
15 ## Development Commands
16
17 ### Running the Project
18 - Use **HBuilderX** to open this project
19 - Or use CLI: `npm run dev:mp-weixin`
20 - Build: `npm run build:mp-weixin`
21
22 ### Key Configurations
23 - `config.js` - API base URLs (dev/prod switching)
24 - `pages.json` - Page routing and global settings
25 - `manifest.json` - App configuration (appid, platform settings)
26
27 ## Architecture
28
29 ### Directory Structure
30 ```
31 ├── common/ # Shared utilities
32 │ ├── api.js # API functions (imported as @/common/api.js)
33 │ ├── request.js # HTTP request wrapper
34 │ ├── login.js # Login logic
35 │ ├── utils.js # Utility functions
36 │ └── pay.js # Payment logic
37 ├── config.js # Environment config (API endpoints)
38 ├── pages/ # Main package pages (index, exam, invoice, rank, webview)
39 ├── login/ # Login sub-package
40 ├── personal/ # Personal member sub-package
41 ├── personalVip/ # VIP member sub-package
42 ├── group/ # Group/Organization sub-package
43 ├── level/ # Level examination sub-package
44 ├── myCenter/ # User center sub-package
45 ├── uni_modules/ # uni-ui components
46 └── static/ # Static assets
47 ```
48
49 ### API Pattern
50 All API functions are defined in `common/api.js` using a consistent pattern:
51 ```js
52 export function apiFunctionName(data) {
53 return request({
54 url: '/path/to/endpoint',
55 method: 'post', // or 'get', 'put', 'delete'
56 params: data
57 })
58 }
59 ```
60
61 ### Page Sub-packages
62 Pages are organized into sub-packages defined in `pages.json` to optimize loading. Each sub-package has its own root directory (e.g., `level/`, `myCenter/`).
63
64 ### Component Auto-import
65 uni-ui components are auto-imported via easycom in `pages.json`:
66 ```json
67 "easycom": {
68 "autoscan": true,
69 "custom": {
70 "^uni-(.*)": "uni_modules/uni-$1/components/uni-$1/uni-$1.vue"
71 }
72 }
73 ```
74
75 ### Global Data
76 `app.globalData` contains shared state (from `App.vue`):
77 - `memberInfo` - Current member info
78 - `isLogin` - Login status
79 - `deptType` - Department type
80
81 Access via: `const app = getApp(); app.globalData.memberInfo`
82
83 ### Form Handling Pattern
84 For forms with `uni-forms`, use `Object.assign(form.value, data)` instead of `form.value = data` to preserve reactive bindings.
85
86 ### DateTime Picker
87 `uni-datetime-picker` requires ISO format strings or timestamps for v-model values.
88
89 ### File Upload Pattern
90 Use `api.uploadFile(e)` or `api.uploadImg(e)` from `common/api.js` which return `{ code, msg }` - the file URL is in `res.msg`.
91
92 ## Common Issues
93
94 ### uni-data-select not working
95 If `uni-data-select` dropdowns don't appear, ensure:
96 1. easycom is properly configured in `pages.json`
97 2. The component is not blocked by CSS `overflow: hidden` on parent containers
98
99 ### Responsive Data Binding
100 When updating form data from API responses, use `Object.assign()` to maintain Vue 3 reactivity:
101 ```js
102 // Instead of: form.value = res.data
103 Object.assign(form.value, res.data)
104 ```
...@@ -61,7 +61,14 @@ function getCodeImg() { ...@@ -61,7 +61,14 @@ function getCodeImg() {
61 method: 'get' 61 method: 'get'
62 }) 62 })
63 } 63 }
64 64 function getSmsCodeImg(data) {
65 return request({
66 url: '/captchaSmsWithCaptchaImage',
67 // url: '/captchaSmsWithCaptchaImageForMiniApp',
68 method: 'post',
69 params: data
70 })
71 }
65 // 代退图形认证的获取手机验证码 72 // 代退图形认证的获取手机验证码
66 function getSmsCode(data) { 73 function getSmsCode(data) {
67 return request({ 74 return request({
...@@ -241,6 +248,7 @@ export { ...@@ -241,6 +248,7 @@ export {
241 pcLogin, 248 pcLogin,
242 getCodeImg, 249 getCodeImg,
243 getSmsCode, 250 getSmsCode,
251 getSmsCodeImg,
244 h5Login, 252 h5Login,
245 h5LoginAuto, 253 h5LoginAuto,
246 loginByPhone, 254 loginByPhone,
......
...@@ -4,13 +4,13 @@ page { ...@@ -4,13 +4,13 @@ page {
4 background: #ecf0f6; 4 background: #ecf0f6;
5 } 5 }
6 /* uni-data-checkbox 选中色全局覆盖为红色 */ 6 /* uni-data-checkbox 选中色全局覆盖为红色 */
7 uni-data-checkbox .checklist-box.is-checked { 7 // uni-data-checkbox .checklist-box.is-checked {
8 border-color: #C4121B !important; 8 // border-color: #C4121B !important;
9 background-color: #C4121B !important; 9 // background-color: #C4121B !important;
10 } 10 // }
11 uni-data-checkbox .checklist-box.is-checked .checklist-text { 11 // uni-data-checkbox .checklist-box.is-checked .checklist-text {
12 color: #fff !important; 12 // color: #fff !important;
13 } 13 // }
14 .wBox{box-sizing: border-box;} 14 .wBox{box-sizing: border-box;}
15 .h3 {font-weight: bold;line-height: 2;} 15 .h3 {font-weight: bold;line-height: 2;}
16 .text-center{text-align: center;} 16 .text-center{text-align: center;}
......
...@@ -933,7 +933,7 @@ ...@@ -933,7 +933,7 @@
933 padding: 20rpx 0; 933 padding: 20rpx 0;
934 background: #fff; 934 background: #fff;
935 border-top: 1rpx solid #f0f0f0; 935 border-top: 1rpx solid #f0f0f0;
936 z-index: 999; 936 z-index: 98;
937 937
938 .btn-red { 938 .btn-red {
939 background: linear-gradient(135deg, #AD181F 0%, #c42a2a 100%); 939 background: linear-gradient(135deg, #AD181F 0%, #c42a2a 100%);
......
...@@ -68,7 +68,7 @@ import { ...@@ -68,7 +68,7 @@ import {
68 } from 'vue' 68 } from 'vue'
69 import { 69 import {
70 getCodeImg, 70 getCodeImg,
71 getSmsCode, 71 getSmsCodeImg,
72 groupMemberRegister 72 groupMemberRegister
73 } from '@/common/login.js' 73 } from '@/common/login.js'
74 import config from '@/config.js' 74 import config from '@/config.js'
...@@ -113,6 +113,14 @@ function register() { ...@@ -113,6 +113,14 @@ function register() {
113 }) 113 })
114 return 114 return
115 } 115 }
116 // 密码强度校验:8~18位大小写字母加数字加特殊符号组合
117 if (!validPassword(registerForm.value.password)) {
118 uni.showToast({
119 title: '密码必须为8~18位大小写字母、数字和特殊符号组合',
120 icon: 'none'
121 })
122 return
123 }
116 if (registerForm.value.password != registerForm.value.password2) { 124 if (registerForm.value.password != registerForm.value.password2) {
117 uni.showToast({ 125 uni.showToast({
118 title: '两次密码不一致,请重新输入', 126 title: '两次密码不一致,请重新输入',
...@@ -131,13 +139,27 @@ function register() { ...@@ -131,13 +139,27 @@ function register() {
131 groupMemberRegister(registerForm.value) 139 groupMemberRegister(registerForm.value)
132 .then((res) => { 140 .then((res) => {
133 uni.showToast({ 141 uni.showToast({
134 title: `恭喜你,您的账号 ${registerForm.value.telNo} 注册成功!` 142 title: `恭喜你,您的账号 ${registerForm.value.telNo} 注册成功!`,
143 icon: 'none'
135 }) 144 })
136 registerForm.value = {} 145 registerForm.value = {}
137 setTimeout(goLogin, 2000) 146 setTimeout(goLogin, 2000)
138 }) 147 })
139 } 148 }
140 149
150 // 密码校验:8~18位大小写字母加数字加特殊符号组合
151 function validPassword(pwd) {
152 if (!pwd || pwd.length < 8 || pwd.length > 18) {
153 return false
154 }
155 const lowerRegex = /[a-z]+/
156 const upperRegex = /[A-Z]+/
157 const digitRegex = /[0-9]+/
158 const symbolRegex = /[\W_]+/
159 const specific = /.*[~!@#$%^&*()_+`\-={}:";'<>?,.\/].*/
160 return (lowerRegex.test(pwd) && upperRegex.test(pwd) && digitRegex.test(pwd) && symbolRegex.test(pwd) && specific.test(pwd))
161 }
162
141 function goLogin() { 163 function goLogin() {
142 let path = '/login/loginC'; 164 let path = '/login/loginC';
143 uni.navigateTo({ 165 uni.navigateTo({
...@@ -169,7 +191,7 @@ function getCaptchaSms() { ...@@ -169,7 +191,7 @@ function getCaptchaSms() {
169 return 191 return
170 } 192 }
171 193
172 getSmsCode({ 194 getSmsCodeImg({
173 uuid: registerForm.value.uuid, 195 uuid: registerForm.value.uuid,
174 telNo: registerForm.value.telNo, 196 telNo: registerForm.value.telNo,
175 code: registerForm.value.captcha 197 code: registerForm.value.captcha
......
...@@ -264,10 +264,10 @@ ...@@ -264,10 +264,10 @@
264 getTree() 264 getTree()
265 form.value.deptType = res.data.dept.deptType 265 form.value.deptType = res.data.dept.deptType
266 form.value.parentId = form.value.parentId.toString() 266 form.value.parentId = form.value.parentId.toString()
267 creditCode.value = form.value.creditCode 267 // creditCode.value = form.value.creditCode
268 companyName.value = form.value.companyName 268 // form.value.companyName = res.data.memberInfo.companyName
269 belongProvinceId.value = form.value.belongProvinceId 269 // belongProvinceId.value = form.value.belongProvinceId
270 parentId.value = form.value.parentId 270 // parentId.value = form.value.parentId
271 271
272 if (form.value.regionId) { 272 if (form.value.regionId) {
273 form.value.coordinates1 = form.value.regionId 273 form.value.coordinates1 = form.value.regionId
......
1 { 1 {
2 "easycom": {
3 "autoscan": true,
4 "custom": {
5 "^uni-(.*)": "uni_modules/uni-$1/components/uni-$1/uni-$1.vue"
6 }
7 },
2 "pages": [{ 8 "pages": [{
3 "path": "pages/index/index" 9 "path": "pages/index/index"
4 }, 10 },
......
...@@ -22,7 +22,9 @@ ...@@ -22,7 +22,9 @@
22 <uni-easyinput class="input-with-border" v-model="form.baseName" :disabled="!editIng" placeholder="单位名称" /> 22 <uni-easyinput class="input-with-border" v-model="form.baseName" :disabled="!editIng" placeholder="单位名称" />
23 </uni-forms-item> 23 </uni-forms-item>
24 <uni-forms-item label="单位类型" required> 24 <uni-forms-item label="单位类型" required>
25 <uni-data-select :disabled="!editIng" v-model="form.type" :localdata="typeList"></uni-data-select> 25 <view style="width: 100%;">
26 <uni-data-select v-model="form.type" :localdata="typeList" placeholder="请选择单位类型"></uni-data-select>
27 </view>
26 </uni-forms-item> 28 </uni-forms-item>
27 <uni-forms-item label="联系人" required> 29 <uni-forms-item label="联系人" required>
28 <uni-easyinput class="input-with-border" v-model="form.contact" :disabled="!editIng" placeholder="请输入联系人姓名" /> 30 <uni-easyinput class="input-with-border" v-model="form.contact" :disabled="!editIng" placeholder="请输入联系人姓名" />
...@@ -51,10 +53,10 @@ ...@@ -51,10 +53,10 @@
51 <text v-if="authenticationStatusa == 4" class="text-warning">即将过期</text> 53 <text v-if="authenticationStatusa == 4" class="text-warning">即将过期</text>
52 <text v-if="authenticationStatusa == 5" class="text-danger">已过期</text> 54 <text v-if="authenticationStatusa == 5" class="text-danger">已过期</text>
53 </view> 55 </view>
54 <view class="btn-row"> 56 <!-- <view class="btn-row">
55 <button type="primary" :disabled="btn" @click="goPay">去缴费</button> 57 <button type="primary" :disabled="btn" @click="goPay">去缴费</button>
56 <button v-if="form.deptType != 2" type="default" @click="goAuditDetail">审核详情</button> 58 <button v-if="form.deptType != 2" type="default" @click="goAuditDetail">审核详情</button>
57 </view> 59 </view> -->
58 </view> 60 </view>
59 61
60 <uni-forms ref="certForm" :modelValue="form" label-width="90"> 62 <uni-forms ref="certForm" :modelValue="form" label-width="90">
...@@ -100,7 +102,7 @@ ...@@ -100,7 +102,7 @@
100 <image :src="config.baseUrl_api + '/fs/static/yyzz@2x.png'" class="placeholder-img"/> 102 <image :src="config.baseUrl_api + '/fs/static/yyzz@2x.png'" class="placeholder-img"/>
101 </view> 103 </view>
102 <view v-else class="license-preview"> 104 <view v-else class="license-preview">
103 <image v-if="typeof form.businessLicense === 'string'" :src="form.businessLicense" class="license-img" @click="previewImage(form.businessLicense)"></image> 105 <image :src="getImageUrl(getBusinessLicenseUrl())" class="license-img" @click="previewImage(getImageUrl(getBusinessLicenseUrl()))"></image>
104 <view class="delete-btn" v-if="editIng" @click="removeBusinessLicense">×</view> 106 <view class="delete-btn" v-if="editIng" @click="removeBusinessLicense">×</view>
105 </view> 107 </view>
106 </view> 108 </view>
...@@ -118,7 +120,7 @@ ...@@ -118,7 +120,7 @@
118 <image :src="config.baseUrl_api + '/fs/static/sfz_zm@2x.png'" class="placeholder-img"/> 120 <image :src="config.baseUrl_api + '/fs/static/sfz_zm@2x.png'" class="placeholder-img"/>
119 </view> 121 </view>
120 <view v-else class="idcard-preview"> 122 <view v-else class="idcard-preview">
121 <image :src="form.legalIdcPhoto1" class="idcard-img" @click="previewImage(form.legalIdcPhoto1)"></image> 123 <image :src="getImageUrl(form.legalIdcPhoto1)" class="idcard-img" @click="previewImage(getImageUrl(form.legalIdcPhoto1))"></image>
122 <view class="delete-btn" v-if="editIng" @click="removeIdCardFront">×</view> 124 <view class="delete-btn" v-if="editIng" @click="removeIdCardFront">×</view>
123 </view> 125 </view>
124 </view> 126 </view>
...@@ -129,7 +131,7 @@ ...@@ -129,7 +131,7 @@
129 <image :src="config.baseUrl_api + '/fs/static/sfz_fm@2x.png'" class="placeholder-img"/> 131 <image :src="config.baseUrl_api + '/fs/static/sfz_fm@2x.png'" class="placeholder-img"/>
130 </view> 132 </view>
131 <view v-else class="idcard-preview"> 133 <view v-else class="idcard-preview">
132 <image :src="form.legalIdcPhoto2" class="idcard-img" @click="previewImage(form.legalIdcPhoto2)"></image> 134 <image :src="getImageUrl(form.legalIdcPhoto2)" class="idcard-img" @click="previewImage(getImageUrl(form.legalIdcPhoto2))"></image>
133 <view class="delete-btn" v-if="editIng" @click="removeIdCardBack">×</view> 135 <view class="delete-btn" v-if="editIng" @click="removeIdCardBack">×</view>
134 </view> 136 </view>
135 </view> 137 </view>
...@@ -147,7 +149,7 @@ ...@@ -147,7 +149,7 @@
147 <image :src="config.baseUrl_api + '/fs/static/jgzp@2x.png'" class="placeholder-img"/> 149 <image :src="config.baseUrl_api + '/fs/static/jgzp@2x.png'" class="placeholder-img"/>
148 </view> 150 </view>
149 <view v-else class="pictures-preview"> 151 <view v-else class="pictures-preview">
150 <image :src="form.pictures.split(',')[0]" class="picture-img" @click="previewImage(form.pictures.split(','))"></image> 152 <image :src="getImageUrl(form.pictures.split(',')[0])" class="picture-img" @click="previewImage(form.pictures.split(',').map(url => getImageUrl(url)))"></image>
151 <view class="delete-btn" v-if="editIng" @click="removePictures">×</view> 153 <view class="delete-btn" v-if="editIng" @click="removePictures">×</view>
152 </view> 154 </view>
153 </view> 155 </view>
...@@ -166,7 +168,8 @@ ...@@ -166,7 +168,8 @@
166 <script setup> 168 <script setup>
167 import { 169 import {
168 ref, 170 ref,
169 reactive 171 reactive,
172 computed
170 } from 'vue'; 173 } from 'vue';
171 import * as api from '@/common/api.js'; 174 import * as api from '@/common/api.js';
172 import { 175 import {
...@@ -174,6 +177,7 @@ ...@@ -174,6 +177,7 @@
174 onShow 177 onShow
175 } from '@dcloudio/uni-app'; 178 } from '@dcloudio/uni-app';
176 import config from '@/config.js' 179 import config from '@/config.js'
180 // import uniDataSelect from '@/uni_modules/uni-data-select/components/uni-data-select/uni-data-select.vue'
177 const app = getApp(); 181 const app = getApp();
178 182
179 const form = ref({ 183 const form = ref({
...@@ -195,6 +199,17 @@ ...@@ -195,6 +199,17 @@
195 text: '其他' 199 text: '其他'
196 }]) 200 }])
197 201
202 // 类型索引
203 const typeIndex = computed(() => {
204 return typeList.value.findIndex(item => String(item.value) === String(form.value.type))
205 })
206
207 // 类型选择
208 function typeChange(e) {
209 const index = e.detail.value
210 form.value.type = typeList.value[index].value
211 }
212
198 // 地址选项 213 // 地址选项
199 const options = ref([]) 214 const options = ref([])
200 const regionOptions = ref([]) 215 const regionOptions = ref([])
...@@ -210,7 +225,7 @@ ...@@ -210,7 +225,7 @@
210 }, { 225 }, {
211 title: '会员认证' 226 title: '会员认证'
212 }]) 227 }])
213 228 const creditCode = ref('')
214 // 编辑状态 229 // 编辑状态
215 const editIng = ref(true); 230 const editIng = ref(true);
216 231
...@@ -232,6 +247,28 @@ ...@@ -232,6 +247,28 @@
232 // 考点审核状态 247 // 考点审核状态
233 const auditStatus = ref('0') 248 const auditStatus = ref('0')
234 249
250 // 图片URL处理:如果不是http开头,拼接baseUrl_api
251 function getImageUrl(url) {
252 if (!url) return ''
253 if (url.indexOf('http') === 0) return url
254 return config.baseUrl_api + url
255 }
256
257 // 解析营业执照URL
258 function getBusinessLicenseUrl() {
259 if (!form.value.businessLicense) return ''
260 try {
261 const arr = JSON.parse(form.value.businessLicense)
262 if (Array.isArray(arr) && arr.length > 0) {
263 return arr[0].url || ''
264 }
265 } catch (e) {
266 // 如果不是JSON格式,可能是直接返回的URL
267 return form.value.businessLicense
268 }
269 return ''
270 }
271
235 onLoad(option => { 272 onLoad(option => {
236 getTree() 273 getTree()
237 if (app.globalData.isLogin) { 274 if (app.globalData.isLogin) {
...@@ -260,6 +297,9 @@ ...@@ -260,6 +297,9 @@
260 // Object.assign(form.value, res.data.memberInfo) 297 // Object.assign(form.value, res.data.memberInfo)
261 // } 298 // }
262 form.value = { ...res.data.dept, ...res.data.memberInfo } 299 form.value = { ...res.data.dept, ...res.data.memberInfo }
300 if (form.value.type) {
301 form.value.type = String(form.value.type)
302 }
263 authenticationStatusa.value = res.data.authenticationStatus 303 authenticationStatusa.value = res.data.authenticationStatus
264 result.value = res.data.result 304 result.value = res.data.result
265 305
...@@ -311,11 +351,11 @@ ...@@ -311,11 +351,11 @@
311 btn.value = !result.value 351 btn.value = !result.value
312 } 352 }
313 353
314 creditCode.value = form.value.creditCode 354 // creditCode.value = form.value.creditCode
315 legal.value = form.value.legal 355 // legal.value = form.value.legal
316 legalIdcCode.value = form.value.legalIdcCode 356 // legalIdcCode.value = form.value.legalIdcCode
317 coordinates1.value = form.value.provinceId 357 // coordinates1.value = form.value.provinceId
318 adress.value = form.value.adress 358 // adress.value = form.value.adress
319 form.value.name = form.value.baseName 359 form.value.name = form.value.baseName
320 }) 360 })
321 } 361 }
...@@ -601,22 +641,18 @@ ...@@ -601,22 +641,18 @@
601 641
602 // 提交认证信息(100%对齐PC端入参格式) 642 // 提交认证信息(100%对齐PC端入参格式)
603 function submitCertification() { 643 function submitCertification() {
604 uni.showLoading({ title: '提交中...' }) 644 let params = {
605 api.editMyMemberCertifiedInfo({
606 parentId: form.value.parentId, 645 parentId: form.value.parentId,
607 creditCode: form.value.creditCode, 646 creditCode: form.value.creditCode,
608 legal: form.value.legal, 647 legal: form.value.legal,
609 businessLicense: JSON.stringify({ 648 businessLicense: form.value.businessLicense,
610 url: form.value.businessLicense,
611 name: form.value.businessLicenseName
612 }),
613 pictures: form.value.pictures, 649 pictures: form.value.pictures,
614 memId: form.value.memId, 650 memId: form.value.memId,
615 id: form.value.deptId, 651 id: form.value.deptId,
616 name: form.value.name, 652 name: form.value.name,
617 regionId: form.value.regionId?.value, 653 regionId: form.value.regionId?.value,
618 cityId: form.value.cityId.value, 654 cityId: form.value.cityId.value.toString(),
619 provinceId: form.value.provinceId.value, 655 provinceId: form.value.provinceId.value.toString(),
620 adress: form.value.adress, 656 adress: form.value.adress,
621 deptType: app.globalData.deptType, 657 deptType: app.globalData.deptType,
622 legalIdcPhoto: [form.value.legalIdcPhoto1, form.value.legalIdcPhoto2].join(','), 658 legalIdcPhoto: [form.value.legalIdcPhoto1, form.value.legalIdcPhoto2].join(','),
...@@ -625,7 +661,11 @@ ...@@ -625,7 +661,11 @@
625 siteTel: form.value.siteTel, 661 siteTel: form.value.siteTel,
626 companyName: form.value.companyName, 662 companyName: form.value.companyName,
627 legalIdcCode: form.value.legalIdcCode 663 legalIdcCode: form.value.legalIdcCode
628 }).then(res => { 664 }
665 console.log(666,params)
666 // return
667 uni.showLoading({ title: '提交中...' })
668 api.editMyMemberCertifiedInfo(params).then(res => {
629 uni.hideLoading() 669 uni.hideLoading()
630 if (res.code === 200) { 670 if (res.code === 200) {
631 uni.showToast({ title: '提交成功', duration: 1500, icon: 'success' }) 671 uni.showToast({ title: '提交成功', duration: 1500, icon: 'success' })
...@@ -654,23 +694,41 @@ ...@@ -654,23 +694,41 @@
654 sourceType: ['album', 'camera'], 694 sourceType: ['album', 'camera'],
655 success: (res) => { 695 success: (res) => {
656 if (res.tempFilePaths && res.tempFilePaths.length > 0) { 696 if (res.tempFilePaths && res.tempFilePaths.length > 0) {
657 form.value.businessLicense = res.tempFilePaths[0] 697 uni.showLoading({ title: '上传中...' })
658 // 调用API识别营业执照 698 // 先上传文件
659 uni.uploadFile({ 699 api.uploadFile(res).then(uploadRes => {
700 if (uploadRes.code !== 200) {
701 throw new Error('上传失败')
702 }
703 const url = uploadRes.msg
704 // 上传成功后调用OCR识别
705 return uni.uploadFile({
660 url: config.baseUrl_api + '/member/info/getBusinessLicense', 706 url: config.baseUrl_api + '/member/info/getBusinessLicense',
661 filePath: res.tempFilePaths[0], 707 filePath: res.tempFilePaths[0],
662 name: 'pic', 708 name: 'pic',
663 header: { 709 header: {
664 'Authorization': uni.getStorageSync('token') 710 'Authorization': uni.getStorageSync('token')
665 }, 711 }
666 success: (uploadRes) => { 712 }).then(ocrRes => {
667 const data = JSON.parse(uploadRes.data) 713 return { url, ocrRes }
714 })
715 }).then(({ url, ocrRes }) => {
716 uni.hideLoading()
717 const data = JSON.parse(ocrRes.data)
718 let name = '营业执照'
668 if (data.code === 200 && data.data) { 719 if (data.code === 200 && data.data) {
669 form.value.creditCode = data.data.creditCode 720 form.value.creditCode = data.data.creditCode
670 form.value.companyName = data.data.companyName 721 form.value.companyName = data.data.companyName
671 form.value.businessLicenseName = data.data.name 722 name = data.data.name || '营业执照'
672 }
673 } 723 }
724 // 存储为数组格式的JSON字符串
725 form.value.businessLicense = JSON.stringify([{
726 url: url,
727 name: name
728 }])
729 }).catch(() => {
730 uni.hideLoading()
731 uni.showToast({ title: '上传失败', icon: 'none' })
674 }) 732 })
675 } 733 }
676 } 734 }
...@@ -692,7 +750,7 @@ ...@@ -692,7 +750,7 @@
692 form.value.legalIdcPhoto2 = '' 750 form.value.legalIdcPhoto2 = ''
693 } 751 }
694 752
695 // 身份证上传(修复:正面调用OCR,和PC端逻辑一致) 753 // 身份证上传
696 function onIdCardFrontSelect() { 754 function onIdCardFrontSelect() {
697 uni.chooseImage({ 755 uni.chooseImage({
698 count: 1, 756 count: 1,
...@@ -700,8 +758,16 @@ ...@@ -700,8 +758,16 @@
700 sourceType: ['album', 'camera'], 758 sourceType: ['album', 'camera'],
701 success: (res) => { 759 success: (res) => {
702 if (res.tempFilePaths && res.tempFilePaths.length > 0) { 760 if (res.tempFilePaths && res.tempFilePaths.length > 0) {
703 form.value.legalIdcPhoto1 = res.tempFilePaths[0] 761 uni.showLoading({ title: '上传中...' })
704 762 api.uploadImg(res).then(data => {
763 if (data.code === 200) {
764 form.value.legalIdcPhoto1 = data.msg
765 }
766 uni.hideLoading()
767 }).catch(() => {
768 uni.hideLoading()
769 uni.showToast({ title: '上传失败', icon: 'none' })
770 })
705 } 771 }
706 } 772 }
707 }) 773 })
...@@ -714,19 +780,30 @@ ...@@ -714,19 +780,30 @@
714 sourceType: ['album', 'camera'], 780 sourceType: ['album', 'camera'],
715 success: (res) => { 781 success: (res) => {
716 if (res.tempFilePaths && res.tempFilePaths.length > 0) { 782 if (res.tempFilePaths && res.tempFilePaths.length > 0) {
717 form.value.legalIdcPhoto2 = res.tempFilePaths[0] 783 const tempPath = res.tempFilePaths[0]
718 extractIdCardInfo() // 修复:正面上传后调用OCR提取信息 784 uni.showLoading({ title: '上传中...' })
785 api.uploadImg(res).then(data => {
786 if (data.code === 200) {
787 form.value.legalIdcPhoto2 = data.msg
788 // 用临时文件路径调用OCR
789 extractIdCardInfo(tempPath)
790 }
791 uni.hideLoading()
792 }).catch(() => {
793 uni.hideLoading()
794 uni.showToast({ title: '上传失败', icon: 'none' })
795 })
719 } 796 }
720 } 797 }
721 }) 798 })
722 } 799 }
723 800
724 // 提取身份证信息(修复:传正面照片legalIdcPhoto1,和PC端逻辑一致) 801 // 提取身份证信息
725 function extractIdCardInfo() { 802 function extractIdCardInfo(tempPath) {
726 if (form.value.legalIdcPhoto1) { 803 if (tempPath) {
727 uni.uploadFile({ 804 uni.uploadFile({
728 url: config.baseUrl_api + '/person/info/getPersonInfoFromCert/0', 805 url: config.baseUrl_api + '/person/info/getPersonInfoFromCert/0',
729 filePath: form.value.legalIdcPhoto2, 806 filePath: tempPath,
730 name: 'pic', 807 name: 'pic',
731 header: { 808 header: {
732 'Authorization': uni.getStorageSync('token') 809 'Authorization': uni.getStorageSync('token')
...@@ -750,7 +827,19 @@ ...@@ -750,7 +827,19 @@
750 sourceType: ['album', 'camera'], 827 sourceType: ['album', 'camera'],
751 success: (res) => { 828 success: (res) => {
752 if (res.tempFilePaths && res.tempFilePaths.length > 0) { 829 if (res.tempFilePaths && res.tempFilePaths.length > 0) {
753 form.value.pictures = res.tempFilePaths.join(',') 830 uni.showLoading({ title: '上传中...' })
831 // 循环上传多张图片
832 const promises = res.tempFilePaths.map(path => {
833 return api.uploadImg({ tempFilePaths: [path] })
834 })
835 Promise.all(promises).then(results => {
836 uni.hideLoading()
837 const urls = results.filter(r => r.code === 200).map(r => r.msg)
838 form.value.pictures = urls.join(',')
839 }).catch(() => {
840 uni.hideLoading()
841 uni.showToast({ title: '上传失败', icon: 'none' })
842 })
754 } 843 }
755 } 844 }
756 }) 845 })
...@@ -951,6 +1040,7 @@ ...@@ -951,6 +1040,7 @@
951 font-size: 28rpx; 1040 font-size: 28rpx;
952 color: #333; 1041 color: #333;
953 margin-right: 10rpx; 1042 margin-right: 10rpx;
1043 width: 100px;
954 } 1044 }
955 1045
956 .btn-row { 1046 .btn-row {
...@@ -1154,6 +1244,34 @@ ...@@ -1154,6 +1244,34 @@
1154 } 1244 }
1155 } 1245 }
1156 1246
1247 /* picker 样式 */
1248 .picker-view {
1249 height: 70rpx;
1250 line-height: 70rpx;
1251 display: flex;
1252 align-items: center;
1253 justify-content: space-between;
1254 padding: 0 20rpx;
1255 box-sizing: border-box;
1256 }
1257
1258 .picker-text {
1259 flex: 1;
1260 overflow: hidden;
1261 text-overflow: ellipsis;
1262 white-space: nowrap;
1263 }
1264
1265 .arrow-icon {
1266 font-size: 20rpx;
1267 color: #999;
1268 }
1269
1270 .placeholder {
1271 color: #999;
1272 }
1273
1274
1157 /* 级联选择器容器 - 修复边框和宽度问题(删除重复定义) */ 1275 /* 级联选择器容器 - 修复边框和宽度问题(删除重复定义) */
1158 .picker-wrapper { 1276 .picker-wrapper {
1159 border: 1rpx solid #e0e0e0; 1277 border: 1rpx solid #e0e0e0;
...@@ -1200,17 +1318,34 @@ ...@@ -1200,17 +1318,34 @@
1200 min-height: 70rpx; 1318 min-height: 70rpx;
1201 } 1319 }
1202 1320
1321 /* uni-data-picker 弹窗样式 - 列表文字大小 */
1322 :deep(.item) {
1323 font-size: 32rpx !important;
1324 padding: 24rpx 30rpx !important;
1325 }
1326 :deep(.item-text) {
1327 font-size: 32rpx !important;
1328 }
1329 :deep(.selected-item-text) {
1330 font-size: 32rpx !important;
1331 }
1332
1203 /* 修复uni-forms-item中内容超出问题 */ 1333 /* 修复uni-forms-item中内容超出问题 */
1334 /* 暂时移除 overflow: hidden 以避免影响下拉组件 */
1335 /*
1204 :deep(.uni-forms-item__content) { 1336 :deep(.uni-forms-item__content) {
1205 overflow: hidden; 1337 overflow: hidden;
1206 width: 100%; 1338 width: 100%;
1207 } 1339 }
1340 */
1208 1341
1209 /* 确保所有表单元素不超出父容器 */ 1342 /* 确保所有表单元素不超出父容器 */
1343 /*
1210 :deep(uni-forms-item) { 1344 :deep(uni-forms-item) {
1211 width: 100%; 1345 width: 100%;
1212 overflow: hidden; 1346 overflow: hidden;
1213 } 1347 }
1348 */
1214 1349
1215 /* 修复选择器容器宽度问题 */ 1350 /* 修复选择器容器宽度问题 */
1216 .picker-wrapper { 1351 .picker-wrapper {
......
...@@ -219,7 +219,7 @@ ...@@ -219,7 +219,7 @@
219 display: flex; 219 display: flex;
220 /* #endif */ 220 /* #endif */
221 align-items: center; 221 align-items: center;
222 padding: 8px 10px; 222 padding: 18px 10px;
223 padding-right: 5px; 223 padding-right: 5px;
224 padding-left: 10px; 224 padding-left: 10px;
225 } 225 }
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!