diff --git a/components/consumer/EmptyState.uvue b/components/consumer/EmptyState.uvue
index 49836aba..a7838249 100644
--- a/components/consumer/EmptyState.uvue
+++ b/components/consumer/EmptyState.uvue
@@ -10,7 +10,7 @@
export default {
props: {
text: { type: String, default: '暂无数据' },
- image: { type: String, default: '/static/default.png' }
+ image: { type: String, default: '/static/consumer/defaul_picture.png' }
}
}
diff --git a/pages/main/profile.uvue b/pages/main/profile.uvue
index 66f17732..b9e71f2f 100644
--- a/pages/main/profile.uvue
+++ b/pages/main/profile.uvue
@@ -357,8 +357,8 @@ export default {
topActionsWidth: 104,
userHeaderRightReserve: 118,
userHeaderTopOffset: 0,
- addressIconPath: '/static/location.png',
- settingIconPath: '/static/setting.png',
+ addressIconPath: '/static/consumer/location.png',
+ settingIconPath: '/static/consumer/setting.png',
navBarRight: 0, // 导航栏右侧预留空间(小程序胶囊按钮)
currentOrderTab: 'all' as string,
pendingReceiptGoods: {
diff --git a/pages/mall/consumer/home-service/order-detail.uvue b/pages/mall/consumer/home-service/order-detail.uvue
index 720f0ec2..ee126bb2 100644
--- a/pages/mall/consumer/home-service/order-detail.uvue
+++ b/pages/mall/consumer/home-service/order-detail.uvue
@@ -86,7 +86,11 @@
状态更新时间:{{ consumerViewState.statusUpdatedAt }}
-
+
+ 返回首页
+ 再次预约
+
+
再次预约
再次预约
去验收反馈
@@ -107,7 +111,7 @@ import ServicePanel from '@/components/homeService/ServicePanel.uvue'
import ServiceStatusTag from '@/components/homeService/ServiceStatusTag.uvue'
import ServiceTimeline from '@/components/homeService/ServiceTimeline.uvue'
import { fetchConsumerHomeServiceCaseDetail } from '@/services/homeServiceService.uts'
-import { dispatchPaidHomecareOrder, getHomecareOrderDisplayStatus, HOMECARE_DISPATCH_STATUS_FAILED, showHomecareDispatchFailureModal } from '@/services/serviceOrderService.uts'
+import { dispatchPaidHomecareOrder, HOMECARE_DISPATCH_STATUS_FAILED, showHomecareDispatchFailureModal } from '@/services/serviceOrderService.uts'
import { HomeServiceCaseType } from '@/types/home-service.uts'
import { getCurrentUser, getCurrentUserId } from '@/utils/store.uts'
import { goToLogin } from '@/utils/utils.uts'
@@ -162,6 +166,10 @@ async function goPayment(): Promise {
uni.showToast({ title: '订单信息加载失败,请稍后重试', icon: 'none' })
return
}
+ if (isServicePaymentExpired.value) {
+ uni.showToast({ title: '订单已超时未支付,请重新预约', icon: 'none' })
+ return
+ }
if (!canPayServiceOrder.value) {
uni.showToast({ title: '当前订单已不可支付,请刷新查看最新状态', icon: 'none' })
return
@@ -192,6 +200,36 @@ function contactService() {
uni.showToast({ title: '即将接入专属客服入口', icon: 'none' })
}
+function goHome() {
+ uni.navigateTo({ url: '/pages/mall/consumer/home-service/index' })
+}
+
+function getPayExpireMs(caseDetail: HomeServiceCaseType): number {
+ if (caseDetail.payExpireAt == null || caseDetail.payExpireAt == '') {
+ return 0
+ }
+ const parsed = Date.parse(caseDetail.payExpireAt)
+ return isNaN(parsed) ? 0 : parsed
+}
+
+function isPaymentTimeExpired(caseDetail: HomeServiceCaseType): boolean {
+ if (caseDetail.paymentStatus != 1 || caseDetail.status != 'created') {
+ return false
+ }
+ const expireMs = getPayExpireMs(caseDetail)
+ if (expireMs <= 0) {
+ return false
+ }
+ return expireMs <= Date.now()
+}
+
+const isServicePaymentExpired = computed(() => {
+ if (detail.value == null) {
+ return false
+ }
+ return isPaymentTimeExpired(detail.value)
+})
+
let isRetryDispatching = false
function retryDispatch() {
@@ -260,6 +298,14 @@ const consumerViewState = computed(() => {
const remark = getLatestTimelineRemark(detail.value)
const result = { ...defaultState }
+ if (isPaymentTimeExpired(detail.value)) {
+ result.showExceptionPanel = true
+ result.exceptionTitle = '订单已超时未支付'
+ result.exceptionDesc = '支付时间已结束,请返回首页重新预约或刷新查看最新状态。'
+ result.statusUpdatedAt = detail.value.payExpireAt != null && detail.value.payExpireAt != '' ? detail.value.payExpireAt : detail.value.serviceTime
+ return result
+ }
+
if (detail.value.statusText == '派单未成功') {
result.showExceptionPanel = true
result.exceptionTitle = '派单未成功'
@@ -320,6 +366,7 @@ const canPayServiceOrder = computed(() => {
}
return detail.value.paymentStatus == 1
&& detail.value.status == 'created'
+ && !isPaymentTimeExpired(detail.value)
})
let detailRefreshTimerId: number = 0
@@ -553,4 +600,4 @@ onUnload(() => {
color: #c2410c;
line-height: 40rpx;
}
-
\ No newline at end of file
+
diff --git a/pages/mall/consumer/order-detail.uvue b/pages/mall/consumer/order-detail.uvue
index 9f9e4f83..a4cdfe00 100644
--- a/pages/mall/consumer/order-detail.uvue
+++ b/pages/mall/consumer/order-detail.uvue
@@ -262,7 +262,8 @@ const getPendingCountdownText = (): string => {
const shouldShowCancelledActions = (): boolean => {
const source = toOrderStatusSource()
if (source == null) return false
- return getOrderDisplayStatus(source) == 'cancelled'
+ const displayStatus = getOrderDisplayStatus(source)
+ return displayStatus == 'cancelled' || displayStatus == 'expired'
}
// 辅助函数 - 必须在调用前定义
@@ -272,6 +273,7 @@ const getStatusText = (): string => {
if (source != null) {
const displayStatus = getOrderDisplayStatus(source)
if (displayStatus == 'pending') return '待付款'
+ if (displayStatus == 'expired') return '已超时未支付'
if (displayStatus == 'cancelled') return '已取消'
}
if (status == 1) return '待付款'
@@ -292,6 +294,9 @@ const getStatusDesc = (): string => {
if (displayStatus == 'pending') {
return '请在 ' + getPendingCountdownText() + ' 内支付'
}
+ if (displayStatus == 'expired') {
+ return '订单已超时未支付,请返回订单列表或重新选购'
+ }
if (displayStatus == 'cancelled') {
const currentReason = order.value?.cancel_reason ?? ''
if (currentReason.indexOf('超时') >= 0) {
@@ -325,7 +330,7 @@ const getStatusClass = (): string => {
if (source != null) {
const displayStatus = getOrderDisplayStatus(source)
if (displayStatus == 'pending') return 'status-pending'
- if (displayStatus == 'cancelled') return 'status-cancelled'
+ if (displayStatus == 'cancelled' || displayStatus == 'expired') return 'status-cancelled'
}
const status = order.value?.order_status ?? 0
return 'status-' + status
diff --git a/pages/mall/consumer/orders.uvue b/pages/mall/consumer/orders.uvue
index a19d50c5..ee128edc 100644
--- a/pages/mall/consumer/orders.uvue
+++ b/pages/mall/consumer/orders.uvue
@@ -1335,7 +1335,8 @@ const onRefresh = async () => {
const getOrderStatusText = (order: OrderItem): string => {
const displayState = getUnifiedDisplayState(toOrderStatusSource(order))
if (displayState == 'pending_pay') return '待付款'
- if (displayState == 'cancelled' || displayState == 'expired') return '已取消'
+ if (displayState == 'expired') return '已超时未支付'
+ if (displayState == 'cancelled') return '已取消'
if (order.biz_type === 'service') {
if (order.payment_status == 1 && order.status == 1) return '待付款'
diff --git a/pages/mall/consumer/payment.uvue b/pages/mall/consumer/payment.uvue
index 8228c65d..f6c94f5d 100644
--- a/pages/mall/consumer/payment.uvue
+++ b/pages/mall/consumer/payment.uvue
@@ -11,7 +11,7 @@
◷
- {{ orderMissing ? '订单不存在' : (isPaymentExpired ? '已取消' : '等待付款') }}
+ {{ orderMissing ? '订单不存在' : (isPaymentExpired ? '已超时未支付' : '等待付款') }}
@@ -26,7 +26,7 @@
- 订单超时未支付,已自动取消
+ 订单已超时未支付
@@ -555,11 +555,11 @@ const countdownText = computed((): string => {
})
const payStatusTitle = computed((): string => {
- return isPaymentExpired.value ? '已取消' : '等待付款'
+ return isPaymentExpired.value ? '已超时未支付' : '等待付款'
})
const payStatusDesc = computed((): string => {
- return isPaymentExpired.value ? '订单超时未支付,已自动取消' : '请在 ' + countdownText.value + ' 内支付'
+ return isPaymentExpired.value ? '订单已超时未支付,请返回订单列表或重新选购' : '请在 ' + countdownText.value + ' 内支付'
})
const getDeadlineByCreatedAt = (createdAt: string): number => {
@@ -944,10 +944,10 @@ const handlePaymentTimeout = async () => {
updateOrderInStorage(orderId.value, cancelledStatus, ORDER_TIMEOUT_CANCEL_REASON)
uni.$emit('orderUpdated', { orderId: orderId.value, status: cancelledStatus, paymentStatus: PAYMENT_STATUS_TIMEOUT, cancelReason: ORDER_TIMEOUT_CANCEL_REASON, payExpireAt: payExpireAtText.value })
if (success) {
- uni.showToast({ title: '订单已取消', icon: 'none' })
+ uni.showToast({ title: '订单已超时未支付', icon: 'none' })
return
}
- uni.showToast({ title: '订单已取消', icon: 'none' })
+ uni.showToast({ title: '订单已超时未支付', icon: 'none' })
}
const parseAddressFromOrder = (orderObj: UTSJSONObject) => {
@@ -1363,7 +1363,7 @@ const confirmPayment = async () => {
}
if (isPaymentExpired.value || remainingSeconds.value <= 0) {
markPaymentExpiredInPage()
- uni.showToast({ title: '订单已取消,不能继续支付', icon: 'none' })
+ uni.showToast({ title: '订单已超时未支付,不能继续支付', icon: 'none' })
return
}
if (!ensureLoggedIn()) return
@@ -1390,7 +1390,7 @@ const confirmPayment = async () => {
if (latestState == 'expired' || latestState == 'cancelled') {
await supabaseService.expireUnifiedOrder(orderId.value, source.value)
markPaymentExpiredInPage()
- uni.showToast({ title: '订单已取消,不能继续支付', icon: 'none' })
+ uni.showToast({ title: '订单已超时未支付,不能继续支付', icon: 'none' })
isPaying.value = false
return
}
@@ -1440,7 +1440,7 @@ const confirmPayment = async () => {
if (isExpiredState(latestStatus, latestPayment, latestReason, latestExpire)) {
markPaymentExpiredInPage()
uni.hideLoading()
- uni.showToast({ title: '订单已取消,不能继续支付', icon: 'none' })
+ uni.showToast({ title: '订单已超时未支付,不能继续支付', icon: 'none' })
isPaying.value = false
return
}
diff --git a/pages/mall/consumer/settings.uvue b/pages/mall/consumer/settings.uvue
index 49cd6bae..b4ff6c9c 100644
--- a/pages/mall/consumer/settings.uvue
+++ b/pages/mall/consumer/settings.uvue
@@ -1,927 +1,697 @@
-
-
-
-
-
+
+
+
+
+
+ 管理我的账户
+
+
+
+
+ {{ getDisplayName() }}
+ 当前登录
+
+ {{ getAccountSubtitle() }}
+
+
+ ✎
+
+
+
-
-
-
- 账户设置
-
-
- 👤
- 个人资料
- ›
-
-
- 📍
- 收货地址
- ›
-
-
- 🔒
- 修改密码
- ›
-
-
- 📱
- 手机绑定
-
-
- {{ userInfo.phone != null && userInfo.phone != '' ? '已绑定' : '未绑定' }}
-
- ›
-
-
-
- 📧
- 邮箱绑定
-
-
- {{ userInfo.email != null && userInfo.email != '' ? '已绑定' : '未绑定' }}
-
- ›
-
-
-
-
+
+ 用户设置
+
+
-
-
- 隐私设置
-
-
- 👁️
- 隐藏购物记录
-
-
-
- 🔍
- 允许通过手机号找到我
-
-
-
- 💬
- 接收商家消息
-
-
-
-
+
+ 功能设置
+
+
-
-
-
-
+
+
+
-
-
- 注销账号
-
-
-
+
+
+
+
-
diff --git a/pages/user/login.uvue b/pages/user/login.uvue
index 8877819a..1dd1c650 100644
--- a/pages/user/login.uvue
+++ b/pages/user/login.uvue
@@ -173,14 +173,14 @@ const loginType = ref(0)
// 默认账号密码(唯一来源,修改只改这里)
// 必须在 account/password ref 之前声明,否则 ref 初始化时无法引用
// ─────────────────────────────────────────────
-// const TEST_ACCOUNT = 'test@mall.com' // ← 旧账号(已停用)
-// const TEST_PASSWORD = 'Hf2152111' // ← 旧密码(已停用)
-const TEST_ACCOUNT = 'test19@163.com'
-const TEST_PASSWORD = 'huang123456'
+const CONSUMER_TEST_ACCOUNT = 'test@mall.com'
+const CONSUMER_TEST_PASSWORD = 'Hf2152111'
+const MERCHANT_TEST_ACCOUNT = 'test19@163.com'
+const MERCHANT_TEST_PASSWORD = 'huang123456'
// ✅ account/password 直接以常量作初始值,上线/刷新立即生效,不再依赖 onMounted 延迟赋值
-const account = ref('')
-const password = ref('')
+const account = ref(CONSUMER_TEST_ACCOUNT)
+const password = ref(CONSUMER_TEST_PASSWORD)
const captcha = ref('')
const isPasswordVisible = ref(false)
@@ -375,7 +375,7 @@ onMounted(() => {
console.log('[Login] ▶ onMounted 开始')
console.log('[Login] 📝 form 初始值:', {
account: account.value,
- password: account.value === TEST_ACCOUNT ? '(TEST_PASSWORD 默认)' : '(ref 已被其他逻辑覆盖)'
+ password: account.value === CONSUMER_TEST_ACCOUNT ? '(CONSUMER_TEST_PASSWORD 默认)' : '(ref 已被其他逻辑覆盖)'
})
// 检查是否存在旧版本 loginn.uvue 遗留的 rememberEmail 缓存
@@ -389,7 +389,7 @@ onMounted(() => {
password.value = '' // 密码不缓存,须用户手动输入
} else {
console.log('[Login] ℹ️ 无缓存,使用默认账号密码(已由 ref 初始化)')
- // account 和 password 已在 ref 声明时直接用 TEST_ACCOUNT/TEST_PASSWORD 初始化,无需重复赋值
+ // account 和 password 已在 ref 声明时直接用消费者默认值初始化,无需重复赋值
}
} catch (e) {
console.error('[Login] ⚠️ 读取 rememberEmail 失败(已忽略):', e)
@@ -397,15 +397,15 @@ onMounted(() => {
console.log('[Login] 📝 onMounted 完成,最终 form 値:', {
account: account.value,
- isDefault: account.value === TEST_ACCOUNT
+ isDefault: account.value === CONSUMER_TEST_ACCOUNT
})
if (isDeliveryMode()) {
account.value = ''
password.value = ''
} else if (isMerchantMode()) {
- account.value = TEST_ACCOUNT
- password.value = TEST_PASSWORD
+ account.value = MERCHANT_TEST_ACCOUNT
+ password.value = MERCHANT_TEST_PASSWORD
}
checkLoginStatus()
diff --git a/services/homeServiceService.uts b/services/homeServiceService.uts
index 8b077ea9..1cdacef7 100644
--- a/services/homeServiceService.uts
+++ b/services/homeServiceService.uts
@@ -655,6 +655,9 @@ function mapOrderToCase(order: ServiceOrderType): HomeServiceCaseType {
const displayStatus = getHomecareOrderDisplayStatus(order)
let statusText = displayStatus
let statusTone = getCaseTone(order.status)
+ if (displayStatus == '已超时未支付') {
+ statusTone = 'danger'
+ }
if (order.dispatchStatus == HOMECARE_DISPATCH_STATUS_FAILED) {
statusTone = 'danger'
}
@@ -1181,4 +1184,4 @@ export async function fetchAdminHomeServiceApplications(): Promise> {
await delay()
return ADMIN_OVERVIEW.map((item) => ({ ...item }))
-}
\ No newline at end of file
+}
diff --git a/services/serviceOrderService.uts b/services/serviceOrderService.uts
index 13163311..233f98c4 100644
--- a/services/serviceOrderService.uts
+++ b/services/serviceOrderService.uts
@@ -951,6 +951,9 @@ export function buildAddressSnapshot(address: UserAddress, latitude: number, lon
}
export function getHomecareOrderDisplayStatus(order: ServiceOrderType): string {
+ if (order.paymentStatus == 1 && order.status == 'created' && isHomecarePaymentExpired(order)) {
+ return '已超时未支付'
+ }
if (order.paymentStatus == 1 && order.status == 'created') {
return '待付款'
}
@@ -969,6 +972,21 @@ export function getHomecareOrderDisplayStatus(order: ServiceOrderType): string {
return getServiceOrderStatusText(order.status)
}
+function isHomecarePaymentExpired(order: ServiceOrderType): boolean {
+ if (order.paymentStatus != 1 || order.status != 'created') {
+ return false
+ }
+ const payExpireAt = order.payExpireAt != null ? order.payExpireAt : ''
+ if (payExpireAt == '') {
+ return false
+ }
+ const expireMs = Date.parse(payExpireAt)
+ if (isNaN(expireMs)) {
+ return false
+ }
+ return expireMs <= Date.now()
+}
+
export async function dispatchPaidHomecareOrder(orderId: string): Promise {
if (orderId == null || orderId.trim() == '') {
return {
@@ -1346,4 +1364,4 @@ export async function rejectServiceOrderAcceptance(orderId: string, content: str
export async function getCurrentConsumerUser() {
return await getCurrentUser()
- }
\ No newline at end of file
+ }
diff --git a/static/consumer/bell.png b/static/consumer/bell.png
new file mode 100644
index 00000000..0506ae54
Binary files /dev/null and b/static/consumer/bell.png differ
diff --git a/static/consumer/change.png b/static/consumer/change.png
new file mode 100644
index 00000000..32582cef
Binary files /dev/null and b/static/consumer/change.png differ
diff --git a/static/default.png b/static/consumer/defaul_picture.png
similarity index 100%
rename from static/default.png
rename to static/consumer/defaul_picture.png
diff --git a/static/consumer/default_index.png b/static/consumer/default_index.png
new file mode 100644
index 00000000..686d225c
Binary files /dev/null and b/static/consumer/default_index.png differ
diff --git a/static/consumer/feedback.png b/static/consumer/feedback.png
new file mode 100644
index 00000000..f3629177
Binary files /dev/null and b/static/consumer/feedback.png differ
diff --git a/static/location.png b/static/consumer/location.png
similarity index 100%
rename from static/location.png
rename to static/consumer/location.png
diff --git a/static/consumer/privacy_setting.png b/static/consumer/privacy_setting.png
new file mode 100644
index 00000000..3b23a58d
Binary files /dev/null and b/static/consumer/privacy_setting.png differ
diff --git a/static/setting.png b/static/consumer/setting.png
similarity index 100%
rename from static/setting.png
rename to static/consumer/setting.png
diff --git a/static/images/default-banner.png b/static/images/default-banner.png
deleted file mode 100644
index e69de29b..00000000
diff --git a/static/images/default-product.png b/static/images/default-product.png
deleted file mode 100644
index e69de29b..00000000
diff --git a/utils/orderStatus.uts b/utils/orderStatus.uts
index 55619afa..1a6ccf51 100644
--- a/utils/orderStatus.uts
+++ b/utils/orderStatus.uts
@@ -136,9 +136,12 @@ export function getOrderDisplayStatus(order: OrderStatusSource): string {
if (displayState == 'pending_pay') {
return 'pending'
}
- if (displayState == 'cancelled' || displayState == 'expired') {
+ if (displayState == 'cancelled') {
return 'cancelled'
}
+ if (displayState == 'expired') {
+ return 'expired'
+ }
if (displayState == 'processing') {
return 'shipping'
}
@@ -169,4 +172,4 @@ export function formatCountdownHMS(seconds: number): string {
const minutes = Math.floor((safeSeconds % 3600) / 60)
const remainSeconds = safeSeconds % 60
return pad2(hours) + ':' + pad2(minutes) + ':' + pad2(remainSeconds)
-}
\ No newline at end of file
+}