refactor(admin): clean up audit/permission/paid content config
- P1: remove the duplicate "审核联动" (ai_moderate_background/submit) block from the attachment permissions page; those settings live in the "评论审核" / API content audit surfaces. - P2: rename the "内容审核" submenu to "评论审核" (permissions domain). - P4: remove the "下载/付费内容中心" page and its schema/route chain; hardcode runtime policy so download always supports credit purchase and paid content is limited to posts. Drop the now-dead cms_features.download_credit flag and parse_slug_list helper.
This commit is contained in:
1 parent
2f4ce790a7
commit
b4a4b295bc
16 files changed
+33
-461
No files matched your search
@@ -1,221 +0,0 @@
|
||||
<template>
|
||||
<div class="aksrt-page-container">
|
||||
<PageHeader
|
||||
title="下载/付费内容中心"
|
||||
desc="统一管理资源下载门槛、积分购买模式开关、角色免扣和人工交付说明。付费解锁走收银台订单,下载 token 不再按次扣费。"
|
||||
>
|
||||
<template #actions>
|
||||
<n-space>
|
||||
<n-button quaternary @click="go('/permissions/capabilities')">基本权限</n-button>
|
||||
<n-button quaternary @click="go('/payment/gateway')">收款接口</n-button>
|
||||
</n-space>
|
||||
</template>
|
||||
</PageHeader>
|
||||
|
||||
<n-spin :show="loading" style="width: 100%; min-height: 200px;">
|
||||
<n-card class="aksrt-section-card">
|
||||
<div class="aksrt-section-header">
|
||||
<h3>当前联动摘要</h3>
|
||||
</div>
|
||||
<n-space>
|
||||
<n-tag round :type="form.download_credit ? 'warning' : 'default'">
|
||||
积分购买模式:{{ form.download_credit ? '已启用' : '已关闭' }}
|
||||
</n-tag>
|
||||
<n-tag round type="info">
|
||||
默认积分价:{{ form.download_default_cost }} {{ currencyName }}
|
||||
</n-tag>
|
||||
<n-tag round :type="form.payment_vip_free_download ? 'success' : 'default'">
|
||||
角色白名单免费:{{ form.payment_vip_free_download ? '已启用' : '未启用' }}
|
||||
</n-tag>
|
||||
<n-tag round type="info">
|
||||
Token TTL:10 分钟
|
||||
</n-tag>
|
||||
</n-space>
|
||||
</n-card>
|
||||
|
||||
<n-card class="aksrt-section-card">
|
||||
<div class="aksrt-section-header">
|
||||
<h3>下载门槛</h3>
|
||||
</div>
|
||||
<n-form :model="form" label-placement="left" label-width="180" class="aksrt-form">
|
||||
<n-form-item label="允许积分购买模式">
|
||||
<n-switch v-model:value="form.download_credit" />
|
||||
<template #feedback>
|
||||
<span class="aksrt-hint-text">开启后,文章 pay_modo=积分 可走收银台一次购买解锁;下载 token 不再按次扣积分。关闭时积分模式资源按免费/需登录策略处理。</span>
|
||||
</template>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item :label="`默认积分价(${currencyName})`">
|
||||
<n-input-number v-model:value="form.download_default_cost" :min="0" :max="100000" style="width: 180px;" />
|
||||
<template #feedback>
|
||||
<span class="aksrt-hint-text">仅作运营参考/兼容字段;实际价格以文章 _aksrt_pay 的积分价/现金价为准。角色白名单命中时免费下载。</span>
|
||||
</template>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-card>
|
||||
|
||||
<n-card class="aksrt-section-card">
|
||||
<div class="aksrt-section-header">
|
||||
<h3>付费内容策略</h3>
|
||||
</div>
|
||||
<n-form :model="form" label-placement="left" label-width="180" class="aksrt-form">
|
||||
<n-form-item label="受管内容类型">
|
||||
<n-input v-model:value="form.payment_paid_post_types" placeholder="post,course,doc" />
|
||||
<template #feedback>
|
||||
<span class="aksrt-hint-text">逗号分隔,标记纳入统一付费策略的内容类型。</span>
|
||||
</template>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="角色白名单免扣下载">
|
||||
<n-switch v-model:value="form.payment_vip_free_download" />
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="免扣角色列表" v-if="form.payment_vip_free_download">
|
||||
<n-input v-model:value="form.payment_vip_exempt_roles" placeholder="administrator,editor,vip" />
|
||||
<template #feedback>
|
||||
<span class="aksrt-hint-text">命中这些 WordPress role 的用户可免费下载(无需购买)。</span>
|
||||
</template>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="前台付费提示">
|
||||
<n-input
|
||||
v-model:value="form.payment_paid_catalog_note"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 3, maxRows: 6 }"
|
||||
placeholder="可填写资源购买须知、交付说明或人工确认提示。"
|
||||
/>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="人工交付备注">
|
||||
<n-input
|
||||
v-model:value="form.payment_manual_delivery_note"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 3, maxRows: 6 }"
|
||||
/>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-card>
|
||||
|
||||
<n-card class="aksrt-section-card">
|
||||
<n-alert type="info" :show-icon="false">
|
||||
当前收款模式:{{ gatewayModeLabel }}。充值、VIP、返佣和分成页均已提供稳定结构,订单和结算台账直接衔接这些字段。
|
||||
</n-alert>
|
||||
</n-card>
|
||||
|
||||
<div class="aksrt-form-actions">
|
||||
<n-button type="primary" :loading="saving" @click="handleSave">保存配置</n-button>
|
||||
</div>
|
||||
</n-spin>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, onMounted, reactive, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useMessage } from 'naive-ui'
|
||||
import api from '@/api'
|
||||
import PageHeader from '@/components/PageHeader.vue'
|
||||
|
||||
const router = useRouter()
|
||||
const message = useMessage()
|
||||
|
||||
const loading = ref(true)
|
||||
const saving = ref(false)
|
||||
const featureSnapshot = ref({})
|
||||
const creditSnapshot = ref({})
|
||||
const overview = ref({})
|
||||
|
||||
const form = reactive({
|
||||
download_credit: true,
|
||||
download_default_cost: 0,
|
||||
payment_paid_post_types: 'post',
|
||||
payment_vip_free_download: false,
|
||||
payment_vip_exempt_roles: '',
|
||||
payment_paid_catalog_note: '',
|
||||
payment_manual_delivery_note: '付费或人工确认内容请在订单备注中记录交付方式。',
|
||||
})
|
||||
|
||||
const currencyName = computed(() => overview.value.currency_name || creditSnapshot.value.currency_name || '积分')
|
||||
const gatewayModeLabel = computed(() => {
|
||||
const mode = overview.value.gateway?.mode || 'manual_review'
|
||||
if (mode === 'test_gateway') return '测试网关'
|
||||
if (mode === 'adapter_ready') return '适配器就绪'
|
||||
return '人工确认'
|
||||
})
|
||||
|
||||
function go(path) {
|
||||
router.push(path)
|
||||
}
|
||||
|
||||
function extractData(response) {
|
||||
return response?.data ?? response ?? {}
|
||||
}
|
||||
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const [featureRes, creditRes, schemaRes, overviewRes] = await Promise.all([
|
||||
api.getCmsFeatures(),
|
||||
api.getCreditSettings(),
|
||||
api.getSchemaPage('payment', 'paid'),
|
||||
api.getPaymentOverview(),
|
||||
])
|
||||
|
||||
const featureData = featureRes?.cms_features ?? featureRes?.data?.cms_features ?? {}
|
||||
const creditData = extractData(creditRes)
|
||||
const schemaData = extractData(schemaRes)
|
||||
|
||||
featureSnapshot.value = featureData
|
||||
creditSnapshot.value = creditData
|
||||
overview.value = extractData(overviewRes)
|
||||
|
||||
form.download_credit = featureData.download_credit !== false
|
||||
form.download_default_cost = Number(creditData.download_default_cost || 0)
|
||||
form.payment_paid_post_types = schemaData.payment_paid_post_types || 'post'
|
||||
form.payment_vip_free_download = !!schemaData.payment_vip_free_download
|
||||
form.payment_vip_exempt_roles = schemaData.payment_vip_exempt_roles || ''
|
||||
form.payment_paid_catalog_note = schemaData.payment_paid_catalog_note || ''
|
||||
form.payment_manual_delivery_note = schemaData.payment_manual_delivery_note || '付费或人工确认内容请在订单备注中记录交付方式。'
|
||||
} catch (error) {
|
||||
message.error(error.message || '加载下载/付费内容中心失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSave() {
|
||||
saving.value = true
|
||||
try {
|
||||
const nextFeatures = {
|
||||
...featureSnapshot.value,
|
||||
download_credit: form.download_credit,
|
||||
}
|
||||
const nextCredits = {
|
||||
...creditSnapshot.value,
|
||||
download_default_cost: Number(form.download_default_cost || 0),
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
api.saveCmsFeatures(nextFeatures),
|
||||
api.saveCreditSettings(nextCredits),
|
||||
api.saveSchemaPage('payment', 'paid', {
|
||||
payment_paid_post_types: form.payment_paid_post_types,
|
||||
payment_vip_free_download: form.payment_vip_free_download,
|
||||
payment_vip_exempt_roles: form.payment_vip_exempt_roles,
|
||||
payment_paid_catalog_note: form.payment_paid_catalog_note,
|
||||
payment_manual_delivery_note: form.payment_manual_delivery_note,
|
||||
}),
|
||||
])
|
||||
|
||||
featureSnapshot.value = nextFeatures
|
||||
creditSnapshot.value = nextCredits
|
||||
message.success('下载/付费内容中心已保存')
|
||||
} catch (error) {
|
||||
message.error(error.message || '保存失败')
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(load)
|
||||
</script>
|
||||
@@ -7,7 +7,6 @@
|
||||
:links="[
|
||||
{ label: '余额充值', path: '/payment/recharge' },
|
||||
{ label: '充值卡', path: '/payment/card-pass' },
|
||||
{ label: '付费内容', path: '/payment/paid' },
|
||||
]"
|
||||
>
|
||||
<template #before-form>
|
||||
|
||||
@@ -70,28 +70,6 @@
|
||||
</n-form>
|
||||
</n-card>
|
||||
|
||||
<!-- AI Moderation -->
|
||||
<n-card class="aksrt-section-card">
|
||||
<div class="aksrt-section-header">
|
||||
<h3>审核联动</h3>
|
||||
</div>
|
||||
<n-form :model="form" label-placement="left" label-width="200" class="aksrt-form">
|
||||
<n-form-item label="背景图接入 AI 审核">
|
||||
<n-switch v-model:value="form.ai_moderate_background" />
|
||||
<template #feedback>
|
||||
<span class="aksrt-hint-text">命中高风险时会阻断上传,并保留上一次背景图。</span>
|
||||
</template>
|
||||
</n-form-item>
|
||||
|
||||
<n-form-item label="投稿图片接入 AI 审核">
|
||||
<n-switch v-model:value="form.ai_moderate_submit" />
|
||||
<template #feedback>
|
||||
<span class="aksrt-hint-text">投稿中插入的图片也会经过内容安全审核。</span>
|
||||
</template>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
</n-card>
|
||||
|
||||
<div class="aksrt-form-actions">
|
||||
<n-button type="primary" :loading="saving" @click="handleSave">保存配置</n-button>
|
||||
</div>
|
||||
@@ -112,15 +90,12 @@ const message = useMessage()
|
||||
|
||||
const loading = ref(true)
|
||||
const saving = ref(false)
|
||||
const moderationSnapshot = ref({})
|
||||
|
||||
const form = reactive({
|
||||
avatar_max_size: 2,
|
||||
submit_image_max_size: 5,
|
||||
comment_image_max_size: 2,
|
||||
resource_max_size: 50,
|
||||
ai_moderate_background: true,
|
||||
ai_moderate_submit: false,
|
||||
})
|
||||
|
||||
const summaryItems = computed(() => [
|
||||
@@ -139,24 +114,15 @@ function goModeration() { router.push('/permissions/moderation') }
|
||||
async function load() {
|
||||
loading.value = true
|
||||
try {
|
||||
const [permissionRes, moderationRes] = await Promise.all([
|
||||
api.getPermissionsAttachmentSettings(),
|
||||
api.getPermissionsModerationSettings(),
|
||||
])
|
||||
const permissionRes = await api.getPermissionsAttachmentSettings()
|
||||
|
||||
const permission = permissionRes?.data ?? permissionRes ?? {}
|
||||
const moderation = moderationRes?.data ?? moderationRes ?? {}
|
||||
|
||||
// Map permission fields
|
||||
form.avatar_max_size = Number(permission.avatar_max_size || 2)
|
||||
form.submit_image_max_size = Number(permission.submit_image_max_size || 5)
|
||||
form.comment_image_max_size = Number(permission.comment_image_max_size || 2)
|
||||
form.resource_max_size = Number(permission.resource_max_size || 50)
|
||||
|
||||
form.ai_moderate_background = moderation.ai_moderate_background !== false
|
||||
form.ai_moderate_submit = !!moderation.ai_moderate_submit
|
||||
|
||||
moderationSnapshot.value = { ...moderation }
|
||||
} catch (error) {
|
||||
message.error(error.message || '加载附件权限失败')
|
||||
} finally {
|
||||
@@ -167,24 +133,12 @@ async function load() {
|
||||
async function handleSave() {
|
||||
saving.value = true
|
||||
try {
|
||||
await Promise.all([
|
||||
api.savePermissionsAttachmentSettings({
|
||||
avatar_max_size: form.avatar_max_size,
|
||||
submit_image_max_size: form.submit_image_max_size,
|
||||
comment_image_max_size: form.comment_image_max_size,
|
||||
resource_max_size: form.resource_max_size,
|
||||
}),
|
||||
api.savePermissionsModerationSettings({
|
||||
...moderationSnapshot.value,
|
||||
ai_moderate_background: form.ai_moderate_background,
|
||||
ai_moderate_submit: form.ai_moderate_submit,
|
||||
}),
|
||||
])
|
||||
moderationSnapshot.value = {
|
||||
...moderationSnapshot.value,
|
||||
ai_moderate_background: form.ai_moderate_background,
|
||||
ai_moderate_submit: form.ai_moderate_submit,
|
||||
}
|
||||
await api.savePermissionsAttachmentSettings({
|
||||
avatar_max_size: form.avatar_max_size,
|
||||
submit_image_max_size: form.submit_image_max_size,
|
||||
comment_image_max_size: form.comment_image_max_size,
|
||||
resource_max_size: form.resource_max_size,
|
||||
})
|
||||
message.success('附件治理配置已保存')
|
||||
} catch (error) {
|
||||
message.error(error.message || '保存失败')
|
||||
|
||||
Reference in new issue
Block a user