fix: some
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 11m35s

This commit is contained in:
luo
2026-09-17 18:43:01 +08:00
parent 68d8f769d1
commit ac541b17af
6 changed files with 295 additions and 14 deletions

View File

@@ -521,7 +521,8 @@
"paymentMerchantPoolsTabWechatAuth": "WeChat Authorization", "paymentMerchantPoolsTabWechatAuth": "WeChat Authorization",
"detailsOfPaymentMerchant": "Payment Merchant Details", "detailsOfPaymentMerchant": "Payment Merchant Details",
"detailsOfPaymentMerchantPool": "Merchant Pool Details", "detailsOfPaymentMerchantPool": "Merchant Pool Details",
"h5PopupConfiguration": "H5 Popup Configurations" "h5PopupConfiguration": "H5 Popup Configurations",
"assetWalletAutoRenewal": "Asset Wallet Auto Renewal"
}, },
"batch": { "batch": {
"title": "Batch Operations", "title": "Batch Operations",

View File

@@ -472,7 +472,8 @@
"paymentMerchantPoolsTabWechatAuth": "微信授权配置", "paymentMerchantPoolsTabWechatAuth": "微信授权配置",
"detailsOfPaymentMerchant": "支付商户详情", "detailsOfPaymentMerchant": "支付商户详情",
"detailsOfPaymentMerchantPool": "商户池详情", "detailsOfPaymentMerchantPool": "商户池详情",
"h5PopupConfiguration": "H5运营弹窗配置" "h5PopupConfiguration": "H5运营弹窗配置",
"assetWalletAutoRenewal": "资产钱包自动续费"
} }
}, },
"table": { "table": {

View File

@@ -1133,6 +1133,17 @@ export const asyncRoutes: AppRouteRecord[] = [
allowedUserTypes: [1, 2], allowedUserTypes: [1, 2],
permissions: [AUGUST_PERMISSIONS.h5PopupConfiguration.list] permissions: [AUGUST_PERMISSIONS.h5PopupConfiguration.list]
} }
},
// 资产钱包自动续费配置
{
path: 'asset-wallet-auto-renewal',
name: 'AssetWalletAutoRenewal',
component: RoutesAlias.AssetWalletAutoRenewal,
meta: {
title: 'menus.settings.assetWalletAutoRenewal',
keepAlive: true,
allowedUserTypes: [1, 2]
}
} }
] ]
}, },

View File

