From 9e6b0d57c26f98aa70aa1dc1903375b1f556648f Mon Sep 17 00:00:00 2001
From: shinnosuke <tantao@1hoper.com>
Date: 星期一, 24 八月 2026 17:44:53 +0800
Subject: [PATCH] 又又更新
---
rencaika/pages/card/card.uvue | 21 +++--
talent-card-admin/src/views/MerchantCreateView.vue | 105 ++++++++++++++++---------
rencaika_merchant/pages/scan/scan.uvue | 5 +
rencaika_merchant/pages/merchant-onboarding/merchant-onboarding.uvue | 7 +
rencaika_merchant/pages/withdrawal-detail/withdrawal-detail.uvue | 42 ++++++++-
talent-card-admin/src/views/RoleFormView.vue | 3
talent-card-admin/src/types/admin.ts | 1
talent-card-admin/src/views/StaffManagementView.vue | 12 +-
rencaika/pages/talent-code/talent-code.uvue | 10 +
talent-card-admin/src/layouts/AdminLayout.vue | 1
rencaika_merchant/pages/merchant/merchant.uvue | 6 -
11 files changed, 137 insertions(+), 76 deletions(-)
diff --git a/rencaika/pages/card/card.uvue b/rencaika/pages/card/card.uvue
index f8917a4..e8a83d9 100644
--- a/rencaika/pages/card/card.uvue
+++ b/rencaika/pages/card/card.uvue
@@ -48,14 +48,14 @@
<text class="refresh-tip">{{canShowCode ? refreshTip : '请联系服务专员了解卡片状态'}}</text>
</view>
- <view v-if="advisorName != ''" class="service-panel">
+ <view v-if="canShowCode" class="service-panel">
<view class="service-title-row"><view class="title-line"></view><text>{{cardLevel}}专属服务专员</text><view class="title-line"></view></view>
- <text class="service-advisor">{{advisorDepartment}} {{advisorName}}</text>
+ <text class="service-advisor">{{advisorName != '' ? advisorDepartment + ' ' + advisorName : '暂未配置服务专员'}}</text>
<view class="service-actions">
- <view v-if="advisorConsultUrl != ''" class="service-action" hover-class="service-action-active" @tap="onlineConsult">
+ <view class="service-action" hover-class="service-action-active" @tap="onlineConsult">
<image src="/static/card-assets/consult.png"></image><text>在线咨询</text>
</view>
- <view v-if="advisorMobile != ''" class="service-action" hover-class="service-action-active" @tap="callAdvisor">
+ <view class="service-action" hover-class="service-action-active" @tap="callAdvisor">
<image src="/static/card-assets/phone.png"></image><text>拨打电话</text>
</view>
</view>
@@ -75,8 +75,11 @@
<view v-if="showApplyNotice" class="apply-mask" @tap="closeApplyNotice">
<view class="apply-dialog" @tap.stop="preventClose">
<text class="dialog-title">温馨提示</text>
- <text class="dialog-copy">请前往东区政务服务中心(东区大渡口街86号)区人才综合服务专窗线下进行人才认定。</text>
- <text class="dialog-phone">0812-3509008,东区人才综合服务专窗</text>
+ <text class="dialog-copy"> 请前往东区政务服务中心(东区大渡口街86号)线下进行人才认定。</text>
+ <view class="dialog-contact">
+ <text class="dialog-phone">联系电话:0812-3509008</text>
+ <text class="dialog-office">东区人才综合服务专窗</text>
+ </view>
<view class="dialog-confirm" hover-class="dialog-confirm-active" @tap="closeApplyNotice"><text>确定</text></view>
</view>
</view>
@@ -209,7 +212,7 @@
if (!advisorConsultUrl.value.match(/^https:\/\//)) { uni.showToast({ title: '暂未配置在线咨询', icon: 'none' }); return }
uni.navigateTo({ url: '/pages/external-webview/external-webview?source=advisor&talentId=' + encodeURIComponent(talentId.value) })
}
- const callAdvisor = () => { if (advisorMobile.value != '') uni.makePhoneCall({ phoneNumber: advisorMobile.value }) }
+ const callAdvisor = () => { if (advisorMobile.value == '') { uni.showToast({ title: '暂未配置服务专员电话', icon: 'none' }); return }; uni.makePhoneCall({ phoneNumber: advisorMobile.value }) }
const goHome = () => uni.reLaunch({ url: '/pages/index/index' })
const goBenefits = () => uni.reLaunch({ url: '/pages/benefits/benefits' })
const goPolicy = () => uni.reLaunch({ url: '/pages/policy/policy' })
@@ -293,7 +296,9 @@
.apply-dialog { width: 100%; box-sizing: border-box; padding: 59rpx 47rpx 39rpx; border-radius: 32rpx; background-color: #FFFFFF; }
.dialog-title { display: block; color: #386BB0; font-size: 43rpx; line-height: 60rpx; font-weight: 700; text-align: center; }
.dialog-copy { display: block; margin-top: 44rpx; color: #737F91; font-size: 27rpx; line-height: 42rpx; font-weight: 600; }
- .dialog-phone { display: block; margin-top: 16rpx; color: #FF8957; font-size: 27rpx; line-height: 39rpx; font-weight: 700; }
+ .dialog-contact { display: flex; margin-top: 16rpx; flex-direction: column; align-items: flex-end; }
+ .dialog-phone, .dialog-office { display: block; color: #FF8957; font-size: 27rpx; line-height: 39rpx; font-weight: 700; text-align: right; }
+ .dialog-office { margin-top: 4rpx; }
.dialog-confirm { display: flex; width: 200rpx; height: 60rpx; margin: 39rpx auto 0; border-radius: 31rpx; background-image: linear-gradient(90deg, #FF4A32 0%, #FF8A1B 100%); justify-content: center; align-items: center; }
.dialog-confirm text { color: #FFFFFF; font-size: 27rpx; font-weight: 700; }
.dialog-confirm-active { opacity: .78; }
diff --git a/rencaika/pages/talent-code/talent-code.uvue b/rencaika/pages/talent-code/talent-code.uvue
index 5982b8d..7306ed8 100644
--- a/rencaika/pages/talent-code/talent-code.uvue
+++ b/rencaika/pages/talent-code/talent-code.uvue
@@ -132,7 +132,6 @@
stopTimers()
codeLoading.value = true
codeLoadFailed.value = false
- codeImageUrl.value = ''
codeMessage.value = '正在生成动态人才码'
issueTalentDynamicCodeForScene(talentId.value, scene.value, merchantId.value, (data: any) => {
codeLoading.value = false
@@ -141,8 +140,13 @@
codeImageUrl.value = getApiBaseUrl().replace(/\/$/, '') + (data.imagePath as string)
expiresAt.value = Number(data.expiresAt)
setCountdown()
- const seconds = data.refreshAfterSeconds != null ? Number(data.refreshAfterSeconds) : 60
- refreshTimer = setTimeout(() => requestDynamicCode(), Math.max(1, seconds - 2) * 1000)
+ // Refresh only after the displayed code expires so the countdown never jumps back early.
+ const refreshDelay = Math.max(1, expiresAt.value - Date.now())
+ refreshTimer = setTimeout(() => {
+ remainingSeconds.value = 0
+ refreshTip.value = '正在刷新动态人才码'
+ requestDynamicCode()
+ }, refreshDelay)
}, (error) => { if (pageVisible) handleCodeFailure(error.message); else codeLoading.value = false })
}
const handleCodeFailure = (message: string) => { stopTimers(); codeLoading.value = false; codeImageUrl.value = ''; codeLoadFailed.value = true; codeMessage.value = message == '' ? '动态人才码加载失败' : message; refreshTip.value = '动态人才码已失效,请重新获取' }
diff --git a/rencaika_merchant/pages/merchant-onboarding/merchant-onboarding.uvue b/rencaika_merchant/pages/merchant-onboarding/merchant-onboarding.uvue
index 70d1139..3c57d35 100644
--- a/rencaika_merchant/pages/merchant-onboarding/merchant-onboarding.uvue
+++ b/rencaika_merchant/pages/merchant-onboarding/merchant-onboarding.uvue
@@ -18,7 +18,7 @@
<view class="field-block">
<text class="field-label">统一社会信用代码</text>
- <view class="input-shell" :class="invalidField == 'creditCode' ? 'field-invalid' : ''"><input class="text-input" v-model="creditCode" maxlength="18" placeholder="请输入18位统一社会信用代码" placeholder-class="input-placeholder" @input="normalizeCreditCode" /></view>
+ <view class="input-shell" :class="invalidField == 'creditCode' ? 'field-invalid' : ''"><input class="text-input" :value="creditCode" maxlength="18" placeholder="请输入18位统一社会信用代码" placeholder-class="input-placeholder" @input="normalizeCreditCode" /></view>
<text v-if="invalidField == 'creditCode'" class="field-error">{{errorMessage}}</text>
</view>
@@ -160,8 +160,9 @@
}
}
- const normalizeCreditCode = () => {
- creditCode.value = creditCode.value.toUpperCase().replace(/[^0-9A-Z]/g, '')
+ const normalizeCreditCode = (event: any) => {
+ const input = event != null && event.detail != null && event.detail.value != null ? '' + event.detail.value : ''
+ creditCode.value = input.toUpperCase().replace(/[^0-9A-Z]/g, '')
clearFieldError('creditCode')
}
diff --git a/rencaika_merchant/pages/merchant/merchant.uvue b/rencaika_merchant/pages/merchant/merchant.uvue
index 0223318..4d198c3 100644
--- a/rencaika_merchant/pages/merchant/merchant.uvue
+++ b/rencaika_merchant/pages/merchant/merchant.uvue
@@ -19,8 +19,6 @@
</view>
<view class="setting-card">
- <view class="setting-row" @tap="handleMenuAction('结算管理')"><view class="setting-leading"><image class="setting-icon" src="/static/icons/lucide/hand-coins.svg" mode="aspectFit"></image><text class="setting-label">结算管理</text></view><image class="setting-chevron" src="/static/icons/lucide/chevron-right.svg" mode="aspectFit"></image></view>
- <view class="setting-row" @tap="handleMenuAction('商户提现')"><view class="setting-leading"><image class="setting-icon" src="/static/icons/lucide/wallet-cards-gray.svg" mode="aspectFit"></image><text class="setting-label">商户提现</text></view><image class="setting-chevron" src="/static/icons/lucide/chevron-right.svg" mode="aspectFit"></image></view>
<view class="setting-row">
<view class="setting-leading"><image class="setting-icon" src="/static/icons/lucide/store.svg" mode="aspectFit"></image><text class="setting-label">营业状态</text></view>
<view class="business-state" :class="businessUpdating ? 'business-state-disabled' : ''" @tap="toggleBusiness"><text class="business-state-text">{{isBusinessOpen ? '营业中' : '休息中'}}</text><view class="state-switch" :class="isBusinessOpen ? 'open' : ''"><view class="state-thumb"></view></view></view>
@@ -93,10 +91,6 @@
}
if (name === '商户提现') {
uni.navigateTo({ url: '/pages/withdrawal/withdrawal' })
- return
- }
- if (name === '结算管理') {
- uni.navigateTo({ url: '/pages/settlement-management/settlement-management' })
return
}
if (name === '营业时间') {
diff --git a/rencaika_merchant/pages/scan/scan.uvue b/rencaika_merchant/pages/scan/scan.uvue
index c645ed9..26c2009 100644
--- a/rencaika_merchant/pages/scan/scan.uvue
+++ b/rencaika_merchant/pages/scan/scan.uvue
@@ -101,7 +101,10 @@
canRetryVerification.value = false
return
}
- if (result.credentialType == 'TALENT_CODE') {
+ // An order QR must always enter the confirmation page. Keep the order
+ // number as a fallback discriminator for older/incorrect type payloads.
+ const isTalentCode = result.credentialType == 'TALENT_CODE' && result.orderNo.length == 0
+ if (isTalentCode) {
openedManualConsumption = true
uni.navigateTo({ url: '/pages/consume-input/consume-input?verificationId=' + encodeURIComponent(result.verificationId) })
return
diff --git a/rencaika_merchant/pages/withdrawal-detail/withdrawal-detail.uvue b/rencaika_merchant/pages/withdrawal-detail/withdrawal-detail.uvue
index 55dc1a3..530fb0a 100644
--- a/rencaika_merchant/pages/withdrawal-detail/withdrawal-detail.uvue
+++ b/rencaika_merchant/pages/withdrawal-detail/withdrawal-detail.uvue
@@ -1,15 +1,14 @@
<template>
<view class="page">
- <view class="navigation-bar"><view class="back-button" @tap="goBack"><image class="back-icon" src="/static/icons/lucide/back-left.svg" mode="aspectFit"></image></view><text class="page-title">商户提现</text></view>
+ <view class="navigation-bar"><view class="back-button" @tap="goBack"><image class="back-icon" src="/static/icons/lucide/back-left-white.svg" mode="aspectFit"></image></view><text class="page-title">商户提现</text></view>
<scroll-view class="form-scroll" scroll-y="true" :show-scrollbar="false" :enhanced="false">
- <view class="available-row"><text class="available-label">当前可提</text><text class="available-value">¥{{availableText}}</text></view>
<view class="form-card">
+ <view class="available-row"><text class="available-label">当前可提</text><text class="available-value">¥{{availableText}}</text></view>
<view class="field-block">
<view class="field-row amount-field-row">
<text class="field-label">提现金额</text>
<view class="amount-input-shell" :class="error.length > 0 ? 'field-invalid' : ''">
- <text class="amount-prefix">¥</text>
- <input class="amount-input" v-model="amount" type="digit" maxlength="10" placeholder="请输入提现金额" placeholder-class="input-placeholder" @input="clearError" />
+ <input class="amount-input" v-model="amount" type="digit" maxlength="10" placeholder="请输入" placeholder-class="input-placeholder" @input="clearError" />
</view>
</view>
<text v-if="error.length > 0" class="field-error">{{error}}</text>
@@ -17,18 +16,17 @@
<view class="field-block bank-field-block">
<view class="field-row bank-field-row">
<text class="field-label">提现银行卡</text>
- <view class="bank-value">
+ <view v-if="selected != null" class="bank-value">
<view v-if="selected != null" class="selected-bank-copy">
<text class="selected-bank-name">{{selected.bankName}}</text>
<text class="selected-card-number">{{selected.cardMasked}}</text>
</view>
- <text v-else class="bank-placeholder">请选择银行卡</text>
</view>
<view class="select-bank-button" @tap="chooseBank"><text>{{selected == null ? '选择' : '更换'}}</text></view>
</view>
</view>
- <view class="submit-button" :class="submitting ? 'submit-disabled' : ''" @tap="submit"><text>{{submitting ? '提交中' : '发起提现'}}</text></view>
</view>
+ <view class="submit-button" :class="submitting ? 'submit-disabled' : ''" @tap="submit"><text>{{submitting ? '提交中' : '发起提现'}}</text></view>
<view class="safe-space"></view>
</scroll-view>
</view>
@@ -101,4 +99,34 @@
.select-bank-button { width: 240rpx; height: 76rpx; margin: 18rpx 0 0; border-color: #F0D1B9; border-radius: 38rpx; color: #D97643; background-color: #FFF9F4; font-size: 28rpx; }
.submit-button { width: 100%; height: 88rpx; margin: 62rpx 0 0; border-radius: 44rpx; color: #FFFFFF; background-image: linear-gradient(90deg, #FF7625 0%, #FF9630 100%); font-size: 29rpx; line-height: 41rpx; font-weight: 700; box-shadow: 0 12rpx 24rpx rgba(255, 107, 36, 0.20); }
.safe-space { height: 70rpx; }
+
+ /* Keep the withdrawal form aligned with the compact prototype layout. */
+ page { background-color: #FFFFFF; }
+ .page { background-color: #FFFFFF; }
+ .navigation-bar { height: 144rpx; padding: 64rpx 32rpx 0; background-color: #B7B7B7; align-items: center; }
+ .back-button { left: 32rpx; top: 64rpx; width: 64rpx; height: 64rpx; }
+ .back-icon { width: 40rpx; height: 40rpx; }
+ .page-title { color: #FFFFFF; font-size: 30rpx; line-height: 42rpx; }
+ .form-scroll { padding: 34rpx 26rpx 0; background-color: #FFFFFF; }
+ .available-row { display: flex; height: 88rpx; padding: 0; flex-direction: row; justify-content: flex-start; align-items: center; }
+ .available-label, .available-value { color: #777777; font-size: 27rpx; line-height: 38rpx; font-weight: 400; }
+ .available-value { margin-left: 12rpx; }
+ .form-card { padding: 0 20rpx; border-radius: 0; background-color: #FFFFFF; box-shadow: none; }
+ .field-row { min-height: 158rpx; flex-direction: row; align-items: center; }
+ .field-label, .amount-field-row .field-label, .bank-field-row .field-label { width: 142rpx; margin: 0; padding: 0; flex: none; color: #222222; font-size: 28rpx; line-height: 40rpx; font-weight: 400; text-align: left; }
+ .amount-field-row { min-height: 158rpx; flex-direction: row; align-items: center; }
+ .amount-input-shell { width: calc(100% - 142rpx); height: 104rpx; padding: 0 18rpx; flex: none; border: 1rpx solid #D7D7D7; border-radius: 5rpx; background-color: #FFFFFF; }
+ .amount-prefix { color: #999999; font-size: 28rpx; }
+ .amount-input { height: 102rpx; margin-left: 8rpx; color: #333333; font-size: 28rpx; }
+ .input-placeholder { color: #999999; font-size: 28rpx; }
+ .bank-field-block { margin-top: 0; }
+ .bank-field-row { min-height: 158rpx; flex-direction: row; align-items: center; }
+ .bank-value { min-width: 0; margin-right: 12rpx; flex: 1; }
+ .selected-bank-copy { flex-direction: column; }
+ .selected-bank-name { color: #333333; font-size: 26rpx; }
+ .selected-card-number { margin-top: 2rpx; color: #888888; font-size: 23rpx; }
+ .select-bank-button { width: 134rpx; height: 58rpx; padding: 0; margin: 0; border: 0; border-radius: 5rpx; color: #FFFFFF; background-color: #3478FF; font-size: 27rpx; font-weight: 400; }
+ .submit-button { width: calc(100% - 40rpx); height: 80rpx; margin: 70rpx 0 0 20rpx; border-radius: 6rpx; color: #FFFFFF; background-color: #3478FF; background-image: none; font-size: 28rpx; line-height: 40rpx; font-weight: 400; box-shadow: none; }
+ .field-error { margin-left: 142rpx; }
+ .safe-space { height: 70rpx; }
</style>
diff --git a/talent-card-admin/src/layouts/AdminLayout.vue b/talent-card-admin/src/layouts/AdminLayout.vue
index e5e8411..4746c43 100644
--- a/talent-card-admin/src/layouts/AdminLayout.vue
+++ b/talent-card-admin/src/layouts/AdminLayout.vue
@@ -83,7 +83,6 @@
const reservationMenus: MenuItem[] = [
{ path: '/medical-reservations', label: '体检预约管理' },
- { path: '/medical-applications', label: '就医申请管理' },
{ path: '/parking-plates', label: '停车车牌管理' },
{ path: '/fuel-services', label: '加油服务管理' },
{ path: '/spouse-employment', label: '配偶就业管理' },
diff --git a/talent-card-admin/src/types/admin.ts b/talent-card-admin/src/types/admin.ts
index 11d04f8..89dd3bb 100644
--- a/talent-card-admin/src/types/admin.ts
+++ b/talent-card-admin/src/types/admin.ts
@@ -181,6 +181,7 @@
id: number | string
merchantName: string
merchantType?: string
+ merchantTypeCode?: string
contactName?: string
contactMobile?: string
logoUrl?: string
diff --git a/talent-card-admin/src/views/MerchantCreateView.vue b/talent-card-admin/src/views/MerchantCreateView.vue
index 0376b43..4431ecf 100644
--- a/talent-card-admin/src/views/MerchantCreateView.vue
+++ b/talent-card-admin/src/views/MerchantCreateView.vue
@@ -80,35 +80,61 @@
const isEditMode = computed(() => route.query.mode === 'edit' && hasValidMerchantId.value)
const hasExistingMerchant = computed(() => isEditMode.value)
const normalizedMerchantType = computed(() => String(form.merchantType || '').trim())
-const isFoodMerchant = computed(() => normalizedMerchantType.value === '餐饮服务')
-const isApartmentMerchant = computed(() => normalizedMerchantType.value === '公寓租赁')
-const isHotelMerchant = computed(() => normalizedMerchantType.value === '酒店服务')
-const isCarWashMerchant = computed(() => normalizedMerchantType.value === '自助洗车')
-const isHealthCheckMerchant = computed(() => normalizedMerchantType.value === '免费体检')
-const isParkingMerchant = computed(() => normalizedMerchantType.value === '停车服务')
-const isFuelMerchant = computed(() => normalizedMerchantType.value === '加油服务')
-const isChildcareMerchant = computed(() => normalizedMerchantType.value === '子女托管')
-const isFinancialMerchant = computed(() => normalizedMerchantType.value === '金融服务')
+const merchantTypeAliases: Record<string, string> = {
+ '餐饮服务': 'food', food: 'food',
+ '景区服务': 'scenic', scenic: 'scenic',
+ '酒店服务': 'hotel', hotel: 'hotel',
+ '公寓租赁': 'apartment', apartment: 'apartment',
+ '自助洗车': 'carWash', '自助洗车服务': 'carWash', carWash: 'carWash',
+ '免费体检': 'medical', medical: 'medical',
+ '停车服务': 'parking', parking: 'parking',
+ '加油服务': 'fuel', fuel: 'fuel',
+ '子女托管': 'children', children: 'children',
+ '金融服务': 'finance', finance: 'finance',
+ '配偶推荐就业': 'employment', employment: 'employment',
+ '行政审批': 'approval', approval: 'approval',
+ '观影服务': 'cinema', cinema: 'cinema', theatre: 'cinema', '电影院': 'cinema', '影院': 'cinema', '影城': 'cinema', '剧院': 'cinema',
+ '购房优惠': 'housing', housing: 'housing',
+ '购车服务': 'car', car: 'car',
+ '家电服务': 'appliance', appliance: 'appliance',
+ '数码服务': 'digital', digital: 'digital',
+ '文化服务': 'culture', culture: 'culture', book: 'culture',
+ '电信服务': 'telecom', telecom: 'telecom',
+ '口腔治疗保健': 'dental', dental: 'dental',
+}
+const merchantTypeCode = computed(() => {
+ const raw = String(form.merchantTypeCode || normalizedMerchantType.value).trim()
+ return merchantTypeAliases[raw] || raw
+})
+const isFoodMerchant = computed(() => merchantTypeCode.value === 'food')
+const isApartmentMerchant = computed(() => merchantTypeCode.value === 'apartment')
+const isHotelMerchant = computed(() => merchantTypeCode.value === 'hotel')
+const isCarWashMerchant = computed(() => merchantTypeCode.value === 'carWash')
+const isHealthCheckMerchant = computed(() => merchantTypeCode.value === 'medical')
+const isParkingMerchant = computed(() => merchantTypeCode.value === 'parking')
+const isFuelMerchant = computed(() => merchantTypeCode.value === 'fuel')
+const isChildcareMerchant = computed(() => merchantTypeCode.value === 'children')
+const isFinancialMerchant = computed(() => merchantTypeCode.value === 'finance')
const isMovieMerchant = computed(() => [
- '观影服务', 'cinema', 'theatre', '电影院', '影院', '影城', '剧院',
-].includes(normalizedMerchantType.value))
-const isSpouseEmploymentMerchant = computed(() => normalizedMerchantType.value === '配偶推荐就业')
-const isApprovalMerchant = computed(() => normalizedMerchantType.value === '行政审批')
-const isServiceMerchant = computed(() => isFoodMerchant.value || normalizedMerchantType.value === '景区服务')
+ 'cinema',
+].includes(merchantTypeCode.value))
+const isSpouseEmploymentMerchant = computed(() => merchantTypeCode.value === 'employment')
+const isApprovalMerchant = computed(() => merchantTypeCode.value === 'approval')
+const isServiceMerchant = computed(() => isFoodMerchant.value || merchantTypeCode.value === 'scenic')
const supportsStoreConsumption = computed(() => [
- '酒店服务', '景区服务', '餐饮服务', '口腔治疗保健', '免费体检',
-].includes(normalizedMerchantType.value) || (isCarWashMerchant.value && form.miniProgramJumpType === 'normal'))
+ 'hotel', 'scenic', 'food', 'dental', 'medical',
+].includes(merchantTypeCode.value) || (isCarWashMerchant.value && form.miniProgramJumpType === 'normal'))
const merchantAppLoginOptionalTypes = [
- '购房优惠', '购车服务', '家电服务', '数码服务', '文化服务', '电信服务', '口腔治疗保健', '加油服务',
+ 'housing', 'car', 'appliance', 'digital', 'culture', 'telecom', 'dental', 'fuel',
]
const simplifiedMerchantSettingsTypes = [
- '购房优惠', '购车服务', '家电服务', '数码服务', '文化服务', '电信服务', '口腔治疗保健', '加油服务',
+ 'housing', 'car', 'appliance', 'digital', 'culture', 'telecom', 'dental', 'fuel',
]
-const usesSimplifiedMerchantSettings = computed(() => simplifiedMerchantSettingsTypes.includes(normalizedMerchantType.value))
+const usesSimplifiedMerchantSettings = computed(() => simplifiedMerchantSettingsTypes.includes(merchantTypeCode.value))
const settingsAndRightsOnlyMerchantTypes = [
- '加油服务', '购房优惠', '购车服务', '家电服务', '数码服务', '文化服务', '电信服务',
+ 'fuel', 'housing', 'car', 'appliance', 'digital', 'culture', 'telecom',
]
-const usesSettingsAndRightsOnlyTabs = computed(() => settingsAndRightsOnlyMerchantTypes.includes(normalizedMerchantType.value))
+const usesSettingsAndRightsOnlyTabs = computed(() => settingsAndRightsOnlyMerchantTypes.includes(merchantTypeCode.value))
const supportsMerchantAppLogin = computed(() => (
isServiceMerchant.value
|| isApartmentMerchant.value
@@ -121,10 +147,10 @@
|| isMovieMerchant.value
|| isSpouseEmploymentMerchant.value
|| isApprovalMerchant.value
- || merchantAppLoginOptionalTypes.includes(normalizedMerchantType.value)
+ || merchantAppLoginOptionalTypes.includes(merchantTypeCode.value)
))
const requiresMerchantOperator = computed(() => (!isEditMode.value || !merchantHasLoginAccount.value) && (
- normalizedMerchantType.value === '景区服务'
+ merchantTypeCode.value === 'scenic'
|| (supportsMerchantAppLogin.value && Number(form.canLoginMerchantApp) === 1)
))
function carWashJumpMeta() {
@@ -167,7 +193,8 @@
function defaultMerchantRecommend() {
const merchantType = queryString('merchantType')
- return merchantType === '餐饮服务' || merchantType === '景区服务' ? 1 : 0
+ const merchantTypeCode = merchantTypeAliases[merchantType] || merchantType
+ return merchantTypeCode === 'food' || merchantTypeCode === 'scenic' ? 1 : 0
}
function applyNewMerchantDefaults() {
@@ -175,7 +202,9 @@
const merchantType = queryString('merchantType')
form.merchantType = merchantType
- form.recommend = merchantType === '餐饮服务' || merchantType === '景区服务' ? 1 : 0
+ form.merchantTypeCode = ''
+ const merchantTypeCode = merchantTypeAliases[merchantType] || merchantType
+ form.recommend = merchantTypeCode === 'food' || merchantTypeCode === 'scenic' ? 1 : 0
form.sortNo = undefined
}
@@ -227,7 +256,7 @@
]
})
-const form = reactive<MerchantPayload & { createdAt: string }>({
+const form = reactive<MerchantPayload & { createdAt: string; merchantTypeCode?: string }>({
merchantName: '',
merchantType: queryString('merchantType', ''),
contactMobile: '',
@@ -548,18 +577,18 @@
const businessHours = reactive<BusinessHour[]>([{ id: 1, value: [] }])
function defaultMerchantRights(): MerchantRightConfig[] {
- const currentType = queryString('merchantType', '') || normalizedMerchantType.value
- const supportsDefaultStoreConsumption = ['餐饮服务', '景区服务', '口腔治疗保健', '免费体检'].includes(currentType)
- || (currentType === '自助洗车' && form.miniProgramJumpType === 'normal')
- const isHotel = currentType === '酒店服务'
- const isCarWash = currentType === '自助洗车'
- const isHealthCheck = currentType === '免费体检'
- const isParking = currentType === '停车服务'
- const isChildcare = currentType === '子女托管'
- const isFinancial = currentType === '金融服务'
- const isMovie = currentType === '观影服务'
- const isSpouseEmployment = currentType === '配偶推荐就业'
- const isApproval = currentType === '行政审批'
+ const currentType = merchantTypeCode.value
+ const supportsDefaultStoreConsumption = ['food', 'scenic', 'dental', 'medical'].includes(currentType)
+ || (currentType === 'carWash' && form.miniProgramJumpType === 'normal')
+ const isHotel = currentType === 'hotel'
+ const isCarWash = currentType === 'carWash'
+ const isHealthCheck = currentType === 'medical'
+ const isParking = currentType === 'parking'
+ const isChildcare = currentType === 'children'
+ const isFinancial = currentType === 'finance'
+ const isMovie = currentType === 'cinema'
+ const isSpouseEmployment = currentType === 'employment'
+ const isApproval = currentType === 'approval'
if (isHealthCheck) {
return [
diff --git a/talent-card-admin/src/views/RoleFormView.vue b/talent-card-admin/src/views/RoleFormView.vue
index 98981f7..3471b3e 100644
--- a/talent-card-admin/src/views/RoleFormView.vue
+++ b/talent-card-admin/src/views/RoleFormView.vue
@@ -38,11 +38,8 @@
{
name: '预约管理',
pages: [
- { code: 'appointment-management', name: '预约服务管理', actions: ['查看', '审核', '下载'] },
{ code: 'medical-reservations', name: '体检预约管理', actions: ['查看', '审核', '下载'] },
- { code: 'medical-applications', name: '就医申请管理', actions: ['查看', '审核', '下载'] },
{ code: 'parking-plates', name: '停车车牌管理', actions: ['查看', '审核', '下载'] },
- { code: 'car-wash-benefits', name: '洗车权益管理', actions: ['查看', '审核'] },
{ code: 'fuel-services', name: '加油服务管理', actions: ['查看', '审核', '下载'] },
{ code: 'spouse-employment', name: '配偶就业管理', actions: ['查看', '审核', '下载'] },
{ code: 'hotel-reservations', name: '酒店预约管理', actions: ['查看', '审核', '下载'] },
diff --git a/talent-card-admin/src/views/StaffManagementView.vue b/talent-card-admin/src/views/StaffManagementView.vue
index fec4397..e815f9f 100644
--- a/talent-card-admin/src/views/StaffManagementView.vue
+++ b/talent-card-admin/src/views/StaffManagementView.vue
@@ -48,7 +48,7 @@
{ required: true, message: "请输入登录账号", trigger: "blur" },
{
validator: (_rule, value, callback) => {
- if (!editId.value && value && !accountPattern.test(String(value).trim())) {
+ if (value && !accountPattern.test(String(value).trim())) {
callback(new Error("登录账号仅支持英文、数字或英文+数字"));
return;
}
@@ -116,8 +116,8 @@
const keepMobileDigits = () => {
form.mobile = form.mobile.replace(/\D/g, "").slice(0, 11);
};
-const normalizeAccount = () => {
- form.account = form.account.replace(/[^A-Za-z0-9]/g, "").slice(0, 32);
+const normalizeAccount = (value: string) => {
+ form.account = String(value || "").replace(/[^A-Za-z0-9]/g, "").slice(0, 32);
accountTaken.value = false;
};
async function checkAccountAvailable() {
@@ -344,11 +344,11 @@
@input="keepMobileDigits" /></el-form-item
><el-form-item label="登录账号" prop="account" required :error="accountTaken ? '登录账号已存在,请更换' : ''"
><el-input
- v-model="form.account"
+ :model-value="form.account"
:disabled="Boolean(editId)"
maxlength="32"
placeholder="仅支持英文和数字"
- @input="normalizeAccount"
+ @update:model-value="normalizeAccount"
@blur="checkAccountAvailable" /></el-form-item
><el-form-item label="登录密码" prop="password" :required="!editId"
><el-input
@@ -357,7 +357,7 @@
:placeholder="
editId ? '留空则不修改' : '至少 6 位'
" /></el-form-item
- ><el-form-item v-if="!editId || form.password" label="确认密码" prop="confirmPassword" :required="!editId || Boolean(form.password)"
+ ><el-form-item label="确认密码" prop="confirmPassword" :required="!editId || Boolean(form.password)"
><el-input
v-model="form.confirmPassword"
type="password"
--
Gitblit v1.7.1