This commit is contained in:
@@ -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",
|
||||||
|
|||||||
@@ -472,7 +472,8 @@
|
|||||||
"paymentMerchantPoolsTabWechatAuth": "微信授权配置",
|
"paymentMerchantPoolsTabWechatAuth": "微信授权配置",
|
||||||
"detailsOfPaymentMerchant": "支付商户详情",
|
"detailsOfPaymentMerchant": "支付商户详情",
|
||||||
"detailsOfPaymentMerchantPool": "商户池详情",
|
"detailsOfPaymentMerchantPool": "商户池详情",
|
||||||
"h5PopupConfiguration": "H5运营弹窗配置"
|
"h5PopupConfiguration": "H5运营弹窗配置",
|
||||||
|
"assetWalletAutoRenewal": "资产钱包自动续费"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"table": {
|
"table": {
|
||||||
|
|||||||
@@ -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]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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', // 数据清理
|
||||||
|
|||||||
@@ -114,7 +114,8 @@
|
|||||||
width="640px"
|
width="640px"
|
||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
>
|
>
|
||||||
<el-descriptions v-if="detailData" :column="2" border>
|
<div v-loading="detailLoading">
|
||||||
|
<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>
|
||||||
<el-descriptions-item label="任务类型">
|
<el-descriptions-item label="任务类型">
|
||||||
@@ -154,7 +155,8 @@
|
|||||||
<el-descriptions-item label="更新时间">
|
<el-descriptions-item label="更新时间">
|
||||||
{{ 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',
|
||||||
|
|||||||
267
src/views/settings/asset-wallet-auto-renewal/index.vue
Normal file
267
src/views/settings/asset-wallet-auto-renewal/index.vue
Normal 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>
|
||||||
Reference in New Issue
Block a user