style(shopGoodsBrowse): 移除商品名称列的居中对齐

- 删除了商品名称列中多余的 align: 'center' 属性
- 保持了 ellipsis 属性以支持文本省略显示
- 优化了表格列的展示样式一致性
This commit is contained in:
2026-07-15 18:55:37 +08:00
parent ace46ffea6
commit 5b5bb3b0e5
4 changed files with 127 additions and 16 deletions

View File

@@ -221,18 +221,19 @@ export async function mpConfirm(
}
/**
* 续费
* 续费基于已有订阅创建续费订单pending返回新 subscriptionId
* POST /app/subscription/renew/{id}?period=month|year
* 返回结构与 subscribe 一致(含 subscriptionId前端再调 pay 生成支付码
*/
export async function renewSubscription(
id: number,
period: 'month' | 'year' = 'month'
): Promise<string> {
const res = await request.post<ApiResult<string>>(`${BASE}/renew/${id}`, undefined, {
): Promise<SubscribeResult> {
const res = await request.post<ApiResult<SubscribeResult>>(`${BASE}/renew/${id}`, undefined, {
params: { period }
});
if (res.data.code === 0) {
return res.data.message || '续费成功';
return res.data.data as SubscribeResult;
}
return Promise.reject(new Error(res.data.message));
}

View File

@@ -286,15 +286,15 @@ export const useAppSubscriptionStore = defineStore('appSubscription', {
// ============================================================
/**
* 续费
* 续费:基于已有订阅创建续费订单,返回新 subscriptionId再调 pay 发起支付)
* @param id 订阅ID
* @param period 周期month/year
*/
async renew(id: number, period: 'month' | 'year' = 'month'): Promise<string> {
async renew(id: number, period: 'month' | 'year' = 'month'): Promise<SubscribeResult> {
try {
const msg = await renewSubscription(id, period);
const result = await renewSubscription(id, period);
this.invalidateCache();
return msg;
return result;
} catch (error) {
console.error('续费失败:', error);
throw error;

View File

@@ -185,13 +185,19 @@
</template>
<template v-else-if="currentSubscription && currentSubscription.status === 'active' && currentSubscription.expireTime">
<span>{{ formatDateTime(currentSubscription.expireTime) }}</span>
<a-tag color="green" style="margin-left: 8px">已激活</a-tag>
<a-tag :color="isExpired ? 'red' : 'green'" style="margin-left: 8px">
{{ isExpired ? '已过期' : '已激活' }}
</a-tag>
<span v-if="daysToExpire !== null && daysToExpire >= 0 && daysToExpire <= 7" class="expire-warn">
{{ daysToExpire }}天后到期
</span>
<span v-else-if="daysToExpire !== null && daysToExpire < 0" class="expire-warn">
已过期
已过期{{ Math.abs(daysToExpire) }}
</span>
<!-- 续费按钮即将到期7天内或已过期时显示 -->
<a-button v-if="showRenewButton" type="link" size="small" @click="onRenew" style="padding: 0 0 0 8px">
立即续费
</a-button>
</template>
<template v-else-if="currentSubscription && currentSubscription.status === 'pending'">
<span class="text-orange">待支付 ¥{{ Number(currentSubscription.payPrice || 0).toFixed(2) }}</span>
@@ -263,15 +269,15 @@
</a-col>
</a-row>
<!-- 订阅 Modal选择订阅周期 -->
<!-- 订阅/续费 Modal选择订阅周期subscribe-新订阅 / renew-续费 -->
<a-modal
v-model:open="subscribeModalVisible"
title="订阅应用"
:confirm-loading="subscribing"
ok-text="确认订阅"
:title="subscribeMode === 'renew' ? '续费应用' : '订阅应用'"
:confirm-loading="subscribeMode === 'renew' ? renewing : subscribing"
:ok-text="subscribeMode === 'renew' ? '确认续费' : '确认订阅'"
cancel-text="取消"
:mask-closable="false"
@ok="confirmSubscribe"
@ok="subscribeMode === 'renew' ? confirmRenew() : confirmSubscribe()"
>
<div class="subscribe-modal-body">
<div class="subscribe-product-name">
@@ -280,7 +286,7 @@
<a-alert
v-if="isFreeProduct"
type="success"
message="该应用为免费应用,订阅后立即激活"
:message="subscribeMode === 'renew' ? '该应用为免费应用,续费后立即激活' : '该应用为免费应用,订阅后立即激活'"
show-icon
style="margin-bottom: 12px"
/>
@@ -416,6 +422,9 @@ const subscriptionLoading = ref(false);
const subscribeModalVisible = ref(false);
const subscribing = ref(false);
const selectedPeriod = ref<'month' | 'year'>('month');
// Modal 模式subscribe-新订阅 / renew-续费(复用同一 Modal
const subscribeMode = ref<'subscribe' | 'renew'>('subscribe');
const renewing = ref(false);
// 支付 Modal小程序码扫码支付
const payModalVisible = ref(false);
@@ -449,6 +458,17 @@ const daysToExpire = computed(() => {
return dayjs(expire).startOf('day').diff(dayjs().startOf('day'), 'day');
});
// 是否已过期expireTime 早于今天)
const isExpired = computed(
() => daysToExpire.value !== null && daysToExpire.value < 0
);
// 续费按钮显示条件即将到期7天内或已过期
const showRenewButton = computed(() => {
if (daysToExpire.value === null) return false;
return daysToExpire.value <= 7;
});
// 格式化时间
const formatDateTime = (dt?: string) => {
if (!dt) return '-';
@@ -509,9 +529,61 @@ const onSubscribe = () => {
return;
}
selectedPeriod.value = 'month';
subscribeMode.value = 'subscribe';
subscribeModalVisible.value = true;
};
// 打开续费 Modal复用订阅 Modal
const onRenew = () => {
if (!currentSubscription.value?.id) {
message.warning('订阅信息加载中,请稍后再试');
return;
}
selectedPeriod.value = 'month';
subscribeMode.value = 'renew';
subscribeModalVisible.value = true;
};
// 确认续费方案1renew 创建续费订单 → pay 生成小程序码 → 扫码,与 confirmSubscribe 对称)
const confirmRenew = async () => {
const sub = currentSubscription.value;
if (!sub?.id) return;
renewing.value = true;
try {
// 1. 续费:基于原订阅创建续费订单,返回新 subscriptionId
const renewResult = await subscriptionStore.renew(sub.id, selectedPeriod.value);
// 免费应用renew 直接激活status=active
if (renewResult.status === 'active') {
message.success('续费成功');
subscribeModalVisible.value = false;
refreshSubscription();
return;
}
// 2. 付费应用:用 pay 生成支付小程序码
const payResult = await subscriptionStore.pay(
renewResult.subscriptionId,
'wechat',
envVersion
);
if ('miniappQrcode' in payResult) {
paySubscriptionNo.value =
payResult.subscriptionNo || renewResult.subscriptionNo;
payQrcode.value = payResult.miniappQrcode;
payPrice.value = Number(payResult.payPrice) || 0;
payProductName.value = currentProduct.value?.productName || '应用续费';
subscribeModalVisible.value = false;
payModalVisible.value = true;
// 开始轮询支付状态
startPolling(paySubscriptionNo.value);
}
} catch (e: any) {
console.error('续费失败:', e);
message.error(e?.message || '续费失败,请重试');
} finally {
renewing.value = false;
}
};
// 确认订阅
const confirmSubscribe = async () => {
const product = currentProduct.value;