<script setup lang="ts">
|
import { nextTick, ref, watch } from 'vue'
|
import { useMessage } from 'naive-ui'
|
import {
|
getVehicleDescription,
|
saveVehicleDescription,
|
} from '@/service/api/contentCenter'
|
// 车辆运维字段优化:整备标准说明收敛为单一富文本后,不再使用 VehiclePrepareForm(子分项表单)
|
// 该组件文件暂予保留,如后续确认无回滚需求可一并删除
|
import SimpleRichTextForm from './components/SimpleRichTextForm.vue'
|
import AgreementListForm from './components/AgreementListForm.vue'
|
|
const activeTab = ref('prepare')
|
const message = useMessage()
|
const loading = ref(false)
|
|
const tabs = [
|
{ key: 'prepare', label: '车辆整备' },
|
{ key: 'charge', label: '车辆充电' },
|
{ key: 'inspect', label: '车辆检测' },
|
{ key: 'bodyClean', label: '车身清洁' },
|
{ key: 'maintenance', label: '车辆保养' },
|
{ key: 'insurance', label: '保险说明' },
|
{ key: 'annual', label: '年检说明' },
|
{ key: 'qualification', label: '运营资质' },
|
{ key: 'opsAppNotice', label: '登录协议' },
|
]
|
|
const contentFormRefs = ref<Record<string, any>>({})
|
|
async function handleSave() {
|
try {
|
const currentForm = contentFormRefs.value[activeTab.value]
|
if (currentForm) {
|
await currentForm.validate()
|
const data = currentForm.getData()
|
let saveRes: any = null
|
|
if (['prepare', 'charge', 'inspect', 'bodyClean', 'insurance', 'annual', 'maintenance', 'qualification'].includes(activeTab.value)) {
|
const typeMap: Record<string, number> = {
|
// 车辆运维字段优化:车辆整备标准说明收敛为单一富文本,写入新增的 descriptionType=12
|
// (原按胎压1/灯光2/舱内清洁4 三个子分项配置,收敛后不再区分模块)
|
prepare: 12,
|
charge: 6,
|
inspect: 7,
|
// 车辆清洁标准说明复用既有 type 3(车身标识及清洁),不新增类型,避免与存量文案数据分裂
|
bodyClean: 3,
|
insurance: 8,
|
annual: 9,
|
maintenance: 10,
|
qualification: 11,
|
}
|
const t = typeMap[activeTab.value]
|
saveRes = await saveVehicleDescription({ descriptionType: t, descriptionContent: data.content || '' })
|
}
|
if (saveRes && saveRes.code === 200) {
|
message.success('保存成功')
|
}
|
else if (saveRes) {
|
message.error('保存失败')
|
}
|
}
|
}
|
catch {
|
// message.error('验证失败')
|
}
|
}
|
|
function handleCancel() {
|
|
}
|
|
async function loadContent(tabKey: string) {
|
try {
|
loading.value = true
|
await nextTick()
|
let currentForm = contentFormRefs.value[tabKey]
|
if (!currentForm || typeof currentForm.setData !== 'function') {
|
await nextTick()
|
currentForm = contentFormRefs.value[tabKey]
|
}
|
if (!currentForm || typeof currentForm.setData !== 'function') {
|
loading.value = false
|
return
|
}
|
|
if (['prepare', 'charge', 'inspect', 'bodyClean', 'insurance', 'annual', 'maintenance', 'qualification'].includes(tabKey)) {
|
const typeMap: Record<string, number> = {
|
// 车辆运维字段优化:整备读取收敛后的单一富文本 type=12
|
prepare: 12,
|
charge: 6,
|
inspect: 7,
|
bodyClean: 3,
|
insurance: 8,
|
annual: 9,
|
maintenance: 10,
|
qualification: 11,
|
}
|
const t = typeMap[tabKey]
|
const res = await getVehicleDescription(t)
|
if (res && res.code === 200) {
|
currentForm.setData({ content: res.data?.descriptionContent || '' })
|
}
|
}
|
}
|
finally {
|
loading.value = false
|
}
|
}
|
|
watch(activeTab, (v) => {
|
loadContent(v)
|
}, { immediate: true })
|
</script>
|
|
<template>
|
<div class="h-full flex flex-col justify-between ">
|
<div class="p-12px content-page">
|
<n-card>
|
<div>
|
<div class="head">
|
运维APP内容管理
|
</div>
|
<n-tabs
|
v-model:value="activeTab"
|
type="line"
|
size="large"
|
:theme-overrides="{
|
tabTextColor: '#666666',
|
tabTextColorActive: '#0068FF',
|
tabBorderColorActive: '#0068FF',
|
tabBorderRadius: '4px',
|
tabPaddingHorizontal: '16px',
|
tabPaddingVertical: '8px',
|
}"
|
class="tab-container"
|
>
|
<n-tab-pane v-for="tab in tabs" :key="tab.key" :name="tab.key" :tab="tab.label">
|
<div class="tab-scroll-area">
|
<!--
|
车辆运维字段优化:车辆整备标准说明已收敛为单一富文本(descriptionType=12),
|
与车辆清洁(3)/车辆检测(7)等一致复用 SimpleRichTextForm,不再按子分项配置
|
-->
|
<SimpleRichTextForm
|
v-if="['prepare', 'charge', 'inspect', 'bodyClean', 'insurance', 'annual', 'maintenance', 'qualification'].includes(tab.key)"
|
:ref="(el) => { if (el) contentFormRefs[tab.key] = el }"
|
/>
|
<AgreementListForm
|
v-else-if="tab.key === 'opsAppNotice'"
|
:ref="(el) => { if (el) contentFormRefs[tab.key] = el }"
|
type="ops"
|
/>
|
</div>
|
</n-tab-pane>
|
</n-tabs>
|
</div>
|
</n-card>
|
</div>
|
|
<div v-if="activeTab !== 'opsAppNotice'" v-permission="202642905" class="footer flex justify-end " style="background-color: white; padding: 16px 24px; border-radius: 8px; box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.05);">
|
<n-button style="padding: 8px 24px; border-radius: 4px; font-size: 14px;margin-right: 12px;" @click="handleCancel">
|
取消
|
</n-button>
|
<n-button v-permission="202642905" type="primary" style="padding: 8px 24px; border-radius: 4px; font-size: 14px;" @click="handleSave">
|
保存
|
</n-button>
|
</div>
|
</div>
|
</template>
|
|
<style scoped lang="scss">
|
.content-page{
|
height: calc(100vh - 302px - 28px);
|
}
|
|
.tab-scroll-area {
|
height: calc(100vh - 304px - 28px);
|
overflow-y: auto;
|
overflow-x: hidden;
|
padding-bottom: 40px;
|
scrollbar-width: thin;
|
scrollbar-color: rgba(23, 31, 38, 0.2) transparent;
|
}
|
|
.tab-scroll-area::-webkit-scrollbar {
|
width: 6px;
|
}
|
|
.tab-scroll-area::-webkit-scrollbar-thumb {
|
border-radius: 999px;
|
background: rgba(23, 31, 38, 0.2);
|
}
|
|
.tab-scroll-area::-webkit-scrollbar-track {
|
background: transparent;
|
}
|
|
.tab-scroll-area::-webkit-scrollbar-thumb:hover {
|
background: rgba(23, 31, 38, 0.3);
|
}
|
|
.tab-container {
|
// border-bottom: 1px solid #e8e8e8;
|
}
|
:deep(.n-tabs-wrapper){
|
padding: 0 10px;
|
}
|
|
:deep(.n-tabs-nav--line .n-tabs-tab) {
|
font-size: 14px;
|
font-weight: 500;
|
transition: all 0.3s ease;
|
}
|
|
:deep(.n-tabs-nav--line .n-tabs-tab:hover) {
|
color: #0068FF;
|
}
|
|
:deep(.n-tabs-nav--line .n-tabs-tab--active) {
|
font-weight: 600;
|
}
|
|
:deep(.n-tabs-nav--line .n-tabs-tab--active::after) {
|
height: 2px;
|
background-color: #0068FF;
|
border-radius: 2px;
|
}
|
|
/* 修复富文本编辑器超链接弹窗被遮挡的问题 */
|
.ql-tooltip {
|
z-index: 2000 !important;
|
left:-10px !important;
|
}
|
|
/* 允许内容溢出,防止 tooltip 被裁剪 */
|
.n-tabs .n-tab-pane,
|
.n-card > .n-card__content {
|
overflow: visible !important;
|
}
|
.n-tabs-tab__label{
|
font-size: 14px;
|
}
|
.head {
|
font-family: PingFang SC;
|
font-size: 16px;
|
font-weight: 600;
|
line-height: 24px;
|
letter-spacing: normal;
|
color: #171F26;
|
position: relative;
|
text-indent: 11px;
|
margin-bottom: 16px;
|
|
&::before {
|
content: '';
|
position: absolute;
|
top: 50%;
|
left: 0;
|
transform: translateY(-50%);
|
width: 3px;
|
height: 14px;
|
z-index: 0;
|
border-radius: 3px;
|
background: #0068FF;
|
}
|
|
}
|
.footer {
|
position: absolute;
|
bottom: 0;
|
left: 0;
|
width: 100%;
|
height: 64px;
|
background-color: #fff;
|
box-shadow: 0px 0px 5px 0px rgba(23, 31, 38, 0.05);
|
padding: 16px 24px;
|
|
}
|
</style>
|