8f77dd9a by lttnew

单位缴费校验营业执照

1 parent 4e1f81c6
...@@ -89,7 +89,7 @@ export function fillMemberPhoto(item = {}, fallback = '') { ...@@ -89,7 +89,7 @@ export function fillMemberPhoto(item = {}, fallback = '') {
89 return photo ? fillImgUrl(photo) : fallback 89 return photo ? fillImgUrl(photo) : fallback
90 } 90 }
91 91
92 export function previewAttachment(file, options = {}) { 92 export async function previewAttachment(file, options = {}) {
93 const item = normalizeAttachment(file) 93 const item = normalizeAttachment(file)
94 const rawUrl = item.rawUrl || item.url 94 const rawUrl = item.rawUrl || item.url
95 const previewUrl = getAttachmentPreviewUrl(rawUrl, 0) 95 const previewUrl = getAttachmentPreviewUrl(rawUrl, 0)
...@@ -101,6 +101,14 @@ export function previewAttachment(file, options = {}) { ...@@ -101,6 +101,14 @@ export function previewAttachment(file, options = {}) {
101 return 101 return
102 } 102 }
103 if (isAttachmentImage(item) || isImageUrl(rawUrl) || isImageUrl(previewUrl)) { 103 if (isAttachmentImage(item) || isImageUrl(rawUrl) || isImageUrl(previewUrl)) {
104 const errorMsg = await checkAttachmentError(previewUrl)
105 if (errorMsg) {
106 uni.showToast({
107 title: errorMsg,
108 icon: 'none'
109 })
110 return
111 }
104 uni.previewImage({ 112 uni.previewImage({
105 urls: [previewUrl], 113 urls: [previewUrl],
106 current: previewUrl, 114 current: previewUrl,
...@@ -120,11 +128,7 @@ export function previewAttachment(file, options = {}) { ...@@ -120,11 +128,7 @@ export function previewAttachment(file, options = {}) {
120 }) 128 })
121 return 129 return
122 } 130 }
123 if (getAttachmentExt(item) === 'pdf' && options.preferWebView !== false) { 131 openDocumentAttachment(item, getAttachmentPreviewUrl(rawUrl, 0), false, options)
124 openAttachmentWebView(previewUrl, options.title || '附件预览')
125 return
126 }
127 openDocumentAttachment(item, getAttachmentPreviewUrl(rawUrl, 1), false, options)
128 } 132 }
129 133
130 export function normalizeAttachment(file) { 134 export function normalizeAttachment(file) {
...@@ -163,7 +167,7 @@ export function getAttachmentPreviewUrl(url, downFlag = 0) { ...@@ -163,7 +167,7 @@ export function getAttachmentPreviewUrl(url, downFlag = 0) {
163 const value = String(url).trim() 167 const value = String(url).trim()
164 if (!value || value === 'null' || value === 'undefined') return '' 168 if (!value || value === 'null' || value === 'undefined') return ''
165 if (value.startsWith('msr:')) { 169 if (value.startsWith('msr:')) {
166 return `${trimBaseUrl(config.baseUrl_api)}/fileServer/download?file=${value}&downFlag=${downFlag}` 170 return `${trimBaseUrl(config.baseUrl_api)}/fileServer/download?file=${encodeURIComponent(value)}&downFlag=${downFlag}`
167 } 171 }
168 return fillImgUrl(value) 172 return fillImgUrl(value)
169 } 173 }
...@@ -192,8 +196,6 @@ function openDocumentAttachment(item, url, retried = false, options = {}) { ...@@ -192,8 +196,6 @@ function openDocumentAttachment(item, url, retried = false, options = {}) {
192 uni.hideLoading() 196 uni.hideLoading()
193 if (redirectUrl) { 197 if (redirectUrl) {
194 openDocumentAttachment(item, redirectUrl, true, options) 198 openDocumentAttachment(item, redirectUrl, true, options)
195 } else if (getAttachmentExt(item) === 'pdf') {
196 openAttachmentWebView(getAttachmentPreviewUrl(item.rawUrl || item.url, 0), options.title || '附件预览')
197 } else { 199 } else {
198 uni.showToast({ 200 uni.showToast({
199 title: '文件下载失败', 201 title: '文件下载失败',
...@@ -202,10 +204,7 @@ function openDocumentAttachment(item, url, retried = false, options = {}) { ...@@ -202,10 +204,7 @@ function openDocumentAttachment(item, url, retried = false, options = {}) {
202 } 204 }
203 return 205 return
204 } 206 }
205 uni.showToast({ 207 showAttachmentFailToast(url, '文件下载失败')
206 title: '文件下载失败',
207 icon: 'none'
208 })
209 return 208 return
210 } 209 }
211 uni.openDocument({ 210 uni.openDocument({
...@@ -213,10 +212,6 @@ function openDocumentAttachment(item, url, retried = false, options = {}) { ...@@ -213,10 +212,6 @@ function openDocumentAttachment(item, url, retried = false, options = {}) {
213 fileType: getDocumentFileType(item), 212 fileType: getDocumentFileType(item),
214 showMenu: true, 213 showMenu: true,
215 fail: () => { 214 fail: () => {
216 if (getAttachmentExt(item) === 'pdf') {
217 openAttachmentWebView(getAttachmentPreviewUrl(item.rawUrl || item.url, 0), options.title || '附件预览')
218 return
219 }
220 uni.showToast({ 215 uni.showToast({
221 title: '文件暂不支持预览', 216 title: '文件暂不支持预览',
222 icon: 'none' 217 icon: 'none'
...@@ -225,14 +220,7 @@ function openDocumentAttachment(item, url, retried = false, options = {}) { ...@@ -225,14 +220,7 @@ function openDocumentAttachment(item, url, retried = false, options = {}) {
225 }) 220 })
226 }, 221 },
227 fail: () => { 222 fail: () => {
228 if (getAttachmentExt(item) === 'pdf') { 223 showAttachmentFailToast(url, '文件下载失败')
229 openAttachmentWebView(getAttachmentPreviewUrl(item.rawUrl || item.url, 0), options.title || '附件预览')
230 return
231 }
232 uni.showToast({
233 title: '文件下载失败',
234 icon: 'none'
235 })
236 }, 224 },
237 complete: () => { 225 complete: () => {
238 uni.hideLoading() 226 uni.hideLoading()
...@@ -260,9 +248,64 @@ function openAttachmentWebView(url, title = '附件预览') { ...@@ -260,9 +248,64 @@ function openAttachmentWebView(url, title = '附件预览') {
260 } 248 }
261 249
262 function getAttachmentExt(file) { 250 function getAttachmentExt(file) {
263 const name = `${file?.extname || file?.name || file?.rawUrl || file?.url || ''}` 251 const name = `${file?.extname || file?.name || file?.rawUrl || file?.url || file || ''}`
264 const ext = name.includes('.') ? name.split('.').pop() : name 252 const fileParam = getQueryParam(name, 'file')
265 return ext.split('?')[0].toLowerCase() 253 const cleanName = safeDecodeURIComponent(fileParam || name).split('?')[0].split('#')[0]
254 const fileName = cleanName.split('/').pop() || cleanName
255 const ext = fileName.includes('.') ? fileName.split('.').pop() : fileName
256 return ext.toLowerCase()
257 }
258
259 function checkAttachmentError(url) {
260 if (!isFileDownloadUrl(url)) return Promise.resolve('')
261 return new Promise(resolve => {
262 uni.request({
263 url,
264 method: 'GET',
265 header: {
266 Authorization: uni.getStorageSync('token') || ''
267 },
268 success: res => {
269 const data = parseAttachmentResponse(res.data)
270 if (res.statusCode >= 400 || (data && data.code && data.code !== 200)) {
271 resolve(getAttachmentErrorMsg(data))
272 return
273 }
274 resolve('')
275 },
276 fail: () => resolve('')
277 })
278 })
279 }
280
281 async function showAttachmentFailToast(url, fallback) {
282 const errorMsg = await checkAttachmentError(url)
283 uni.showToast({
284 title: errorMsg || fallback,
285 icon: 'none'
286 })
287 }
288
289 function parseAttachmentResponse(data) {
290 if (!data) return null
291 if (typeof data === 'object') return data
292 if (typeof data === 'string') {
293 try {
294 return JSON.parse(data)
295 } catch (e) {
296 return null
297 }
298 }
299 return null
300 }
301
302 function getAttachmentErrorMsg(data) {
303 const msg = data?.msg || data?.message || ''
304 if (!msg) return '附件预览失败'
305 if (msg.includes('Hostname') || msg.includes('certificate')) {
306 return '附件服务证书异常,请稍后再试'
307 }
308 return msg.length > 40 ? msg.slice(0, 40) : msg
266 } 309 }
267 310
268 function isAttachmentImage(file) { 311 function isAttachmentImage(file) {
...@@ -282,6 +325,16 @@ function getRedirectUrl(header = {}) { ...@@ -282,6 +325,16 @@ function getRedirectUrl(header = {}) {
282 return `${trimBaseUrl(config.baseUrl_api)}/${String(location).replace(/^\/+/, '')}` 325 return `${trimBaseUrl(config.baseUrl_api)}/${String(location).replace(/^\/+/, '')}`
283 } 326 }
284 327
328 function isFileDownloadUrl(url) {
329 const value = String(url || '')
330 return value.includes('/fileServer/download') || value.startsWith('fileServer/download')
331 }
332
333 function getQueryParam(url, key) {
334 const match = String(url || '').match(new RegExp(`[?&]${key}=([^&#]+)`))
335 return match ? safeDecodeURIComponent(match[1]) : ''
336 }
337
285 function isValidUrlValue(value) { 338 function isValidUrlValue(value) {
286 if (value === undefined || value === null) return false 339 if (value === undefined || value === null) return false
287 const url = String(value).trim() 340 const url = String(value).trim()
......
...@@ -266,7 +266,7 @@ function init() { ...@@ -266,7 +266,7 @@ function init() {
266 ...res.data.memberInfo, 266 ...res.data.memberInfo,
267 ...pr.value 267 ...pr.value
268 } 268 }
269 form.value.businessLicenseArr = parseFileList(imageSource.certBusinessLicense || imageSource.businessLicense, '营业执照') 269 form.value.businessLicenseArr = parseFileList(imageSource.businessLicense , '营业执照')
270 form.value.legalIdcPhotoArr = parseImageList(imageSource.certLegalIdcPhoto || imageSource.legalIdcPhoto) 270 form.value.legalIdcPhotoArr = parseImageList(imageSource.certLegalIdcPhoto || imageSource.legalIdcPhoto)
271 form.value.picturesArr = parseImageList(imageSource.certPictures || imageSource.pictures) 271 form.value.picturesArr = parseImageList(imageSource.certPictures || imageSource.pictures)
272 console.log('营业执照', form.value.businessLicenseArr) 272 console.log('营业执照', form.value.businessLicenseArr)
......
...@@ -251,6 +251,7 @@ ...@@ -251,6 +251,7 @@
251 const coordinates1 = ref([]) 251 const coordinates1 = ref([])
252 const pictures = ref() 252 const pictures = ref()
253 const legalIdcPhoto = ref([]) 253 const legalIdcPhoto = ref([])
254 const currentBusinessLicenseAddress = ref('')
254 const carriedReadonlyFields = ['companyName', 'creditCode', 'name', 'address', 'adress', 'parentId', 'legal', 'legalIdcCode'] 255 const carriedReadonlyFields = ['companyName', 'creditCode', 'name', 'address', 'adress', 'parentId', 'legal', 'legalIdcCode']
255 256
256 function isFieldDisabled(field) { 257 function isFieldDisabled(field) {
...@@ -285,6 +286,18 @@ ...@@ -285,6 +286,18 @@
285 ocrLockedFields.value = {} 286 ocrLockedFields.value = {}
286 } 287 }
287 288
289 function clearBusinessLicenseUpload() {
290 selectFileValue = {}
291 form.value.businessLicense = ''
292 currentBusinessLicenseAddress.value = ''
293 }
294
295 function lockParentIdField() {
296 if (hasValue(form.value.parentId)) {
297 ocrLockedFields.value.parentId = true
298 }
299 }
300
288 onLoad(option => { 301 onLoad(option => {
289 if (app.globalData.isLogin) { 302 if (app.globalData.isLogin) {
290 init() 303 init()
...@@ -296,7 +309,10 @@ ...@@ -296,7 +309,10 @@
296 }); 309 });
297 310
298 async function init() { 311 async function init() {
299 getRegionsList() 312 await Promise.all([
313 getRegionsList(),
314 getTree()
315 ])
300 await getForm() 316 await getForm()
301 await canUseDiscountApi() 317 await canUseDiscountApi()
302 await getZtxDiscountPolicyApi() 318 await getZtxDiscountPolicyApi()
...@@ -344,7 +360,6 @@ ...@@ -344,7 +360,6 @@
344 ...res.data.dept, 360 ...res.data.dept,
345 ...res.data.memberInfo 361 ...res.data.memberInfo
346 } 362 }
347 getTree()
348 form.value.deptType = res.data.dept.deptType 363 form.value.deptType = res.data.dept.deptType
349 form.value.parentId = form.value.parentId ?? '' 364 form.value.parentId = form.value.parentId ?? ''
350 // creditCode.value = form.value.creditCode 365 // creditCode.value = form.value.creditCode
...@@ -383,6 +398,8 @@ ...@@ -383,6 +398,8 @@
383 398
384 creditCode.value = form.value.creditCode 399 creditCode.value = form.value.creditCode
385 parentId.value = form.value.parentId 400 parentId.value = form.value.parentId
401 restoreAssoFullName()
402 lockParentIdField()
386 companyName.value = form.value.companyName 403 companyName.value = form.value.companyName
387 legal.value = form.value.legal 404 legal.value = form.value.legal
388 legalIdcCode.value = form.value.legalIdcCode 405 legalIdcCode.value = form.value.legalIdcCode
...@@ -408,7 +425,7 @@ ...@@ -408,7 +425,7 @@
408 } 425 }
409 426
410 function getRegionsList() { 427 function getRegionsList() {
411 api.regionsList().then(res => { 428 return api.regionsList().then(res => {
412 regionsList.value = res.data; 429 regionsList.value = res.data;
413 }); 430 });
414 } 431 }
...@@ -472,6 +489,14 @@ ...@@ -472,6 +489,14 @@
472 }) 489 })
473 return 490 return
474 } 491 }
492 if (currentBusinessLicenseAddress.value && !validateBusinessLicenseProvince(currentBusinessLicenseAddress.value)) {
493 uni.showToast({
494 title: '请上传省内的营业执照',
495 icon: 'none',
496 duration: 3000
497 })
498 return
499 }
475 if (legalIdcPhoto1.value == '' || legalIdcPhoto2.value == '') { 500 if (legalIdcPhoto1.value == '' || legalIdcPhoto2.value == '') {
476 uni.showToast({ 501 uni.showToast({
477 title: '请上传法人身份证', 502 title: '请上传法人身份证',
...@@ -895,55 +920,39 @@ ...@@ -895,55 +920,39 @@
895 return true 920 return true
896 } 921 }
897 922
898 function findAssoPathByRegionNames(regionPath) {
899 if (!regionPath?.length || !tree.value?.length) return null
900 const names = regionPath.map(node => normalizeAddressText(getNodeText(node))).filter(Boolean)
901 const candidates = []
902
903 function walk(listData, path) {
904 for (const item of listData || []) {
905 const itemName = normalizeAddressText(getNodeText(item))
906 const nextPath = [...path, item]
907 const score = names.reduce((total, name, index) => {
908 const shortName = name.replace(/省|市|区|县|自治区|壮族自治区|回族自治区|维吾尔自治区|地区|自治州|盟|旗/g, '')
909 return total + (itemName.includes(name) || (shortName.length > 1 && itemName.includes(shortName)) ? index + 1 : 0)
910 }, 0)
911 if (score > 0) candidates.push({ path: nextPath, score })
912 if (item.children?.length) walk(item.children, nextPath)
913 }
914 }
915
916 walk(tree.value, [])
917 candidates.sort((a, b) => b.score - a.score || b.path.length - a.path.length)
918 return candidates[0]?.path || null
919 }
920
921 function applyAssoPath(path) {
922 if (!path?.length) return false
923 const lastNode = path[path.length - 1]
924 form.value.parentId = getNodeValue(lastNode) || ''
925 assoFullName.value = getAssoFullName(path.map(node => ({ value: getNodeValue(node) })))
926 lockOcrField('parentId', form.value.parentId)
927 return !!form.value.parentId
928 }
929
930 async function applyBusinessAddress(address) { 923 async function applyBusinessAddress(address) {
931 const businessAddress = String(address || '').trim() 924 const businessAddress = String(address || '').trim()
932 if (!businessAddress) return 925 if (!businessAddress) return false
933 form.value.adress = businessAddress 926 form.value.adress = businessAddress
934 lockOcrField('adress', businessAddress) 927 lockOcrField('adress', businessAddress)
935 928
936 if (!regionsList.value?.length) { 929 if (!regionsList.value?.length) {
937 await getRegionsList().catch(() => {}) 930 await getRegionsList().catch(() => {})
938 } 931 }
939 if (!tree.value?.length) { 932 const regionPath = findRegionPathByAddress(businessAddress)
940 await getTree().catch(() => {}) 933 return applyRegionPath(regionPath)
941 } 934 }
935
936 function validateBusinessLicenseProvince(address) {
937 const businessAddress = String(address || '').trim()
938 if (!businessAddress) return true
942 const regionPath = findRegionPathByAddress(businessAddress) 939 const regionPath = findRegionPathByAddress(businessAddress)
943 if (applyRegionPath(regionPath)) { 940 const currentAssoName = assoFullName.value || getAssoName(form.value.parentId)
944 const assoPath = findAssoPathByRegionNames(regionPath) 941 return isSameProvince(regionPath, currentAssoName)
945 applyAssoPath(assoPath) 942 }
943
944 function isSameProvince(regionPath, assoName) {
945 const regionProvince = normalizeProvinceName(getNodeText(regionPath?.[0]))
946 if (!regionProvince) return false
947 const normalizedAssoName = normalizeProvinceName(assoName)
948 return normalizedAssoName && (
949 normalizedAssoName.includes(regionProvince) ||
950 regionProvince.includes(normalizedAssoName)
951 )
946 } 952 }
953
954 function normalizeProvinceName(name) {
955 return normalizeAddressText(name).replace(/省|市|自治区|壮族自治区|回族自治区|维吾尔自治区/g, '')
947 } 956 }
948 957
949 // 恢复协会完整路径名称 958 // 恢复协会完整路径名称
...@@ -1102,7 +1111,18 @@ ...@@ -1102,7 +1111,18 @@
1102 lockOcrField('companyName', form.value.companyName) 1111 lockOcrField('companyName', form.value.companyName)
1103 lockOcrField('creditCode', form.value.creditCode) 1112 lockOcrField('creditCode', form.value.creditCode)
1104 lockOcrField('legal', form.value.legal) 1113 lockOcrField('legal', form.value.legal)
1114 currentBusinessLicenseAddress.value = ocrData.businessAddress || ''
1105 await applyBusinessAddress(ocrData.businessAddress) 1115 await applyBusinessAddress(ocrData.businessAddress)
1116 if (!validateBusinessLicenseProvince(ocrData.businessAddress)) {
1117 clearBusinessLicenseUpload()
1118 uni.hideLoading()
1119 uni.showToast({
1120 title: '请上传省内的营业执照',
1121 icon: 'none',
1122 duration: 3000
1123 })
1124 return
1125 }
1106 await onCreditCodeBlur(false) 1126 await onCreditCodeBlur(false)
1107 } 1127 }
1108 selectFileValue = { 1128 selectFileValue = {
...@@ -1122,9 +1142,9 @@ ...@@ -1122,9 +1142,9 @@
1122 } 1142 }
1123 1143
1124 function delSupplementFile() { 1144 function delSupplementFile() {
1125 selectFileValue = {} 1145 clearBusinessLicenseUpload()
1126 form.value.businessLicense = ''
1127 unlockOcrFields() 1146 unlockOcrFields()
1147 lockParentIdField()
1128 } 1148 }
1129 1149
1130 function getBusinessLicenseOcr(filePath) { 1150 function getBusinessLicenseOcr(filePath) {
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!