first
This commit is contained in:
172
admin-web/src/pages/content/policy.vue
Normal file
172
admin-web/src/pages/content/policy.vue
Normal file
@@ -0,0 +1,172 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { adminApi, type AdminContentPolicyConfig, type AdminContentPolicyItem, type AdminHelpArticleItem } from "../../api/admin";
|
||||
import { createPolicyItem, normalizePolicyConfig } from "./shared";
|
||||
|
||||
const loading = ref(false);
|
||||
const saving = ref(false);
|
||||
const articles = ref<AdminHelpArticleItem[]>([]);
|
||||
const policyForm = ref<AdminContentPolicyConfig>({
|
||||
legal_entries: [],
|
||||
appraisal_agreements: [],
|
||||
});
|
||||
|
||||
const helpArticleOptions = computed(() =>
|
||||
articles.value.map((item) => ({
|
||||
label: `${item.title}(${item.category_text})`,
|
||||
value: item.id,
|
||||
})),
|
||||
);
|
||||
|
||||
async function fetchPolicy() {
|
||||
loading.value = true;
|
||||
try {
|
||||
const [policyResult, articleResult] = await Promise.all([
|
||||
adminApi.getContentPolicy(),
|
||||
adminApi.getHelpArticles(),
|
||||
]);
|
||||
policyForm.value = normalizePolicyConfig(policyResult.data.policy_config);
|
||||
articles.value = articleResult.data.list;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
ElMessage.error("协议与说明加载失败");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function addPolicyItem(section: "legal_entries" | "appraisal_agreements") {
|
||||
policyForm.value[section].push(createPolicyItem());
|
||||
}
|
||||
|
||||
function removePolicyItem(section: "legal_entries" | "appraisal_agreements", index: number) {
|
||||
policyForm.value[section].splice(index, 1);
|
||||
}
|
||||
|
||||
function bindPolicyArticle(item: AdminContentPolicyItem, articleId: number) {
|
||||
item.article_id = Number(articleId || 0);
|
||||
item.target_url = item.article_id > 0 ? `/pages/help/detail?id=${item.article_id}` : "";
|
||||
}
|
||||
|
||||
async function savePolicy() {
|
||||
saving.value = true;
|
||||
try {
|
||||
const response = await adminApi.saveContentPolicy(policyForm.value);
|
||||
policyForm.value = normalizePolicyConfig(response.data.policy_config);
|
||||
ElMessage.success("协议与说明已保存");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
ElMessage.error("协议与说明保存失败");
|
||||
} finally {
|
||||
saving.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(fetchPolicy);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-card class="panel-card" shadow="never" v-loading="loading">
|
||||
<div class="filters-row" style="justify-content: space-between;">
|
||||
<div>
|
||||
<div style="font-size: 16px; font-weight: 700;">协议与说明</div>
|
||||
<div style="color: var(--admin-text-subtle); margin-top: 6px;">
|
||||
维护设置页说明入口,以及下单确认页展示的服务协议、鉴定须知与隐私政策。
|
||||
</div>
|
||||
</div>
|
||||
<el-button type="primary" :loading="saving" @click="savePolicy">保存协议与说明</el-button>
|
||||
</div>
|
||||
|
||||
<el-form label-position="top">
|
||||
<el-divider content-position="left">设置页说明入口</el-divider>
|
||||
<div v-for="(item, index) in policyForm.legal_entries" :key="`legal-${index}`" class="content-block">
|
||||
<div class="content-block__header">
|
||||
<div class="content-block__title">入口 {{ index + 1 }}</div>
|
||||
<el-button link type="danger" @click="removePolicyItem('legal_entries', index)">删除</el-button>
|
||||
</div>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="6"><el-form-item label="编码"><el-input v-model="item.code" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="标题"><el-input v-model="item.title" /></el-form-item></el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="绑定文章">
|
||||
<el-select
|
||||
v-model="item.article_id"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 100%"
|
||||
placeholder="请选择帮助中心文章"
|
||||
@change="bindPolicyArticle(item, Number($event || 0))"
|
||||
>
|
||||
<el-option v-for="option in helpArticleOptions" :key="option.value" :label="option.label" :value="option.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="详情页链接">
|
||||
<el-input v-model="item.target_url" placeholder="/pages/help/detail?id=12" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24"><el-form-item label="说明"><el-input v-model="item.desc" /></el-form-item></el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-button plain @click="addPolicyItem('legal_entries')">新增设置入口</el-button>
|
||||
|
||||
<el-divider content-position="left">下单确认协议</el-divider>
|
||||
<div v-for="(item, index) in policyForm.appraisal_agreements" :key="`agreement-${index}`" class="content-block">
|
||||
<div class="content-block__header">
|
||||
<div class="content-block__title">协议 {{ index + 1 }}</div>
|
||||
<el-button link type="danger" @click="removePolicyItem('appraisal_agreements', index)">删除</el-button>
|
||||
</div>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="6"><el-form-item label="编码"><el-input v-model="item.code" /></el-form-item></el-col>
|
||||
<el-col :span="6"><el-form-item label="标题"><el-input v-model="item.title" /></el-form-item></el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="绑定文章">
|
||||
<el-select
|
||||
v-model="item.article_id"
|
||||
clearable
|
||||
filterable
|
||||
style="width: 100%"
|
||||
placeholder="请选择帮助中心文章"
|
||||
@change="bindPolicyArticle(item, Number($event || 0))"
|
||||
>
|
||||
<el-option v-for="option in helpArticleOptions" :key="option.value" :label="option.label" :value="option.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="详情页链接">
|
||||
<el-input v-model="item.target_url" placeholder="/pages/help/detail?id=12" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24"><el-form-item label="说明"><el-input v-model="item.desc" /></el-form-item></el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-button plain @click="addPolicyItem('appraisal_agreements')">新增协议项</el-button>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.content-block {
|
||||
margin-bottom: 18px;
|
||||
padding: 16px 18px;
|
||||
border: 1px solid var(--admin-border);
|
||||
border-radius: 14px;
|
||||
background: linear-gradient(180deg, rgba(255, 251, 244, 0.7) 0%, rgba(255, 255, 255, 0.96) 100%);
|
||||
}
|
||||
|
||||
.content-block__header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.content-block__title {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: var(--admin-text);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user