Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
3cbb8fb6df
11 files changed
+161
-89
No files matched your search
@@ -33,11 +33,11 @@ VITE_OAUTH2_SOCIAL_CLIENT='social:social'
|
||||
# 是否开启websocket 消息接受,
|
||||
VITE_WEBSOCKET_ENABLE = true
|
||||
# --------------------------- start 开发环境 start ----------------------------------
|
||||
VITE_APP_DEV_SERVICE = https://www.zianxin.com/api
|
||||
# VITE_APP_DEV_SERVICE = https://dzc-test-1.fy.takin.cc
|
||||
# VITE_APP_DEV_SERVICE = https://www.zianxin.com/api
|
||||
VITE_APP_DEV_SERVICE = https://dzc-test-1.fy.takin.cc
|
||||
# VITE_APP_DEV_SERVICE = http://127.0.0.1:9999
|
||||
# VITE_APP_DEV_SERVICE = https://www.zianxin.com/api
|
||||
# VITE_APP_DEV_SERVICE = https://dzc-test-1.fy.takin.cc
|
||||
VITE_APP_DEV_SERVICE = https://dzc-test-1.fy.takin.cc
|
||||
#VITE_APP_DEV_SERVICE = http://127.0.0.1:9999
|
||||
|
||||
VITE_IMAGE_DEV_PATH = https://www.zianxin.com/api
|
||||
|
||||
@@ -20,3 +20,8 @@ dist
|
||||
*.sln
|
||||
*.sw?
|
||||
unpackage
|
||||
|
||||
# AI assistant artifacts
|
||||
.video_agent
|
||||
.mimosa
|
||||
.v2c
|
||||
@@ -1,9 +1,6 @@
|
||||
export default {
|
||||
|
||||
mobile: {
|
||||
|
||||
pay: {
|
||||
|
||||
selectWallet: "Select wallet:",
|
||||
|
||||
balance: "Balance:",
|
||||
@@ -297,7 +294,6 @@ export default {
|
||||
duplicateDinerWallet: "Duplicate meal card data for {name}. Contact admin.",
|
||||
|
||||
refundApply: {
|
||||
|
||||
pageTitle: "Request refund",
|
||||
|
||||
loadFail: "Failed to load refund info",
|
||||
@@ -417,11 +413,9 @@ export default {
|
||||
increaseQtyAria: "Increase refund qty for {productName}",
|
||||
|
||||
qtyAria: "{productName} refund qty {count}",
|
||||
|
||||
},
|
||||
|
||||
refundHistory: {
|
||||
|
||||
pageTitle: "Refund progress",
|
||||
|
||||
loadFail: "Failed to load refund progress",
|
||||
@@ -467,7 +461,6 @@ export default {
|
||||
statusUpdated: "Refund status updated",
|
||||
|
||||
status: {
|
||||
|
||||
pendingReview: { title: "Refund under review", desc: "Merchant is processing. See updates below.", label: "Reviewing" },
|
||||
|
||||
completed: { title: "Refund completed", desc: "Confirmed. Arrival per payment channel.", label: "Completed" },
|
||||
@@ -477,24 +470,16 @@ export default {
|
||||
rejected: { title: "Refund rejected", desc: "Not approved. See records below.", label: "Rejected" },
|
||||
|
||||
updated: { title: "Progress updated", desc: "Status reflects latest server records", label: "Updated" },
|
||||
|
||||
},
|
||||
|
||||
auto: {
|
||||
|
||||
completed: { title: "Refund completed", desc: "Auto refund done. Check meal card balance.", label: "Completed" },
|
||||
|
||||
waitRetry: { title: "Waiting for auto refund", desc: "Will retry automatically. No resubmit needed.", label: "Retry pending" },
|
||||
|
||||
processing: { title: "Auto refund in progress", desc: "Processing without merchant review.", label: "Auto processing" },
|
||||
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -2,8 +2,8 @@
|
||||
"name" : "资安信",
|
||||
"appid" : "__UNI__1BFE88F",
|
||||
"description" : "资安信后勤管理系统",
|
||||
"versionName" : "1.5.33",
|
||||
"versionCode" : 1533,
|
||||
"versionName" : "1.5.36",
|
||||
"versionCode" : 1536,
|
||||
"transformPx" : false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
|
||||
@@ -75,6 +75,7 @@ import { useI18n } from "vue-i18n"
|
||||
import dayjs from "dayjs"
|
||||
|
||||
import { orderApi } from "@@/api"
|
||||
import { hooks } from "@@/index"
|
||||
|
||||
import ServiceText from "@@/components/common/service-text.vue"
|
||||
|
||||
@@ -129,9 +130,10 @@ const getOptionId = (option: ApptOption) => option.reserveMode === WEEKLY_CYCLE
|
||||
? `cycle:${option.apptRuleId ?? ""}:${option.hourType ?? ""}`
|
||||
: `appt:${option.id ?? ""}`
|
||||
|
||||
const getOptionTitle = (option: ApptOption) => option.reserveMode === WEEKLY_CYCLE
|
||||
? option.hourTypeName || option.title || t("mobile.tableReservation.mealDefault")
|
||||
: option.title || option.hourTypeName || t("mobile.tableReservation.mealDefault")
|
||||
/** 已知餐段按当前语言展示,未知协议值保留服务端标题以兼容自定义餐段。 */
|
||||
const getOptionTitle = (option: ApptOption) => hooks.useEnum("hardHourTypeEnum", option.hourType)
|
||||
|| (option.reserveMode === WEEKLY_CYCLE ? option.hourTypeName || option.title : option.title || option.hourTypeName)
|
||||
|| t("mobile.tableReservation.mealDefault")
|
||||
|
||||
const formatMonthDay = (value: string) => dayjs(value).format("MM/DD")
|
||||
|
||||
|
||||
@@ -98,8 +98,8 @@
|
||||
t('mobile.dailyMenu.bookedEmpty') }}
|
||||
</view>
|
||||
<view v-else class="mt-2rpx text-20rpx color-#667085 show-line">
|
||||
{{ formatReservationDate(bookedMenus[0]?.apptUseDate) }} · {{ bookedMenus[0]?.apptTitle ||
|
||||
t('mobile.dailyMenu.mealSlot') }}
|
||||
{{ formatReservationDate(bookedMenus[0]?.apptUseDate) }} · {{
|
||||
resolveMealTitle(bookedMenus[0]) }}
|
||||
·
|
||||
{{ bookedFoodSummary(bookedMenus[0]) }}
|
||||
</view>
|
||||
@@ -118,8 +118,7 @@
|
||||
<view class="flex items-center gap-8rpx">
|
||||
<text class="sub-text-23">{{ formatReservationDate(reservation.apptUseDate) }}</text>
|
||||
<text class="meal-tag show-line">
|
||||
{{ hooks.useEnum("hardHourTypeEnum", reservation.hourType) ||
|
||||
t("mobile.dailyMenu.mealSlot") }}
|
||||
{{ resolveMealTitle(reservation) }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="mt-4rpx text-20rpx color-#667085 show-line">
|
||||
@@ -498,12 +497,31 @@ const bookedMenus = computed(() =>
|
||||
*/
|
||||
const resolveDailyMenuCartUserId = () => String(userStore.userId || userStore.userInfo?.userId || "")
|
||||
|
||||
/**
|
||||
* 清理预约日期严格早于当前本地自然日的购物车草稿。
|
||||
* 页面引用的是 Pinia Store 内的持久化对象,逐项删除会同步更新统一缓存;日期缺失或无效时保留原数据,避免误删。
|
||||
*/
|
||||
const removeExpiredDrafts = () => {
|
||||
const today = dayjs().startOf("day")
|
||||
Object.entries(state.draftMap).forEach(([draftKey, draft]) => {
|
||||
const apptDate = dayjs(draft?.apptDate)
|
||||
if (apptDate.isValid() && apptDate.startOf("day").isBefore(today)) {
|
||||
delete state.draftMap[draftKey]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/** 使用日期和餐段生成仅供页面草稿索引的稳定键。 */
|
||||
const createDraftKey = (apptDate: string, hourType: string | number) =>
|
||||
apptDate && String(hourType) ? `${apptDate}::${String(hourType)}` : ""
|
||||
|
||||
/** 解析预约选项的餐段名称,优先使用服务端展示文案。 */
|
||||
const resolveMealTitle = (apptObj: any) => apptObj?.hourTypeName || apptObj?.title || t("mobile.dailyMenu.mealSlot")
|
||||
/** 已知餐段按当前语言展示,未知协议值保留服务端标题以兼容自定义餐段和历史订单。 */
|
||||
const resolveMealTitle = (apptObj: any) => hooks.useEnum("hardHourTypeEnum", apptObj?.hourType)
|
||||
|| apptObj?.hourTypeName
|
||||
|| apptObj?.title
|
||||
|| apptObj?.apptTitle
|
||||
|| apptObj?.mealTitle
|
||||
|| t("mobile.dailyMenu.mealSlot")
|
||||
|
||||
/** 将预约日期格式化为适合移动端阅读的日期和星期。 */
|
||||
const formatReservationDate = (value?: string) => {
|
||||
@@ -611,7 +629,7 @@ const removeDraftGroup = (draftKey: string) => {
|
||||
title: t("mobile.dailyMenu.modal.removeMealTitle"),
|
||||
content: t("mobile.dailyMenu.modal.removeMealContent", {
|
||||
date: formatReservationDate(draft.apptDate),
|
||||
meal: draft.mealTitle,
|
||||
meal: resolveMealTitle(draft),
|
||||
}),
|
||||
confirmColor: "#d92d20",
|
||||
success: (result) => {
|
||||
@@ -778,7 +796,7 @@ const formatDraftFoodSelection = (draft: ReservationDraft, item: DailyMenuItem)
|
||||
const foodName = String(item.name || "").trim() || t("mobile.dailyMenu.reconcile.foodIdFallback", {
|
||||
id: String(item.spuId || item.id || t("mobile.dailyMenu.reconcile.unknownId")),
|
||||
})
|
||||
return `${formatReservationDate(draft.apptDate)} ${draft.mealTitle}:${foodName}`
|
||||
return `${formatReservationDate(draft.apptDate)} ${resolveMealTitle(draft)}:${foodName}`
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -947,7 +965,7 @@ const showSameMealReservationConflict = (conflicts: ReturnType<typeof findSameMe
|
||||
const summaries = conflicts
|
||||
.slice(0, 2)
|
||||
.map(({ draft, dinerUserIds }) =>
|
||||
`${formatReservationDate(draft.apptDate)} ${draft.mealTitle}${t("mobile.dailyMenu.modal.dupPeople", { count: dinerUserIds.length })}`,
|
||||
`${formatReservationDate(draft.apptDate)} ${resolveMealTitle(draft)}${t("mobile.dailyMenu.modal.dupPeople", { count: dinerUserIds.length })}`,
|
||||
)
|
||||
const remainingCount = Math.max(conflicts.length - summaries.length, 0)
|
||||
viewState.bookedMenusExpanded = true
|
||||
@@ -1118,7 +1136,7 @@ const submitDrafts = async () => {
|
||||
uni.showToast({
|
||||
title: t("mobile.dailyMenu.toast.singleMealOnly", {
|
||||
date: formatReservationDate(invalidDraft.apptDate),
|
||||
meal: invalidDraft.mealTitle,
|
||||
meal: resolveMealTitle(invalidDraft),
|
||||
}),
|
||||
icon: "none",
|
||||
})
|
||||
@@ -1163,8 +1181,9 @@ onLoad((options: any) => {
|
||||
state.draftMap = dailyMenuCartStore.getOrCreateDraftMap(resolveDailyMenuCartUserId(), state.merchantId)
|
||||
})
|
||||
|
||||
/** 页面每次显示时刷新商户配置和已预订菜谱。 */
|
||||
/** 页面每次显示时先清理过期购物车,再刷新商户配置和已预订菜谱。 */
|
||||
onShow(async () => {
|
||||
removeExpiredDrafts()
|
||||
await loadMch()
|
||||
await loadBookedMenus()
|
||||
})
|
||||
|
||||
@@ -26,9 +26,11 @@
|
||||
<tm-icon name="error-warning-line" :size="42" color="#d97706" />
|
||||
</view>
|
||||
<view class="sub-text-28 font-700">{{ t('mobile.pay.refundApply.loadFail') }}</view>
|
||||
<view class="mt-8rpx text-22rpx leading-36rpx color-#667085">{{ t('mobile.pay.refundApply.loadFailHint') }}</view>
|
||||
<view class="mt-8rpx text-22rpx leading-36rpx color-#667085">{{ t('mobile.pay.refundApply.loadFailHint')
|
||||
}}</view>
|
||||
<view class="retry-button mt-24rpx" hover-class="tap-feedback" role="button" tabindex="0"
|
||||
:aria-label="t('mobile.pay.refundApply.reloadAria')" @tap="loadPage">{{ t('mobile.pay.reload') }}</view>
|
||||
:aria-label="t('mobile.pay.refundApply.reloadAria')" @tap="loadPage">{{ t('mobile.pay.reload') }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<template v-else-if="refundDetail">
|
||||
@@ -38,16 +40,18 @@
|
||||
<view class="panel-head">
|
||||
<view>
|
||||
<view class="main-text-28">{{ t('mobile.pay.refundApply.selectProducts') }}</view>
|
||||
<view class="mt-3rpx text-20rpx color-#667085">{{ t('mobile.pay.refundApply.selectProductsHint') }}</view>
|
||||
<view class="mt-3rpx text-20rpx color-#667085">{{
|
||||
t('mobile.pay.refundApply.selectProductsHint') }}</view>
|
||||
</view>
|
||||
<view v-if="canEditForm" class="all-refund-action"
|
||||
:class="{ 'all-refund-action--active': allRemainingSelected }"
|
||||
:hover-class="allRemainingSelected ? 'none' : 'tap-feedback'" role="button"
|
||||
:tabindex="allRemainingSelected ? -1 : 0" :aria-disabled="allRemainingSelected"
|
||||
:tabindex="allRemainingSelected ? -1 : 0" :aria-disabled="allRemainingSelected"
|
||||
:aria-label="t('mobile.pay.refundApply.selectAllAria')" @tap="selectAllRemaining">
|
||||
<tm-icon :name="allRemainingSelected ? 'checkbox-circle-line' : 'check-double-line'"
|
||||
:size="24" color="#0094ff" />
|
||||
<text class="ml-5rpx">{{ allRemainingSelected ? t('mobile.pay.refundApply.allSelected') : t('mobile.pay.refundApply.selectAll') }}</text>
|
||||
<text class="ml-5rpx">{{ allRemainingSelected ? t('mobile.pay.refundApply.allSelected') :
|
||||
t('mobile.pay.refundApply.selectAll') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -56,7 +60,8 @@
|
||||
<tm-icon name="shopping-bag-3-line" :size="42" color="#667085" />
|
||||
</view>
|
||||
<view class="sub-text-28 font-700">{{ t('mobile.pay.refundApply.noRefundableProducts') }}</view>
|
||||
<view class="mt-8rpx text-22rpx color-#667085">{{ t('mobile.pay.refundApply.contactMerchant') }}</view>
|
||||
<view class="mt-8rpx text-22rpx color-#667085">{{ t('mobile.pay.refundApply.contactMerchant') }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-else class="product-list">
|
||||
@@ -72,26 +77,36 @@
|
||||
<text class="text-19rpx font-700">¥</text>
|
||||
<text class="ml-2rpx text-28rpx font-800">{{ money(product.productPrice)
|
||||
}}</text>
|
||||
<text class="ml-4rpx text-19rpx color-#667085">{{ t('mobile.pay.refundApply.perUnit') }}</text>
|
||||
<text class="ml-4rpx text-19rpx color-#667085">{{
|
||||
t('mobile.pay.refundApply.perUnit') }}</text>
|
||||
</view>
|
||||
<view v-if="product.onlineRefundSupported"
|
||||
class="mt-5rpx flex flex-wrap items-center gap-x-12rpx gap-y-3rpx text-19rpx color-#667085">
|
||||
<text>{{ t('mobile.pay.refundApply.purchased', { count: product.originalCount }) }}</text>
|
||||
<text>{{ t('mobile.pay.refundApply.refunded', { count: product.refundedCount }) }}</text>
|
||||
<text class="font-700 color-#0094ff">{{ t('mobile.pay.refundApply.remaining', { count: product.refundableCount }) }}</text>
|
||||
<text>{{ t('mobile.pay.refundApply.purchased', { count: product.originalCount })
|
||||
}}</text>
|
||||
<text>{{ t('mobile.pay.refundApply.refunded', { count: product.refundedCount })
|
||||
}}</text>
|
||||
<text class="font-700 color-#0094ff">{{ t('mobile.pay.refundApply.remaining', {
|
||||
count: product.refundableCount
|
||||
}) }}</text>
|
||||
</view>
|
||||
<view v-else class="weighted-tag mt-9rpx">{{ t('mobile.pay.refundApply.weightedProduct') }}</view>
|
||||
<view v-else class="weighted-tag mt-9rpx">{{
|
||||
t('mobile.pay.refundApply.weightedProduct') }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="product.onlineRefundSupported" class="product-control">
|
||||
<view class="min-w-0 flex-1 pr-10rpx">
|
||||
<view v-if="product.selectedCount > 0" class="text-21rpx font-700 color-#e5484d">
|
||||
{{ t('mobile.pay.refundApply.estimatedRefund', { amount: money(estimateProductRefund(product)) }) }}
|
||||
{{ t('mobile.pay.refundApply.estimatedRefund', {
|
||||
amount:
|
||||
money(estimateProductRefund(product))
|
||||
}) }}
|
||||
</view>
|
||||
<view v-else-if="product.refundableCount > 0" class="text-20rpx color-#667085">
|
||||
{{ t('mobile.pay.refundApply.selectRefundQty') }}</view>
|
||||
<view v-else class="text-20rpx color-#98a2b3">{{ t('mobile.pay.refundApply.noRefundableQty') }}</view>
|
||||
<view v-else class="text-20rpx color-#98a2b3">{{
|
||||
t('mobile.pay.refundApply.noRefundableQty') }}</view>
|
||||
</view>
|
||||
<view class="quantity-control"
|
||||
:aria-label="t('mobile.pay.refundApply.qtyAria', { productName: product.productName, count: product.selectedCount })">
|
||||
@@ -134,7 +149,8 @@
|
||||
<tm-icon name="scales-3-line" :size="42" color="#b54708" />
|
||||
</view>
|
||||
<view class="sub-text-28 font-700">{{ t('mobile.pay.refundApply.weightedOnly') }}</view>
|
||||
<view class="mt-8rpx text-center text-22rpx leading-36rpx color-#667085">{{ t('mobile.pay.refundApply.weightedOnlyHint') }}
|
||||
<view class="mt-8rpx text-center text-22rpx leading-36rpx color-#667085">{{
|
||||
t('mobile.pay.refundApply.weightedOnlyHint') }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -151,9 +167,11 @@
|
||||
v-model:model-str="applyForm.reasonText" :list="reasonOptions">
|
||||
<view class="form-row" hover-class="row-tap-feedback" role="button" tabindex="0"
|
||||
:aria-label="t('mobile.pay.refundApply.selectReasonAria')">
|
||||
<view class="form-label"><text class="required-mark">*</text>{{ t('mobile.pay.refundApply.refundReason') }}</view>
|
||||
<view class="form-label"><text class="required-mark">*</text>{{
|
||||
t('mobile.pay.refundApply.refundReason') }}</view>
|
||||
<view class="flex min-w-0 flex-1 items-center justify-end text-23rpx color-#475467">
|
||||
<text class="show-line">{{ applyForm.reasonText || t('mobile.pay.refundApply.selectPlaceholder') }}</text>
|
||||
<text class="show-line">{{ applyForm.reasonText ||
|
||||
t('mobile.pay.refundApply.selectPlaceholder') }}</text>
|
||||
<tm-icon class="ml-6rpx flex-shrink-0" name="arrow-right-s-line" :size="27"
|
||||
color="#98a2b3" />
|
||||
</view>
|
||||
@@ -164,11 +182,13 @@
|
||||
<view class="mt-12rpx refund-panel p-24rpx">
|
||||
<view class="flex items-center justify-between">
|
||||
<view class="main-text-26">{{ t('mobile.pay.refundApply.proofTitle') }}</view>
|
||||
<view class="text-20rpx color-#667085">{{ t('mobile.pay.refundApply.proofOptional') }}</view>
|
||||
<view class="text-20rpx color-#667085">{{ t('mobile.pay.refundApply.proofOptional') }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="mt-18rpx">
|
||||
<tm-upload-photo v-model="uploadFiles" :maxFileSize="1024 * 1024 * 5" :url="uploadActionUrl"
|
||||
:header="uploadHeader" :maxCount="6" :column="4" img-height="142" :permissionFeature="t('mobile.pay.refundApply.proofPermission')" />
|
||||
:header="uploadHeader" :maxCount="6" :column="4" img-height="142"
|
||||
:permissionFeature="t('mobile.pay.refundApply.proofPermission')" />
|
||||
</view>
|
||||
<view class="mt-16rpx flex items-start text-20rpx leading-32rpx color-#667085">
|
||||
<tm-icon name="information-line" :size="22" color="#667085" />
|
||||
@@ -198,20 +218,25 @@
|
||||
<view v-if="refundDetail && !requestState.failed" class="refund-submit-bar">
|
||||
<view class="min-w-0 flex-1">
|
||||
<view class="flex items-baseline gap-6rpx">
|
||||
<text class="text-20rpx color-#667085">{{ t('mobile.pay.refundApply.estimatedRefundLabel') }}</text>
|
||||
<text class="text-20rpx color-#667085">{{ t('mobile.pay.refundApply.estimatedRefundLabel')
|
||||
}}</text>
|
||||
<text class="text-25rpx font-800 color-#e5484d">¥</text>
|
||||
<text class="text-34rpx font-800 color-#e5484d refund-number">{{ money(selectedRefundPrice)
|
||||
}}</text>
|
||||
</view>
|
||||
<view class="mt-2rpx show-line text-20rpx color-#667085">
|
||||
{{ selectedProductCount > 0 ? t('mobile.pay.refundApply.selectedSummary', { productCount: selectedProductCount, unitCount: selectedUnitCount }) :
|
||||
{{ selectedProductCount > 0 ? t('mobile.pay.refundApply.selectedSummary', {
|
||||
productCount:
|
||||
selectedProductCount, unitCount: selectedUnitCount
|
||||
}) :
|
||||
submitHint }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="submit-button" :class="{ 'submit-button--disabled': submitDisabled }"
|
||||
:hover-class="submitDisabled ? 'none' : 'tap-feedback'" role="button"
|
||||
:tabindex="submitDisabled ? -1 : 0" :aria-disabled="submitDisabled" :aria-label="t('mobile.pay.refundApply.submitAria')"
|
||||
@tap="!submitDisabled && submitRefund()">{{ submitButtonText }}</view>
|
||||
:tabindex="submitDisabled ? -1 : 0" :aria-disabled="submitDisabled"
|
||||
:aria-label="t('mobile.pay.refundApply.submitAria')" @tap="!submitDisabled && submitRefund()">{{
|
||||
submitButtonText }}</view>
|
||||
</view>
|
||||
</template>
|
||||
</crud-layout>
|
||||
@@ -536,6 +561,7 @@ function confirmSubmit(): Promise<boolean> {
|
||||
amount: money(selectedRefundPrice.value),
|
||||
processingText,
|
||||
}),
|
||||
cancelText: t('common.cancel'),
|
||||
confirmText: t('mobile.pay.refundApply.confirmSubmit'),
|
||||
confirmColor: "#0094ff",
|
||||
success: (result) => resolve(Boolean(result.confirm)),
|
||||
@@ -827,7 +853,7 @@ async function submitRefund() {
|
||||
|
||||
.submit-button {
|
||||
display: flex;
|
||||
min-width: 184rpx;
|
||||
min-width: 220rpx;
|
||||
height: 88rpx;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
|
||||
@@ -144,17 +144,31 @@ const doTab = (e: any) => {
|
||||
<view class="flex-row items-center justify-between card p-x-20rpx p-y-30rpx m-b-20rpx"
|
||||
v-for="(v, i) in pageHook.list" :key="i">
|
||||
<view class="flex">
|
||||
<view class="w-200rpx flex justify-left p-r-25rpx">
|
||||
<tm-tag v-if="v.title == '更新余额'" size="m">{{ t('mobile.wallet.txUpdateBalance') }}</tm-tag>
|
||||
<tm-tag v-if="v.title == '批量更新余额'" size="m">{{ t('mobile.wallet.txBatchUpdateBalance') }}</tm-tag>
|
||||
<tm-tag v-if="v.title == '充值'" size="m">{{ t('mobile.wallet.txRecharge') }}</tm-tag>
|
||||
<tm-tag v-if="v.title == '支付'" color="error" size="m">{{ t('mobile.wallet.txPay') }}</tm-tag>
|
||||
<tm-tag v-if="v.title == '退款'" color="info" size="m">{{ t('mobile.wallet.txRefund') }}</tm-tag>
|
||||
<tm-tag v-if="v.title == '转账'" color="success" size="m">{{ t('mobile.wallet.txTransfer') }}</tm-tag>
|
||||
<tm-tag v-if="v.title == '转账退款'" color="info" size="m">{{ t('mobile.wallet.txTransferRefund') }}</tm-tag>
|
||||
<view class="w-260rpx flex justify-left p-r-25rpx">
|
||||
<tm-tag v-if="v.title == '更新余额'" size="xs">{{ t('mobile.wallet.txUpdateBalance') }}</tm-tag>
|
||||
<tm-tag v-if="v.title == '批量更新余额'" size="xs">
|
||||
{{ t('mobile.wallet.txBatchUpdateBalance') }}
|
||||
</tm-tag>
|
||||
<tm-tag v-if="v.title == '充值'" size="xs">
|
||||
{{ t('mobile.wallet.txRecharge') }}
|
||||
</tm-tag>
|
||||
<tm-tag v-if="v.title == '支付'" color="error" size="xs">
|
||||
{{ t('mobile.wallet.txPay') }}
|
||||
</tm-tag>
|
||||
<tm-tag v-if="v.title == '退款'" color="info" size="xs">
|
||||
{{ t('mobile.wallet.txRefund') }}
|
||||
</tm-tag>
|
||||
<tm-tag v-if="v.title == '转账'" color="success" size="xs">
|
||||
{{ t('mobile.wallet.txTransfer') }}
|
||||
</tm-tag>
|
||||
<tm-tag v-if="v.title == '转账退款'" color="info" size="xs">
|
||||
{{ t('mobile.wallet.txTransferRefund') }}
|
||||
</tm-tag>
|
||||
</view>
|
||||
<view class="flex-row-center">
|
||||
<text class="sub-text-30">{{ hooks.useMoney(v.price) }}{{ t('mobile.wallet.currencyUnit') }}</text>
|
||||
<text class="sub-text-30">
|
||||
{{ hooks.useMoney(v.price) }}{{ t('mobile.wallet.currencyUnit') }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="sub-text-24 text-right">
|
||||
|
||||
+24
-16
@@ -41,7 +41,7 @@ onLoad(() => { })
|
||||
onShow(async () => {
|
||||
const isLogin = await hooks.useCheckLogin()
|
||||
if (!isLogin) return
|
||||
await userStore._getUserZsMch()
|
||||
await userStore._getUserZsMch()
|
||||
if (pageRef.value) {
|
||||
pageRef.value.reload(false)
|
||||
}
|
||||
@@ -151,7 +151,7 @@ const doTransferMoney = (v: any) => {
|
||||
* 后端返回的 identityTypes 是钱包所属用户身份,不能使用当前登录用户身份替代。
|
||||
*/
|
||||
const canRecharge = (wallet: any) => wallet?.walletTypeUniqueCode == 1
|
||||
&& userStore.isTopUpIdentityAllowed(wallet?.identityTypes)
|
||||
&& userStore.isTopUpIdentityAllowed(wallet?.identityTypes)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -165,7 +165,8 @@ const canRecharge = (wallet: any) => wallet?.walletTypeUniqueCode == 1
|
||||
<view class="flex-col">
|
||||
<view class="flex-row items-center justify-between">
|
||||
<view class="flex-row-center">
|
||||
<text v-if="v.cardNumber" class="second-text-28">{{ t('mobile.wallet.cardNumber') }} {{ v.cardNumber }}</text>
|
||||
<text v-if="v.cardNumber" class="second-text-28">{{ t('mobile.wallet.cardNumber') }} {{
|
||||
v.cardNumber }}</text>
|
||||
</view>
|
||||
<view class="second-text-50">
|
||||
<text v-if="v.cardNumber" class="iconfont icon-fuzhi"
|
||||
@@ -184,8 +185,10 @@ const canRecharge = (wallet: any) => wallet?.walletTypeUniqueCode == 1
|
||||
</text>
|
||||
</view>
|
||||
<view v-if="v.cardNumber">
|
||||
<tm-tag v-if="v.isFreeze == 0" size="s" color="success">{{ t('mobile.wallet.statusNormal') }}</tm-tag>
|
||||
<tm-tag v-if="v.isFreeze == 1" size="s" color="error">{{ t('mobile.wallet.statusFrozen') }}</tm-tag>
|
||||
<tm-tag v-if="v.isFreeze == 0" size="s" color="success">{{ t('mobile.wallet.statusNormal')
|
||||
}}</tm-tag>
|
||||
<tm-tag v-if="v.isFreeze == 1" size="s" color="error">{{ t('mobile.wallet.statusFrozen')
|
||||
}}</tm-tag>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-row items-center justify-between m-t-10rpx">
|
||||
@@ -193,7 +196,8 @@ const canRecharge = (wallet: any) => wallet?.walletTypeUniqueCode == 1
|
||||
</view>
|
||||
<view class="flex-row items-center justify-end space-x-20rpx m-t-10rpx">
|
||||
<!-- <view v-if="v.walletTypeUniqueCode == 1 && !v.cardNumber" class="botder_btn" @tap.stop="openBindDialog(v)">{{ t('mobile.wallet.bind') }}</view> -->
|
||||
<view v-if="v.isRule == '1'" class="botder_btn" @tap.stop="doTransferMoney(v)">{{ t('mobile.wallet.transfer') }}</view>
|
||||
<view v-if="v.isRule == '1'" class="botder_btn" @tap.stop="doTransferMoney(v)">{{
|
||||
t('mobile.wallet.transfer') }}</view>
|
||||
<view v-if="v.walletTypeUniqueCode == 1 && v.cardNumber && v.isFreeze != 1" class="botder_btn"
|
||||
@tap.stop="openFreezeDialog(v)">
|
||||
{{ t('mobile.wallet.applyFreeze') }}
|
||||
@@ -210,30 +214,34 @@ const canRecharge = (wallet: any) => wallet?.walletTypeUniqueCode == 1
|
||||
</z-paging>
|
||||
</crud-layout>
|
||||
|
||||
<tm-drawer z-index="100" v-model:show="state.showBindDialog" :overlayClick="false" :title="t('mobile.wallet.bindMealCard')" :show-close="true"
|
||||
position="bottom" size="40%">
|
||||
<tm-drawer z-index="100" v-model:show="state.showBindDialog" :overlayClick="false"
|
||||
:title="t('mobile.wallet.bindMealCard')" :show-close="true" position="bottom" size="40%">
|
||||
<view class="h-50rpx" />
|
||||
<tm-form ref="bindFormRef" v-model="bindForm" :rules="bindFormRules">
|
||||
<tm-form-item name="cardNumber" :showLabel="false" :showBottom="false">
|
||||
<tm-input v-model="bindForm.cardNumber" showClear :placeholder="t('mobile.wallet.cardNumberPlaceholder')" />
|
||||
<tm-input v-model="bindForm.cardNumber" showClear
|
||||
:placeholder="t('mobile.wallet.cardNumberPlaceholder')" />
|
||||
</tm-form-item>
|
||||
</tm-form>
|
||||
<view class="h-50rpx" />
|
||||
<view class="bg-#0094ff p-y-20rpx text-center rounded-40rpx sub-text-30 color-white!" @tap="doBind">{{ t('mobile.wallet.bind') }}</view>
|
||||
<view class="bg-#0094ff p-y-20rpx text-center rounded-40rpx sub-text-30 color-white!" @tap="doBind">{{
|
||||
t('mobile.wallet.bind') }}</view>
|
||||
</tm-drawer>
|
||||
<tm-drawer z-index="100" v-model:show="state.showFreezeDialog" :overlayClick="true" :title="t('mobile.wallet.applyFreezeTitle')" :show-close="true"
|
||||
position="bottom" size="40%">
|
||||
<tm-drawer z-index="100" v-model:show="state.showFreezeDialog" :overlayClick="true"
|
||||
:title="t('mobile.wallet.applyFreezeTitle')" :show-close="true" position="bottom" size="40%">
|
||||
<view class="h-50rpx" />
|
||||
<tm-form ref="bindFormRef" v-model="freezeForm">
|
||||
<tm-form-item name="remark" :showLabel="false" :showBottom="false">
|
||||
<tm-input v-model="freezeForm.remark" type="textarea" showClear :placeholder="t('mobile.wallet.remarkPlaceholder')" />
|
||||
<tm-input v-model="freezeForm.remark" type="textarea" showClear
|
||||
:placeholder="t('mobile.wallet.remarkPlaceholder')" />
|
||||
</tm-form-item>
|
||||
</tm-form>
|
||||
<view class="h-50rpx" />
|
||||
<view class="bg-#0094ff p-y-20rpx text-center rounded-40rpx sub-text-30 color-white!" @tap="doFreeze">{{ t('mobile.wallet.freeze') }}</view>
|
||||
<view class="bg-#0094ff p-y-20rpx text-center rounded-40rpx sub-text-30 color-white!" @tap="doFreeze">{{
|
||||
t('mobile.wallet.freeze') }}</view>
|
||||
</tm-drawer>
|
||||
<tm-drawer z-index="100" v-model:show="state.showQrCodeDialog" :overlayClick="false" :title="t('mobile.wallet.qrCodeTitle')"
|
||||
:show-close="true" position="bottom" size="50%">
|
||||
<tm-drawer z-index="100" v-model:show="state.showQrCodeDialog" :overlayClick="false"
|
||||
:title="t('mobile.wallet.qrCodeTitle')" :show-close="true" position="bottom" size="50%">
|
||||
<view class="flex-col-center">
|
||||
<view class="h-80rpx" />
|
||||
<canvas canvas-id="qrcodeId" class="size-200px" />
|
||||
|
||||
@@ -12,19 +12,23 @@
|
||||
<view v-else class="pb-12rpx">
|
||||
<view class="cart-toolbar">
|
||||
<view class="text-21rpx color-#667085">
|
||||
{{ t('mobile.dailyMenu.cart.segmentCount', { meals: props.draftGroups.length, foods: props.totalFoodCount }) }}
|
||||
{{ t('mobile.dailyMenu.cart.segmentCount', {
|
||||
meals: props.draftGroups.length, foods:
|
||||
props.totalFoodCount
|
||||
}) }}
|
||||
</view>
|
||||
<view class="clear-button" hover-class="tap-feedback" @tap="emitClear">{{ t('mobile.dailyMenu.cart.clear') }}</view>
|
||||
<view class="clear-button" hover-class="tap-feedback" @tap="emitClear">{{
|
||||
t('mobile.dailyMenu.cart.clear') }}</view>
|
||||
</view>
|
||||
|
||||
<view v-for="draft in props.draftGroups" :key="draft.key" class="cart-group">
|
||||
<view class="cart-group__header">
|
||||
<view class="cart-group__meta">
|
||||
<text class="cart-group__date">{{ formatReservationDate(draft.apptDate) }}</text>
|
||||
<text class="meal-tag show-line">{{ draft.mealTitle }}</text>
|
||||
<text class="meal-tag show-line">{{ resolveMealTitle(draft) }}</text>
|
||||
</view>
|
||||
<view class="remove-hit-area" hover-class="tap-feedback"
|
||||
:aria-label="t('mobile.dailyMenu.cart.removeGroupAria', { meal: draft.mealTitle })"
|
||||
:aria-label="t('mobile.dailyMenu.cart.removeGroupAria', { meal: resolveMealTitle(draft) })"
|
||||
@tap="emitRemoveGroup(draft.key)">
|
||||
<view class="remove-button">
|
||||
<tm-icon name="delete-bin-line" :size="23" color="#d92d20" />
|
||||
@@ -35,7 +39,8 @@
|
||||
<view v-for="item in draft.items" :key="item.spuId || item.id" class="cart-food-row">
|
||||
<image class="cart-food-row__image" :src="foodImage(item)" mode="aspectFill" />
|
||||
<view class="ml-12rpx min-w-0 flex-1">
|
||||
<view class="show-line sub-text-24">{{ item.name || t('mobile.dailyMenu.foodCard.unnamed') }}</view>
|
||||
<view class="show-line sub-text-24">{{ item.name || t('mobile.dailyMenu.foodCard.unnamed') }}
|
||||
</view>
|
||||
<view class="mt-3rpx text-23rpx font-700 color-#e5484d">¥{{ hooks.useMoney(item.price || 0) }}
|
||||
</view>
|
||||
</view>
|
||||
@@ -63,7 +68,10 @@
|
||||
<template #footer>
|
||||
<view class="drawer-footer">
|
||||
<view class="min-w-0 flex-1">
|
||||
<view class="text-20rpx color-#667085">{{ t('mobile.dailyMenu.cart.dinerTotal', { count: props.selectedDinerCount }) }}</view>
|
||||
<view class="text-20rpx color-#667085">{{ t('mobile.dailyMenu.cart.dinerTotal', {
|
||||
count:
|
||||
props.selectedDinerCount
|
||||
}) }}</view>
|
||||
<view class="mt-1rpx text-32rpx font-800 color-#e5484d">¥{{ hooks.useMoney(props.totalPayableAmount)
|
||||
}}</view>
|
||||
</view>
|
||||
@@ -138,6 +146,11 @@ const drawerShow = computed({
|
||||
set: (show: boolean) => emit("update:show", show),
|
||||
})
|
||||
|
||||
/** 已知餐段按当前语言展示,并为旧缓存草稿及未知协议值保留原始标题回退。 */
|
||||
const resolveMealTitle = (draft: ReservationDraft) => hooks.useEnum("hardHourTypeEnum", draft.hourType)
|
||||
|| draft.mealTitle
|
||||
|| t("mobile.dailyMenu.mealSlot")
|
||||
|
||||
/** 将预约日期格式化为抽屉标题使用的“月日 + 星期”,避免依赖各端 dayjs locale。 */
|
||||
const formatReservationDate = (value?: string) => {
|
||||
if (!value || !dayjs(value).isValid()) return t("mobile.dailyMenu.datePending")
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<base-skeleton class="mt-18rpx" width="126" height="44" round="22" color="#dcecff" dark-color="#323232" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<view class="flex items-center justify-between gap-8rpx">
|
||||
<view class="flex items-center justify-between">
|
||||
<view>
|
||||
<view class="sub-text-30">{{ t("mobile.order.diners.title") }}</view>
|
||||
<view class="second-text-22 mt-6rpx color-#999">
|
||||
|
||||
Reference in new issue
Block a user