feat: C 端套餐沉默期展示与自助延期
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 23m46s

- 套餐历史展示沉默期状态、截止日期、累计延期与调整审批中,可延期时显示延期入口
- 新增延期页:资格、档位与自定义天数试算、支付方式、下单(request_id 幂等)
- 支付宝走现有支付页;微信为链接时在微信外直接跳转,否则展示二维码与复制链接
- 新增我的延期订单列表与详情、沉默期记录,沉默期错误码转客户提示
This commit is contained in:
邹进
2026-11-07 13:19:33 +09:00
parent b2f802e6f8
commit 31ff18d66a
15 changed files with 1500 additions and 22 deletions

View File

@@ -30,6 +30,43 @@
</view>
</view>
<view v-if="silence" class="silence-info">
<view class="silence-header flex-row-sb">
<view class="silence-title">实名沉默期</view>
<view class="silence-status" :class="getSilenceStatusClass(silence.silence_status)">
{{ silence.silence_status_name || '-' }}
</view>
</view>
<view class="info-row flex-row-sb">
<view class="info-label">截止时间</view>
<view class="info-value">{{ formatSilenceDate(silence.silence_deadline_at) }}</view>
</view>
<view v-if="silence.silence_period_days" class="info-row flex-row-sb">
<view class="info-label">沉默期天数</view>
<view class="info-value">{{ silence.silence_period_days }} 天</view>
</view>
<view v-if="silence.silence_extended_days > 0" class="info-row flex-row-sb">
<view class="info-label">累计延期</view>
<view class="info-value">{{ silence.silence_extended_days }} 天</view>
</view>
<view v-if="silence.silence_adjust_pending" class="silence-pending">调整审批中</view>
<view class="silence-actions">
<view
class="silence-link"
role="button"
tabindex="0"
@tap.stop="openSilenceRecords"
>沉默期记录</view>
<view
v-if="silence.extendable"
class="silence-extend"
role="button"
tabindex="0"
@tap.stop="openSilenceExtension"
>延期</view>
</view>
</view>
<view class="divider"></view>
<view class="flow-info">
@@ -80,6 +117,7 @@
<script setup>
import { computed, ref } from 'vue';
import { formatSilenceDate, getSilenceStatusClass } from '@/utils/silence.js';
const props = defineProps({
node: {
@@ -92,6 +130,19 @@
}
});
const silence = computed(() => props.node.silence || null);
const openSilenceExtension = () => {
if (!silence.value?.extendable || !props.node.package_usage_id) return;
uni.navigateTo({
url: `/pages/silence-extension/silence-extension?package_usage_id=${props.node.package_usage_id}`
});
};
const openSilenceRecords = () => {
if (!props.node.package_usage_id) return;
uni.navigateTo({
url: `/pages/silence-records/silence-records?package_usage_id=${props.node.package_usage_id}`
});
};
const children = computed(() => Array.isArray(props.node.children) ? props.node.children : []);
const hasChildren = computed(() => children.value.length > 0);
const isMasterMissing = computed(() => props.node.relationship_status === 'master_missing');
@@ -147,6 +198,73 @@
</script>
<style lang="scss" scoped>
.silence-info {
margin-top: var(--space-md);
padding: var(--space-md);
border-radius: 16rpx;
background: var(--bg-secondary);
}
.silence-header {
align-items: center;
margin-bottom: var(--space-sm);
}
.silence-title {
font-size: 28rpx;
font-weight: 600;
color: var(--text-primary);
}
.silence-status {
padding: 4rpx 16rpx;
border-radius: 999rpx;
font-size: 22rpx;
color: var(--text-secondary);
background: var(--bg-primary);
&.silence-waiting {
color: #0a84ff;
background: rgba(10, 132, 255, 0.12);
}
&.silence-expired {
color: var(--danger);
background: var(--danger-light);
}
&.silence-ended {
color: var(--text-tertiary);
}
}
.silence-pending {
margin-top: var(--space-sm);
font-size: 24rpx;
color: #ff9f0a;
}
.silence-actions {
display: flex;
justify-content: flex-end;
gap: 24rpx;
margin-top: var(--space-sm);
}
.silence-link {
padding: 10rpx 0;
font-size: 24rpx;
color: var(--primary-dark);
}
.silence-extend {
padding: 10rpx 32rpx;
border-radius: 999rpx;
font-size: 24rpx;
color: #fff;
background: var(--primary);
}
.package-node {
margin-bottom: var(--space-md);