@@ -124,6 +124,7 @@ export enum RoutesAlias {
WecomMembers = '/settings/wecom/members', // 企业微信成员 WecomMembers = '/settings/wecom/members', // 企业微信成员
WecomScenes = '/settings/wecom/scenes', // 企业微信审批场景 WecomScenes = '/settings/wecom/scenes', // 企业微信审批场景
H5PopupConfigurations = '/settings/h5-popup-configuration', // H5运营弹窗配置 H5PopupConfigurations = '/settings/h5-popup-configuration', // H5运营弹窗配置
AssetWalletAutoRenewal = '/settings/asset-wallet-auto-renewal', // 资产钱包自动续费配置
// 轮询管理 // 轮询管理
DataCleanup = '/polling-management/data-cleanup', // 数据清理 DataCleanup = '/polling-management/data-cleanup', // 数据清理

View File

@@ -114,6 +114,7 @@
width="640px" width="640px"
:close-on-click-modal="false" :close-on-click-modal="false"
> >
<div v-loading="detailLoading">
<el-descriptions v-if="detailData" :column="2" border> <el-descriptions v-if="detailData" :column="2" border>
<el-descriptions-item label="ID">{{ detailData.id }}</el-descriptions-item> <el-descriptions-item label="ID">{{ detailData.id }}</el-descriptions-item>
<el-descriptions-item label="卡ICCID">{{ detailData.iccid }}</el-descriptions-item> <el-descriptions-item label="卡ICCID">{{ detailData.iccid }}</el-descriptions-item>
@@ -155,6 +156,7 @@
{{ formatDateTime(detailData.updated_at) }} {{ formatDateTime(detailData.updated_at) }}
</el-descriptions-item> </el-descriptions-item>
</el-descriptions> </el-descriptions>
</div>
</el-dialog> </el-dialog>
</ArtTableFullScreen> </ArtTableFullScreen>
</template> </template>
@@ -269,10 +271,8 @@
prop: 'status', prop: 'status',
label: '状态', label: '状态',
width: 100, width: 100,
slots: { formatter: (row: PollingPriorityItem) =>
default: ({ row }: any) =>
h(ElTag, { type: getStatusTagType(row.status) }, () => row.status_name) h(ElTag, { type: getStatusTagType(row.status) }, () => row.status_name)
}
}, },
{ {
prop: 'trigger_type_name', prop: 'trigger_type_name',
@@ -294,12 +294,12 @@
prop: 'result', prop: 'result',
label: '执行结果', label: '执行结果',
width: 110, width: 110,
slots: { formatter: (row: PollingPriorityItem) =>
default: ({ row }: any) => h(
h(ElTag, { type: getResultTagType(row.result) }, () => ElTag,
getPollingPriorityResultName(row.result) { type: getResultTagType(row.result) },
() => getPollingPriorityResultName(row.result)
) )
}
}, },
{ {
prop: 'manual_operator_name', prop: 'manual_operator_name',

View File

@@ -0,0 +1,267 @@
<template>
<ArtTableFullScreen>
<div class="asset-wallet-auto-renewal-page" id="table-full-screen">
<ElCard shadow="never" class="art-table-card">
<ElResult
v-if="loadError"
icon="error"
title="配置加载失败"
sub-title="无权限操作该资源或资源不存在"
>
<template #extra>
<ElButton type="primary" @click="loadConfig">重新加载</ElButton>
</template>
</ElResult>
<template v-else>
<ElForm
ref="formRef"
v-loading="loading"
:model="form"
:rules="formRules"
label-width="140px"
class="config-form"
>
<ElFormItem label="总开关" prop="enabled">
<ElSwitch v-model="form.enabled" :active-value="1" :inactive-value="0" />
<span class="form-tip">{{ form.enabled === 1 ? '开启' : '关闭' }}</span>
</ElFormItem>
<ElFormItem label="适用范围" prop="scope">
<ElRadioGroup v-model="form.scope">
<ElRadio value="all">全部主套餐</ElRadio>
<ElRadio value="specified">指定主套餐</ElRadio>
</ElRadioGroup>
</ElFormItem>
<ElFormItem
v-if="form.scope === 'specified'"
label="指定主套餐"
prop="package_ids"
>
<ElSelect
v-model="form.package_ids"
multiple
filterable
:loading="packageLoading"
placeholder="请选择主套餐"
style="width: 100%"
>
<ElOption
v-for="pkg in packageOptions"
:key="pkg.id"
:label="pkg.package_name"
:value="pkg.id"
/>
</ElSelect>
<span class="form-tip">仅支持选择当前可售主套餐</span>
</ElFormItem>
<ElFormItem label="到期前天数" prop="days_before_expiry">
<ElInputNumber
v-model="form.days_before_expiry"
:min="1"
:max="90"
controls-position="right"
style="width: 200px"
/>
<span class="form-tip">到期前 N 天开始扫描并自动续费1-90</span>
</ElFormItem>
</ElForm>
<div class="config-meta">
<span>配置版本v{{ config?.config_version ?? '-' }}</span>
<span>最近保存{{ config?.updater || '-' }}</span>
<span>{{ config?.updated_at ? formatDateTime(config.updated_at) : '-' }}</span>
</div>
<div class="form-actions">
<ElButton type="primary" :loading="saving" @click="handleSave">保存配置</ElButton>
<ElButton :disabled="saving" @click="loadConfig">重新加载</ElButton>
</div>
</template>
</ElCard>
</div>
</ArtTableFullScreen>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue'
import { ElMessage, type FormInstance, type FormRules } from 'element-plus'
import { AssetWalletService, PackageManageService } from '@/api/modules'
import type {
AssetAutoRenewalConfig,
AssetAutoRenewalScope,
UpdateAssetAutoRenewalConfigRequest
} from '@/types/api'
import { formatDateTime } from '@/utils/business/format'
import { usePermission } from '@/composables/usePermission'
defineOptions({ name: 'AssetWalletAutoRenewal' })
const { isPlatformAccount } = usePermission()
const formRef = ref<FormInstance>()
const loading = ref(false)
const saving = ref(false)
const loadError = ref(false)
const config = ref<AssetAutoRenewalConfig | null>(null)
const form = reactive({
enabled: 1 as 0 | 1,
scope: 'all' as AssetAutoRenewalScope,
package_ids: [] as number[],
days_before_expiry: 30
})
const formRules: FormRules = {
enabled: [{ required: true, message: '请选择总开关状态', trigger: 'change' }],
scope: [{ required: true, message: '请选择适用范围', trigger: 'change' }],
package_ids: [
{
validator: (_rule, value, callback) => {
if (form.scope === 'specified' && (!value || value.length === 0)) {
callback(new Error('请至少选择一个主套餐'))
} else {
callback()
}
},
trigger: 'change'
}
],
days_before_expiry: [
{ required: true, message: '请输入到期前天数', trigger: 'change' },
{
validator: (_rule, value, callback) => {
if (value === null || value === undefined) {
callback(new Error('请输入到期前天数'))
} else if (Number(value) < 1 || Number(value) > 90) {
callback(new Error('到期前天数必须在 1-90 之间'))
} else {
callback()
}
},
trigger: 'change'
}
]
}
const packageLoading = ref(false)
const packageOptions = ref<Array<{ id: number; package_name: string }>>([])
const loadPackages = async () => {
packageLoading.value = true
try {
const { data } = await PackageManageService.getPackages({
page: 1,
page_size: 200,
package_type: 'formal',
shelf_status: 1,
status: 1
})
packageOptions.value = (data.items || []).map((pkg) => ({
id: pkg.id,
package_name: pkg.package_name
}))
} catch (error) {
console.error('加载可售主套餐失败', error)
} finally {
packageLoading.value = false
}
}
const applyConfig = (data: AssetAutoRenewalConfig) => {
config.value = data
form.enabled = data.enabled
form.scope = data.scope
form.package_ids = data.package_ids || []
form.days_before_expiry = data.days_before_expiry
}
const loadConfig = async () => {
if (!isPlatformAccount.value) {
loadError.value = true
return
}
loading.value = true
loadError.value = false
try {
const res = await AssetWalletService.getAutoRenewalConfig()
if (res.code === 0 && res.data) {
applyConfig(res.data)
} else if (res.code !== 0) {
ElMessage.error(res.msg || '配置加载失败')
loadError.value = true
}
} catch (error) {
console.error('加载自动续费配置失败', error)
loadError.value = true
} finally {
loading.value = false
}
}
const handleSave = async () => {
if (!formRef.value) return
const valid = await formRef.value.validate().catch(() => false)
if (!valid) return
const payload: UpdateAssetAutoRenewalConfigRequest = {
enabled: form.enabled,
scope: form.scope,
package_ids: form.scope === 'all' ? [] : form.package_ids,
days_before_expiry: form.days_before_expiry
}
saving.value = true
try {
const res = await AssetWalletService.saveAutoRenewalConfig(payload)
if (res.code === 0 && res.data) {
applyConfig(res.data)
ElMessage.success('自动续费配置保存成功')
} else {
ElMessage.error(res.msg || '自动续费配置保存失败')
}
} catch (error) {
console.error('保存自动续费配置失败', error)
} finally {
saving.value = false
}
}
onMounted(() => {
loadConfig()
loadPackages()
})
</script>
<style scoped lang="scss">
.asset-wallet-auto-renewal-page {
height: 100%;
.config-form {
max-width: 720px;
padding-top: 10px;
}
.form-tip {
margin-left: 12px;
font-size: 12px;
color: var(--art-gray-600);
}
.config-meta {
display: flex;
gap: 24px;
padding: 12px 0 0 140px;
font-size: 13px;
color: var(--art-gray-600);
}
.form-actions {
display: flex;
gap: 12px;
padding: 20px 0 10px 140px;
}
}
</style>