2025-07-18 08:22:28 +00:00
|
|
|
|
<template>
|
2025-08-01 08:33:33 +00:00
|
|
|
|
|
|
|
|
|
<div class="editor-page" v-loading="addLoading" :class="{ 'no-scroll': addLoading }">
|
|
|
|
|
|
|
|
|
|
<h2 style="margin-bottom: 20px;">{{ $t('backendSystem.modifyDocument') || '修改文档' }}</h2>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
<!-- 页面头部 -->
|
|
|
|
|
<div class="page-header">
|
|
|
|
|
<div class="header-left">
|
|
|
|
|
<div class="title-section">
|
|
|
|
|
<i class="el-icon-edit-outline title-icon"></i>
|
2025-08-01 08:33:33 +00:00
|
|
|
|
<h1 class="page-title">{{ $t('backendSystem.wangeditor') || 'wangeditor 富文本文档编辑器' }}</h1>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
</div>
|
2025-08-01 08:33:33 +00:00
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
</div>
|
|
|
|
|
<div class="header-actions">
|
2025-08-01 08:33:33 +00:00
|
|
|
|
<el-button
|
|
|
|
|
type="primary"
|
|
|
|
|
icon="el-icon-link"
|
|
|
|
|
@click="handleInsertAnchor"
|
|
|
|
|
>
|
|
|
|
|
{{ $t('backendSystem.insertAnchor') || '插入锚点' }}
|
|
|
|
|
</el-button>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
<el-button type="info" icon="el-icon-view" @click="handlePreview">
|
2025-08-01 08:33:33 +00:00
|
|
|
|
{{ $t('backendSystem.previewDocument') || '预览文档' }}
|
2025-07-25 08:39:37 +00:00
|
|
|
|
</el-button>
|
|
|
|
|
<el-button type="success" icon="el-icon-document" @click="handleSave">
|
2025-08-01 08:33:33 +00:00
|
|
|
|
{{ $t('backendSystem.saveDocument') || '保存文档' }}
|
2025-07-25 08:39:37 +00:00
|
|
|
|
</el-button>
|
|
|
|
|
<el-button
|
|
|
|
|
type="warning"
|
|
|
|
|
icon="el-icon-upload2"
|
|
|
|
|
@click="handelAddDocument"
|
|
|
|
|
>
|
2025-08-01 08:33:33 +00:00
|
|
|
|
{{ $t('backendSystem.modifyDocument') || '修改文档' }}
|
2025-07-25 08:39:37 +00:00
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 文档配置区域 -->
|
|
|
|
|
<div class="config-section">
|
|
|
|
|
<div class="section-header">
|
|
|
|
|
<i class="el-icon-setting"></i>
|
2025-08-01 08:33:33 +00:00
|
|
|
|
<span>{{ $t('backendSystem.documentConfiguration') || '文档配置' }}</span>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="config-content">
|
|
|
|
|
<div class="config-row">
|
|
|
|
|
<div class="config-item">
|
2025-08-01 08:33:33 +00:00
|
|
|
|
<label>{{ $t('backendSystem.navigationTitle') || '导航标题' }}</label>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
<el-input
|
|
|
|
|
v-model="addParams.title"
|
2025-08-01 08:33:33 +00:00
|
|
|
|
:placeholder="$t('backendSystem.pleaseInputDocumentTitle') || '请输入文档标题'"
|
2025-07-25 08:39:37 +00:00
|
|
|
|
@input="handleAutoSave"
|
|
|
|
|
size="medium"
|
|
|
|
|
/>
|
2025-07-18 08:22:28 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
<div class="config-item">
|
2025-08-01 08:33:33 +00:00
|
|
|
|
<label class="required">{{ $t('backendSystem.documentType') || '文档类型' }}</label>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
<el-cascader
|
|
|
|
|
:options="TypeList"
|
|
|
|
|
v-model="typeArray"
|
|
|
|
|
@change="handleAutoSaveType(typeArray)"
|
|
|
|
|
clearable
|
2025-08-01 08:33:33 +00:00
|
|
|
|
:placeholder="$t('backendSystem.pleaseSelectDocumentType') || '请选择文档类型'"
|
2025-07-25 08:39:37 +00:00
|
|
|
|
:props="{
|
|
|
|
|
label: 'label',
|
|
|
|
|
value: 'value',
|
|
|
|
|
children: 'children',
|
|
|
|
|
}"
|
|
|
|
|
/>
|
2025-07-18 08:22:28 +00:00
|
|
|
|
</div>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
</div>
|
2025-07-18 08:22:28 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
<div class="config-content">
|
|
|
|
|
<div class="config-row">
|
|
|
|
|
<div class="config-item">
|
2025-08-01 08:33:33 +00:00
|
|
|
|
<label>{{ $t('backendSystem.titleImageAddress') || '标题图片地址' }}</label>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
<el-input
|
|
|
|
|
v-model="addParams.titleUrl"
|
2025-08-01 08:33:33 +00:00
|
|
|
|
:placeholder="$t('backendSystem.pleaseInputImageAddress') || '请输入图片地址'"
|
2025-07-25 08:39:37 +00:00
|
|
|
|
@input="handleAutoSave"
|
|
|
|
|
size="medium"
|
|
|
|
|
/>
|
2025-07-18 08:22:28 +00:00
|
|
|
|
</div>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
|
|
|
|
|
<div class="config-item">
|
2025-08-01 08:33:33 +00:00
|
|
|
|
<label>{{ $t('backendSystem.articleAccessAddress') || '文章访问地址' }}</label>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
<el-input
|
|
|
|
|
v-model="addParams.articleUrl"
|
2025-08-01 08:33:33 +00:00
|
|
|
|
:placeholder="$t('backendSystem.pleaseInputAccessAddress') || '请输入访问地址'"
|
2025-07-25 08:39:37 +00:00
|
|
|
|
@input="handleAutoSave"
|
|
|
|
|
size="medium"
|
|
|
|
|
/>
|
2025-07-18 08:22:28 +00:00
|
|
|
|
</div>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
</div>
|
2025-07-18 08:22:28 +00:00
|
|
|
|
</div>
|
2025-08-01 08:33:33 +00:00
|
|
|
|
<div class="config-content">
|
|
|
|
|
<div class="config-row">
|
|
|
|
|
<div class="config-item">
|
|
|
|
|
<label >{{
|
|
|
|
|
$t("backendSystem.coin2") || "币种"
|
|
|
|
|
}}</label>
|
|
|
|
|
<el-select
|
|
|
|
|
class="input"
|
|
|
|
|
size="middle"
|
|
|
|
|
ref="screen"
|
|
|
|
|
@change="changeScreen(screenCurrency)"
|
|
|
|
|
v-model="screenCurrency"
|
|
|
|
|
|
|
|
|
|
:placeholder="$t(`backendSystem.selectCurrency`)"
|
|
|
|
|
>
|
|
|
|
|
<el-option
|
|
|
|
|
v-for="item in currencyList"
|
|
|
|
|
:key="item.value"
|
|
|
|
|
:label="item.label"
|
|
|
|
|
:value="item.value"
|
|
|
|
|
>
|
|
|
|
|
|
|
|
|
|
<div style="display: flex; align-items: center">
|
|
|
|
|
<img :src="item.imgUrl" style="float: left; width: 20px" />
|
|
|
|
|
<span style="float: left; margin-left: 5px">
|
|
|
|
|
{{ item.label }}</span
|
|
|
|
|
>
|
|
|
|
|
</div>
|
|
|
|
|
</el-option>
|
|
|
|
|
</el-select>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
</div>
|
2025-07-18 08:22:28 +00:00
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
<!-- 编辑器区域 -->
|
|
|
|
|
<div class="editor-section">
|
|
|
|
|
<div class="section-header">
|
|
|
|
|
<i class="el-icon-edit-outline"></i>
|
2025-08-01 08:33:33 +00:00
|
|
|
|
<span>{{ $t('backendSystem.richTextEditor') || '富文本编辑器' }}</span>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
</div>
|
|
|
|
|
<div class="editor-container">
|
2025-08-01 08:33:33 +00:00
|
|
|
|
<div ref="editor" style="height: 600px"></div>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-08-01 08:33:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
|
|
|
|
|
<!-- 预览文档对话框 -->
|
|
|
|
|
<el-dialog
|
2025-08-01 08:33:33 +00:00
|
|
|
|
:title="$t('backendSystem.documentPreview') || '文档预览'"
|
2025-07-25 08:39:37 +00:00
|
|
|
|
:visible.sync="previewVisible"
|
|
|
|
|
width="80%"
|
|
|
|
|
:before-close="handlePreviewClose"
|
|
|
|
|
class="preview-dialog wangeditor-preview"
|
|
|
|
|
>
|
|
|
|
|
<div class="preview-content">
|
2025-08-01 08:33:33 +00:00
|
|
|
|
<div v-html="addParams.content" class="dynamic-content"></div>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
|
|
|
|
|
<div v-if="!addParams.content" class="preview-empty">
|
|
|
|
|
<i class="el-icon-document"></i>
|
2025-08-01 08:33:33 +00:00
|
|
|
|
<p>{{ $t('backendSystem.noContent') || '暂无内容' }}</p>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
</div>
|
2025-07-18 08:22:28 +00:00
|
|
|
|
</div>
|
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
<span slot="footer" class="dialog-footer">
|
2025-08-01 08:33:33 +00:00
|
|
|
|
<el-button @click="previewVisible = false">{{ $t('backendSystem.close') || '关闭' }}</el-button>
|
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
</span>
|
|
|
|
|
</el-dialog>
|
2025-07-18 08:22:28 +00:00
|
|
|
|
</div>
|
2025-08-01 08:33:33 +00:00
|
|
|
|
|
2025-07-18 08:22:28 +00:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
2025-07-25 08:39:37 +00:00
|
|
|
|
import Vue from "vue";
|
2025-08-01 08:33:33 +00:00
|
|
|
|
import E from "wangeditor";
|
2025-07-25 08:39:37 +00:00
|
|
|
|
import { updateDocument } from "../../../api/documentManagement";
|
|
|
|
|
import Index from "./index";
|
2025-07-18 08:22:28 +00:00
|
|
|
|
export default Vue.extend({
|
|
|
|
|
mixins: [Index],
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
editor: null,
|
2025-08-01 08:33:33 +00:00
|
|
|
|
html: "", // 编辑器内容
|
|
|
|
|
hasSetEditorContent: false, // 避免重复 set 内容
|
2025-07-25 08:39:37 +00:00
|
|
|
|
mode: "default",
|
|
|
|
|
addParams: {
|
|
|
|
|
title: "",
|
|
|
|
|
content: "",
|
|
|
|
|
type: "",
|
|
|
|
|
lang: "",
|
|
|
|
|
titleUrl: "",
|
|
|
|
|
articleUrl: "",
|
2025-08-01 08:33:33 +00:00
|
|
|
|
childType: "",
|
|
|
|
|
coin: "",
|
2025-07-18 08:22:28 +00:00
|
|
|
|
},
|
2025-07-25 08:39:37 +00:00
|
|
|
|
lastSaveTime: "",
|
2025-07-18 08:22:28 +00:00
|
|
|
|
autoSaveTimer: null,
|
|
|
|
|
isSaving: false, // 新增:控制自动保存提示的显示
|
|
|
|
|
previewVisible: false, // 新增:控制预览对话框的显示
|
2025-07-25 08:39:37 +00:00
|
|
|
|
currentTime: "", // 新增:记录预览时间
|
|
|
|
|
TypeList: [
|
|
|
|
|
// {
|
|
|
|
|
// value: "1",
|
|
|
|
|
// label: "服务条款",
|
|
|
|
|
// },
|
|
|
|
|
// {
|
|
|
|
|
// value: "2",
|
|
|
|
|
// label: "api文档",
|
|
|
|
|
// },
|
|
|
|
|
// {
|
|
|
|
|
// value: "3",
|
|
|
|
|
// label: "挖矿教程",
|
|
|
|
|
// },
|
|
|
|
|
// {
|
|
|
|
|
// value: "0",
|
|
|
|
|
// label: "其他",
|
|
|
|
|
// },
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
addLoading: false,
|
|
|
|
|
typeArray: [],
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
mounted() {
|
|
|
|
|
try {
|
|
|
|
|
this.TypeList = JSON.parse(localStorage.getItem("TypeList"));
|
2025-08-01 08:33:33 +00:00
|
|
|
|
this.TypeList = this.TypeList.map((item) => ({
|
|
|
|
|
// 翻译label
|
2025-07-25 08:39:37 +00:00
|
|
|
|
...item,
|
|
|
|
|
label: this.$t(item.label),
|
|
|
|
|
children: item.children
|
|
|
|
|
? item.children.map((child) => ({
|
|
|
|
|
...child,
|
|
|
|
|
label: this.$t(child.label),
|
|
|
|
|
}))
|
|
|
|
|
: undefined,
|
|
|
|
|
}));
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.log(error);
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
2025-07-25 08:39:37 +00:00
|
|
|
|
|
|
|
|
|
// 先恢复数据
|
|
|
|
|
this.loadFromLocalStorage();
|
|
|
|
|
|
|
|
|
|
// 添加页面卸载前的保存保护
|
|
|
|
|
window.addEventListener("beforeunload", this.handleBeforeUnload);
|
|
|
|
|
|
|
|
|
|
// 延迟设置默认内容,避免覆盖恢复的数据
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
if (!this.addParams.content) {
|
|
|
|
|
this.html = "<p>模拟 Ajax 异步设置内容 HTML</p>";
|
|
|
|
|
}
|
|
|
|
|
}, 1500);
|
|
|
|
|
|
2025-08-01 08:33:33 +00:00
|
|
|
|
this.editor = new E(this.$refs.editor);
|
|
|
|
|
this.editor.config.height = 600;
|
|
|
|
|
this.editor.config.onchange = (html) => {
|
|
|
|
|
this.html = html;
|
|
|
|
|
this.addParams.content = html;
|
|
|
|
|
};
|
|
|
|
|
//配置颜色
|
|
|
|
|
this.editor.config.colors = [
|
|
|
|
|
`#651FFF`,
|
|
|
|
|
`#FF4081`,
|
|
|
|
|
`#FF9900`,
|
|
|
|
|
`#FFC107`,
|
|
|
|
|
`#FF5722`,
|
|
|
|
|
`#9C27B0`,
|
|
|
|
|
`#673AB7`,
|
|
|
|
|
`#3F51B5`,
|
|
|
|
|
"#000000", // 黑色
|
|
|
|
|
"#ffffff", // 白色
|
|
|
|
|
"#eeece0", // 浅米色
|
|
|
|
|
"#1c487f", // 深蓝
|
|
|
|
|
"#4d80bf", // 蓝色
|
|
|
|
|
"#c24f4a", // 红色
|
|
|
|
|
"#8baa4a", // 绿色
|
|
|
|
|
"#a96b59", // 棕色
|
|
|
|
|
"#2b2b2b", // 深灰
|
|
|
|
|
"#b6975a", // 金色
|
|
|
|
|
"#5b9bd5", // 天蓝
|
|
|
|
|
"#70ad47", // 草绿
|
|
|
|
|
"#ed7d31", // 橙色
|
|
|
|
|
"#ffc000", // 黄色
|
|
|
|
|
"#7030a0", // 紫色
|
|
|
|
|
"#f4b084", // 浅橙
|
|
|
|
|
"#bdd7ee", // 浅蓝
|
|
|
|
|
"#a9d08e", // 浅绿
|
|
|
|
|
"#ffe699", // 浅黄
|
|
|
|
|
"#d9d9d9", // 浅灰
|
|
|
|
|
"#f8cbad", // 浅棕
|
|
|
|
|
"#e2efda", // 淡绿
|
|
|
|
|
"#fff2cc", // 淡黄
|
|
|
|
|
"#dbe5f1", // 淡蓝
|
|
|
|
|
"#e4dfec", // 淡紫
|
|
|
|
|
"#fbeee6", // 淡橙
|
|
|
|
|
"#f6f6f6", // 极浅灰
|
|
|
|
|
"#ff0000", // 纯红
|
|
|
|
|
"#00b050", // 纯绿
|
|
|
|
|
"#0070c0", // 纯蓝
|
|
|
|
|
"#7030a0", // 纯紫
|
|
|
|
|
"#ff9900", // 纯橙
|
|
|
|
|
"#808080", // 中灰
|
|
|
|
|
];
|
|
|
|
|
//配置字体
|
|
|
|
|
this.editor.config.fontNames = [
|
|
|
|
|
// 对象形式 v4.6.16
|
|
|
|
|
{name:"黑体",value:"黑体"},
|
|
|
|
|
{name:"绝绝字体",value:"Times New Roman"},
|
|
|
|
|
// 字符串形式
|
|
|
|
|
'黑体',
|
|
|
|
|
'仿宋',
|
|
|
|
|
'楷体',
|
|
|
|
|
'标楷体',
|
|
|
|
|
'华文仿宋',
|
|
|
|
|
'华文楷体',
|
|
|
|
|
'宋体',
|
|
|
|
|
'微软雅黑',
|
|
|
|
|
'Arial',
|
|
|
|
|
'Tahoma',
|
|
|
|
|
'Verdana',
|
|
|
|
|
'Times New Roman',
|
|
|
|
|
'Courier New',
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// 不自定义菜单,使用官方默认菜单栏
|
|
|
|
|
this.editor.create();
|
|
|
|
|
// 只在初始化时 set 一次内容
|
|
|
|
|
if (this.addParams.content && !this.hasSetEditorContent) {
|
|
|
|
|
this.editor.txt.html(this.addParams.content);
|
|
|
|
|
this.html = this.addParams.content;
|
|
|
|
|
this.hasSetEditorContent = true;
|
|
|
|
|
}
|
2025-07-18 08:22:28 +00:00
|
|
|
|
},
|
|
|
|
|
methods: {
|
2025-07-25 08:39:37 +00:00
|
|
|
|
async fetchUpdateDocument(params) {
|
|
|
|
|
this.setLoading("addLoading", true);
|
|
|
|
|
const res = await updateDocument(params);
|
|
|
|
|
if (res && res.code == 200) {
|
|
|
|
|
this.$message.success(this.$t("backendSystem.updateSuccess"));
|
|
|
|
|
this.$router.push({ path: `/${this.$i18n.locale}/documentManagement` });
|
|
|
|
|
}
|
|
|
|
|
this.setLoading("addLoading", false);
|
|
|
|
|
},
|
|
|
|
|
|
2025-08-01 08:33:33 +00:00
|
|
|
|
/**
|
|
|
|
|
* 编辑器创建后回调,确保 this.editor 正确赋值
|
|
|
|
|
* @param {Object} editor wangEditor 实例
|
|
|
|
|
*/
|
2025-07-18 08:22:28 +00:00
|
|
|
|
onCreated(editor) {
|
2025-08-01 08:33:33 +00:00
|
|
|
|
this.editor = editor;
|
|
|
|
|
console.log("编辑器已初始化", this.editor);
|
2025-07-18 08:22:28 +00:00
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
// 编辑器创建后,如果有恢复的内容,设置到编辑器中
|
|
|
|
|
if (this.addParams.content) {
|
|
|
|
|
this.$nextTick(() => {
|
2025-08-01 08:33:33 +00:00
|
|
|
|
this.editor.txt.html(this.addParams.content);
|
2025-07-25 08:39:37 +00:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
2025-07-18 08:22:28 +00:00
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
handelAddDocument() {
|
2025-08-01 08:33:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!this.addParams.type || this.addParams.type == "0") {
|
2025-07-25 08:39:37 +00:00
|
|
|
|
this.$message({
|
2025-08-01 08:33:33 +00:00
|
|
|
|
message: this.$t('backendSystem.pleaseInputType') || '请填写文档类型',
|
2025-07-25 08:39:37 +00:00
|
|
|
|
type: "warning",
|
|
|
|
|
duration: 4000,
|
|
|
|
|
showClose: true,
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-07-18 08:22:28 +00:00
|
|
|
|
|
2025-08-01 08:33:33 +00:00
|
|
|
|
console.log(this.screenCurrency, "this.screenCurrency",this.addParams.type);
|
|
|
|
|
|
|
|
|
|
if (this.addParams.type == "1" && !this.screenCurrency) {
|
|
|
|
|
this.$message({
|
|
|
|
|
message:
|
|
|
|
|
this.$t("backendSystem.pleaseSelectCurrency2") ||
|
|
|
|
|
"添加挖矿教程,请选择币种",
|
|
|
|
|
type: "warning",
|
|
|
|
|
duration: 4000,
|
|
|
|
|
showClose: true,
|
|
|
|
|
});
|
|
|
|
|
return;
|
2025-07-25 08:39:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2025-08-01 08:33:33 +00:00
|
|
|
|
if (this.addParams.content) {
|
|
|
|
|
//锚点定位的A标签 去掉target="_blank"
|
|
|
|
|
this.addParams.content = this.addParams.content.replace(
|
|
|
|
|
/<a([^>]*href="#[^"]*")[^>]*>/gi,
|
|
|
|
|
function (match) {
|
|
|
|
|
return match.replace(/\s*target="_blank"/gi, "");
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.addParams.coin = this.screenCurrency
|
|
|
|
|
|
|
|
|
|
console.log(this.addParams.content, "this.addParams.content");
|
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
this.fetchUpdateDocument(this.addParams);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
handlePreview() {
|
|
|
|
|
this.previewVisible = true;
|
|
|
|
|
this.currentTime = new Date().toLocaleString("zh-CN", {
|
|
|
|
|
year: "numeric",
|
|
|
|
|
month: "2-digit",
|
|
|
|
|
day: "2-digit",
|
|
|
|
|
hour: "2-digit",
|
|
|
|
|
minute: "2-digit",
|
|
|
|
|
second: "2-digit",
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
handlePreviewClose() {
|
|
|
|
|
this.previewVisible = false;
|
|
|
|
|
},
|
|
|
|
|
|
2025-08-01 08:33:33 +00:00
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
|
|
|
|
|
handleSave() {
|
2025-08-01 08:33:33 +00:00
|
|
|
|
// 保存前彻底去除所有锚点链接的 target="_blank"
|
|
|
|
|
this.addParams.content = this.addParams.content.replace(
|
|
|
|
|
/<a([^>]*href="#([^"]*)")[^>]*>/gi,
|
|
|
|
|
function (match) {
|
|
|
|
|
// 去掉 target="_blank"
|
|
|
|
|
return match.replace(/\s*target="_blank"/gi, "");
|
|
|
|
|
}
|
|
|
|
|
);
|
2025-07-25 08:39:37 +00:00
|
|
|
|
this.manualSave();
|
|
|
|
|
this.$message({
|
2025-08-01 08:33:33 +00:00
|
|
|
|
message: this.$t('backendSystem.contentSaved') || '内容已保存到本地,请尽快发布,关闭页面可能丢失内容',
|
2025-07-25 08:39:37 +00:00
|
|
|
|
type: "success",
|
|
|
|
|
duration: 4000,
|
|
|
|
|
showClose: true,
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
handleEditorChange() {
|
|
|
|
|
this.handleAutoSave();
|
|
|
|
|
},
|
|
|
|
|
handleAutoSaveType(type) {
|
|
|
|
|
try {
|
|
|
|
|
let item = this.TypeList.find((item) => item.value === type[0]);
|
|
|
|
|
if (item.articleUrl) {
|
|
|
|
|
this.addParams.articleUrl = item.articleUrl;
|
|
|
|
|
} else {
|
|
|
|
|
this.addParams.articleUrl = "";
|
|
|
|
|
}
|
|
|
|
|
this.addParams.type = type[0];
|
2025-08-01 08:33:33 +00:00
|
|
|
|
this.addParams.childType = type[1];
|
2025-07-25 08:39:37 +00:00
|
|
|
|
} catch (error) {
|
|
|
|
|
console.log(error, "error");
|
|
|
|
|
}
|
2025-07-18 08:22:28 +00:00
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
// 显示正在保存状态
|
|
|
|
|
this.isSaving = true;
|
2025-07-18 08:22:28 +00:00
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
if (this.autoSaveTimer) {
|
|
|
|
|
clearTimeout(this.autoSaveTimer);
|
|
|
|
|
}
|
2025-07-18 08:22:28 +00:00
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
this.autoSaveTimer = setTimeout(() => {
|
|
|
|
|
this.saveToLocalStorage();
|
|
|
|
|
}, 1500); // 减少到1.5秒,提高响应速度
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
handleAutoSave() {
|
|
|
|
|
// 显示正在保存状态
|
|
|
|
|
this.isSaving = true;
|
|
|
|
|
|
|
|
|
|
if (this.autoSaveTimer) {
|
|
|
|
|
clearTimeout(this.autoSaveTimer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.autoSaveTimer = setTimeout(() => {
|
|
|
|
|
this.saveToLocalStorage();
|
|
|
|
|
}, 1500); // 减少到1.5秒,提高响应速度
|
|
|
|
|
|
|
|
|
|
if (this.addParams.type == "2") {
|
|
|
|
|
//常见问题
|
|
|
|
|
this.addParams.articleUrl = `commonProblem`;
|
|
|
|
|
} else if (this.addParams.type == "3") {
|
|
|
|
|
//公告中心
|
|
|
|
|
this.addParams.articleUrl = `announcementDetails`;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
saveToLocalStorage() {
|
|
|
|
|
try {
|
|
|
|
|
// 确保获取最新的编辑器内容
|
|
|
|
|
if (this.editor) {
|
2025-08-01 08:33:33 +00:00
|
|
|
|
this.addParams.content = this.editor.txt.html();
|
2025-07-25 08:39:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const saveData = {
|
|
|
|
|
title: this.addParams.title,
|
|
|
|
|
content: this.addParams.content,
|
|
|
|
|
type: this.addParams.type,
|
|
|
|
|
imageUrl: this.addParams.imageUrl,
|
|
|
|
|
timestamp: new Date().toLocaleString("zh-CN", {
|
|
|
|
|
year: "numeric",
|
|
|
|
|
month: "2-digit",
|
|
|
|
|
day: "2-digit",
|
|
|
|
|
hour: "2-digit",
|
|
|
|
|
minute: "2-digit",
|
|
|
|
|
second: "2-digit",
|
|
|
|
|
}),
|
|
|
|
|
lastModified: Date.now(),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
localStorage.setItem("editor_draft", JSON.stringify(saveData));
|
|
|
|
|
this.lastSaveTime = saveData.timestamp;
|
|
|
|
|
this.isSaving = false;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("自动保存失败:", error);
|
|
|
|
|
this.isSaving = false;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
loadFromLocalStorage() {
|
|
|
|
|
try {
|
|
|
|
|
const savedData = localStorage.getItem("editor_draft");
|
|
|
|
|
if (savedData) {
|
|
|
|
|
const data = JSON.parse(savedData);
|
|
|
|
|
|
|
|
|
|
// 检查数据是否过期(7天)
|
|
|
|
|
const isExpired =
|
|
|
|
|
Date.now() - (data.lastModified || 0) > 7 * 24 * 60 * 60 * 1000;
|
|
|
|
|
|
|
|
|
|
if (isExpired) {
|
|
|
|
|
console.log("本地数据已过期,清除缓存");
|
|
|
|
|
localStorage.removeItem("editor_draft");
|
|
|
|
|
return;
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
2025-07-25 08:39:37 +00:00
|
|
|
|
|
|
|
|
|
// 使用 $nextTick 确保 DOM 更新后再设置内容
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.addParams.title = data.title || "";
|
|
|
|
|
this.addParams.content = data.content || "";
|
|
|
|
|
this.addParams.type = data.type || "1";
|
|
|
|
|
this.addParams.imageUrl = data.imageUrl || "";
|
|
|
|
|
this.lastSaveTime = data.timestamp || "";
|
|
|
|
|
|
|
|
|
|
// 如果编辑器已经创建,直接设置内容
|
|
|
|
|
if (this.editor) {
|
2025-08-01 08:33:33 +00:00
|
|
|
|
this.editor.txt.html(data.content || "");
|
2025-07-25 08:39:37 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("恢复数据失败:", error);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
clearDraft() {
|
|
|
|
|
localStorage.removeItem("editor_draft");
|
|
|
|
|
this.lastSaveTime = "";
|
|
|
|
|
this.isSaving = false;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 新增:手动保存方法
|
|
|
|
|
manualSave() {
|
2025-07-18 08:22:28 +00:00
|
|
|
|
// 确保获取最新的编辑器内容
|
|
|
|
|
if (this.editor) {
|
2025-08-01 08:33:33 +00:00
|
|
|
|
this.addParams.content = this.editor.txt.html();
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
2025-07-25 08:39:37 +00:00
|
|
|
|
this.saveToLocalStorage();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 页面卸载前处理
|
|
|
|
|
handleBeforeUnload(event) {
|
|
|
|
|
// 自动保存,不提示用户
|
|
|
|
|
if (this.addParams.title || this.addParams.content) {
|
|
|
|
|
// 确保获取最新的编辑器内容
|
|
|
|
|
if (this.editor) {
|
2025-08-01 08:33:33 +00:00
|
|
|
|
this.addParams.content = this.editor.txt.html();
|
2025-07-25 08:39:37 +00:00
|
|
|
|
}
|
|
|
|
|
this.saveToLocalStorage();
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
2025-07-25 08:39:37 +00:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 新增:获取文档类型名称
|
|
|
|
|
getDocumentTypeName(type) {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case "1":
|
2025-08-01 08:33:33 +00:00
|
|
|
|
return "home.serviceTerms";//服务条款
|
2025-07-25 08:39:37 +00:00
|
|
|
|
case "2":
|
2025-08-01 08:33:33 +00:00
|
|
|
|
return "home.APIfile";//api文档
|
2025-07-25 08:39:37 +00:00
|
|
|
|
case "3":
|
2025-08-01 08:33:33 +00:00
|
|
|
|
return "home.miningTutorial";//挖矿教程
|
2025-07-25 08:39:37 +00:00
|
|
|
|
case "0":
|
2025-08-01 08:33:33 +00:00
|
|
|
|
return "home.other";//其他
|
2025-07-25 08:39:37 +00:00
|
|
|
|
default:
|
2025-08-01 08:33:33 +00:00
|
|
|
|
return "home.unknownType";//未知类型
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 插入锚点(源码模式下插入HTML)
|
|
|
|
|
*/
|
|
|
|
|
handleInsertAnchor() {
|
|
|
|
|
if (!this.editor) {
|
|
|
|
|
this.$message.warning("编辑器尚未初始化");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
this.$prompt(this.$t('backendSystem.pleaseInputAnchorName') || '请输入锚点名称(不能重复)', this.$t('backendSystem.insertAnchor') || '插入锚点', {
|
|
|
|
|
confirmButtonText: this.$t('backendSystem.confirm') || '确定',
|
|
|
|
|
cancelButtonText: this.$t('backendSystem.cancel') || '取消',
|
|
|
|
|
inputPattern: /^[a-zA-Z0-9_-]+$/,
|
|
|
|
|
inputErrorMessage: this.$t('backendSystem.anchorNameErrorMessage') || '锚点名只能包含字母、数字、下划线和中划线',
|
|
|
|
|
})
|
|
|
|
|
.then(({ value }) => {
|
|
|
|
|
this.editor.cmd.do("insertHTML", `<span id="${value}"></span>`);
|
|
|
|
|
this.html = this.editor.txt.html();
|
|
|
|
|
this.addParams.content = this.html;
|
|
|
|
|
this.$message.success(this.$t('backendSystem.anchorInserted') || '锚点已插入');
|
|
|
|
|
})
|
|
|
|
|
.catch(() => {});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 给选中的标题添加id属性作为锚点
|
|
|
|
|
*/
|
|
|
|
|
handleAddHeadingId() {
|
|
|
|
|
if (!this.editor) {
|
|
|
|
|
this.$message.warning("编辑器尚未初始化");
|
|
|
|
|
return;
|
2025-07-25 08:39:37 +00:00
|
|
|
|
}
|
2025-08-01 08:33:33 +00:00
|
|
|
|
// 获取当前选中的标题节点
|
|
|
|
|
const headers = this.editor.getElemsByTypePrefix("header");
|
|
|
|
|
if (!headers || headers.length === 0) {
|
|
|
|
|
this.$message.warning(this.$t('backendSystem.pleaseSelectHeader') || '请先选中一个标题(h1~h6)');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
const node = headers[0];
|
|
|
|
|
this.$prompt(this.$t('backendSystem.pleaseInputAnchorID') || '请输入锚点ID(不能重复)', this.$t('backendSystem.titleAnchor') || '标题锚点', {
|
|
|
|
|
confirmButtonText: this.$t('backendSystem.confirm') || '确定',
|
|
|
|
|
cancelButtonText: this.$t('backendSystem.cancel') || '取消',
|
|
|
|
|
inputPattern: /^[a-zA-Z0-9_-]+$/,
|
|
|
|
|
inputErrorMessage: this.$t('backendSystem.anchorIDErrorMessage') || 'ID只能包含字母、数字、下划线和中划线',
|
|
|
|
|
})
|
|
|
|
|
.then(({ value }) => {
|
|
|
|
|
this.editor.setElemAttribute(node, "id", value);
|
|
|
|
|
this.$message.success(this.$t('backendSystem.anchorIDAdded') || '锚点ID已添加');
|
|
|
|
|
})
|
|
|
|
|
.catch(() => {});
|
2025-07-25 08:39:37 +00:00
|
|
|
|
},
|
2025-07-18 08:22:28 +00:00
|
|
|
|
},
|
2025-07-25 08:39:37 +00:00
|
|
|
|
|
|
|
|
|
beforeDestroy() {
|
|
|
|
|
if (this.editor) {
|
2025-08-01 08:33:33 +00:00
|
|
|
|
this.editor.destroy();
|
2025-07-25 08:39:37 +00:00
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
2025-07-18 08:22:28 +00:00
|
|
|
|
beforeRouteLeave(to, from, next) {
|
2025-07-25 08:39:37 +00:00
|
|
|
|
// 确保获取最新的编辑器内容
|
|
|
|
|
if (this.editor) {
|
2025-08-01 08:33:33 +00:00
|
|
|
|
this.addParams.content = this.editor.txt.html();
|
2025-07-25 08:39:37 +00:00
|
|
|
|
}
|
|
|
|
|
this.saveToLocalStorage();
|
|
|
|
|
next();
|
|
|
|
|
},
|
|
|
|
|
});
|
2025-07-18 08:22:28 +00:00
|
|
|
|
</script>
|
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
<style lang="scss" scoped>
|
2025-07-18 08:22:28 +00:00
|
|
|
|
/* 页面整体样式 */
|
|
|
|
|
.editor-page {
|
|
|
|
|
width: 100%;
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
padding: 20px;
|
|
|
|
|
background: #f8f9fa;
|
|
|
|
|
min-height: 60vh;
|
|
|
|
|
overflow-y: auto;
|
2025-08-01 08:33:33 +00:00
|
|
|
|
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 页面头部样式 */
|
|
|
|
|
.page-header {
|
|
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
|
|
color: white;
|
|
|
|
|
padding: 30px;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: flex-start;
|
|
|
|
|
box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.header-left {
|
|
|
|
|
flex: 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.title-section {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-bottom: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.title-icon {
|
|
|
|
|
font-size: 28px;
|
|
|
|
|
margin-right: 12px;
|
|
|
|
|
color: #ffd700;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.page-title {
|
|
|
|
|
font-size: 28px;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
margin: 0;
|
2025-07-25 08:39:37 +00:00
|
|
|
|
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.page-description {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
opacity: 0.9;
|
|
|
|
|
margin: 0;
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.header-actions {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 12px;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.header-actions .el-button {
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
padding: 12px 20px;
|
2025-07-25 08:39:37 +00:00
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
2025-07-18 08:22:28 +00:00
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.header-actions .el-button:hover {
|
|
|
|
|
transform: translateY(-2px);
|
2025-07-25 08:39:37 +00:00
|
|
|
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 配置区域样式 */
|
|
|
|
|
.config-section {
|
|
|
|
|
background: white;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
padding: 24px;
|
|
|
|
|
margin-bottom: 24px;
|
2025-07-25 08:39:37 +00:00
|
|
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
2025-07-18 08:22:28 +00:00
|
|
|
|
border: 1px solid #e9ecef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.section-header {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
padding-bottom: 16px;
|
|
|
|
|
border-bottom: 2px solid #f8f9fa;
|
|
|
|
|
color: #2c3e50;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.section-header i {
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
color: #667eea;
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.config-content {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 20px;
|
2025-07-25 08:39:37 +00:00
|
|
|
|
margin-top: 18px;
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.config-row {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: 1fr 1fr;
|
|
|
|
|
gap: 24px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.config-item {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.config-item label {
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #495057;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.required::after {
|
2025-07-25 08:39:37 +00:00
|
|
|
|
content: "*";
|
2025-07-18 08:22:28 +00:00
|
|
|
|
color: #e74c3c;
|
|
|
|
|
margin-left: 4px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 编辑器区域样式 */
|
|
|
|
|
.editor-section {
|
|
|
|
|
background: white;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
padding: 24px;
|
2025-07-25 08:39:37 +00:00
|
|
|
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
|
2025-07-18 08:22:28 +00:00
|
|
|
|
border: 1px solid #e9ecef;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.editor-container {
|
|
|
|
|
border: 1px solid #dcdfe6;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
background: white;
|
|
|
|
|
min-height: 650px;
|
2025-08-01 08:33:33 +00:00
|
|
|
|
position: relative;
|
|
|
|
|
z-index: 1;
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 设置编辑器高度 */
|
2025-08-01 08:33:33 +00:00
|
|
|
|
::v-deep .editor-container .w-e-text-container {
|
2025-07-18 08:22:28 +00:00
|
|
|
|
height: 600px !important;
|
|
|
|
|
min-height: 600px !important;
|
2025-08-01 08:33:33 +00:00
|
|
|
|
z-index: 1 !important;
|
|
|
|
|
position: relative;
|
|
|
|
|
}
|
|
|
|
|
::v-deep .w-e-toolbar {
|
|
|
|
|
z-index: 10 !important;
|
|
|
|
|
position: relative;
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 编辑器内容区域样式 */
|
|
|
|
|
.editor-container .w-e-text {
|
|
|
|
|
height: 600px !important;
|
|
|
|
|
min-height: 600px !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 保存状态样式 */
|
|
|
|
|
.save-status {
|
|
|
|
|
position: fixed;
|
|
|
|
|
bottom: 20px;
|
|
|
|
|
right: 20px;
|
|
|
|
|
background: #67c23a;
|
|
|
|
|
color: white;
|
|
|
|
|
padding: 12px 20px;
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
box-shadow: 0 4px 12px rgba(103, 194, 58, 0.3);
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 8px;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
z-index: 1000;
|
|
|
|
|
animation: slideIn 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes slideIn {
|
|
|
|
|
from {
|
2025-07-25 08:39:37 +00:00
|
|
|
|
transform: translateX(100%);
|
|
|
|
|
opacity: 0;
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
|
|
|
|
to {
|
2025-07-25 08:39:37 +00:00
|
|
|
|
transform: translateX(0);
|
|
|
|
|
opacity: 1;
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 预览对话框样式 */
|
|
|
|
|
.preview-dialog .el-dialog__body {
|
|
|
|
|
padding: 20px;
|
|
|
|
|
max-height: 70vh;
|
|
|
|
|
overflow-y: auto;
|
2025-08-01 08:33:33 +00:00
|
|
|
|
z-index: 9999;
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.preview-dialog .el-dialog__header {
|
|
|
|
|
background-color: #f8f9fa;
|
|
|
|
|
border-bottom: 1px solid #ebeef5;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.preview-dialog .el-dialog__header .el-dialog__title {
|
|
|
|
|
color: #333;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.preview-dialog .el-dialog__footer {
|
|
|
|
|
background-color: #f8f9fa;
|
|
|
|
|
border-top: 1px solid #ebeef5;
|
|
|
|
|
padding: 15px 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.preview-dialog .el-dialog__footer .dialog-footer {
|
|
|
|
|
text-align: right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.preview-dialog .el-dialog__footer .dialog-footer .el-button {
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
padding: 8px 15px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.preview-dialog .el-dialog__footer .dialog-footer .el-button:first-child {
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.preview-dialog .el-dialog__footer .dialog-footer .el-button:last-child {
|
|
|
|
|
background-color: #667eea;
|
|
|
|
|
border-color: #667eea;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.preview-dialog .el-dialog__footer .dialog-footer .el-button:last-child:hover {
|
|
|
|
|
background-color: #5a67d8;
|
|
|
|
|
border-color: #5a67d8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 预览内容样式 - 简化版本 */
|
|
|
|
|
.preview-content {
|
|
|
|
|
background: white;
|
|
|
|
|
padding: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.preview-empty {
|
|
|
|
|
text-align: center;
|
|
|
|
|
padding: 50px 20px;
|
|
|
|
|
color: #95a5a6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.preview-empty i {
|
|
|
|
|
font-size: 48px;
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
display: block;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.preview-empty p {
|
|
|
|
|
margin: 0;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 响应式设计 */
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
.editor-page {
|
2025-07-25 08:39:37 +00:00
|
|
|
|
padding: 10px;
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
2025-07-25 08:39:37 +00:00
|
|
|
|
|
2025-07-18 08:22:28 +00:00
|
|
|
|
.page-header {
|
2025-07-25 08:39:37 +00:00
|
|
|
|
flex-direction: column;
|
|
|
|
|
gap: 20px;
|
|
|
|
|
padding: 20px;
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
2025-07-25 08:39:37 +00:00
|
|
|
|
|
2025-07-18 08:22:28 +00:00
|
|
|
|
.header-actions {
|
2025-07-25 08:39:37 +00:00
|
|
|
|
width: 100%;
|
|
|
|
|
justify-content: center;
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
2025-07-25 08:39:37 +00:00
|
|
|
|
|
2025-07-18 08:22:28 +00:00
|
|
|
|
.config-row {
|
2025-07-25 08:39:37 +00:00
|
|
|
|
grid-template-columns: 1fr;
|
|
|
|
|
gap: 16px;
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
2025-07-25 08:39:37 +00:00
|
|
|
|
|
2025-07-18 08:22:28 +00:00
|
|
|
|
.page-title {
|
2025-07-25 08:39:37 +00:00
|
|
|
|
font-size: 24px;
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
2025-07-25 08:39:37 +00:00
|
|
|
|
|
2025-07-18 08:22:28 +00:00
|
|
|
|
.save-status {
|
2025-07-25 08:39:37 +00:00
|
|
|
|
bottom: 10px;
|
|
|
|
|
right: 10px;
|
|
|
|
|
left: 10px;
|
|
|
|
|
text-align: center;
|
|
|
|
|
justify-content: center;
|
2025-07-18 08:22:28 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Element UI 组件样式优化 */
|
2025-07-25 08:39:37 +00:00
|
|
|
|
.el-input,
|
|
|
|
|
.el-select {
|
2025-07-18 08:22:28 +00:00
|
|
|
|
border-radius: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
.el-input__inner,
|
|
|
|
|
.el-select .el-input__inner {
|
2025-07-18 08:22:28 +00:00
|
|
|
|
border-radius: 8px;
|
|
|
|
|
border: 1px solid #dcdfe6;
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-25 08:39:37 +00:00
|
|
|
|
.el-input__inner:focus,
|
|
|
|
|
.el-select .el-input__inner:focus {
|
2025-07-18 08:22:28 +00:00
|
|
|
|
border-color: #667eea;
|
|
|
|
|
box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.el-tag {
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
2025-07-25 08:39:37 +00:00
|
|
|
|
|
|
|
|
|
/* -------富文本样式-------------- */
|
|
|
|
|
.dynamic-content {
|
2025-08-01 08:33:33 +00:00
|
|
|
|
width: 100%;
|
|
|
|
|
margin: 0 auto;
|
2025-07-18 08:22:28 +00:00
|
|
|
|
|
2025-08-01 08:33:33 +00:00
|
|
|
|
:deep(table) {
|
|
|
|
|
border-collapse: collapse;
|
|
|
|
|
width: 100%;
|
|
|
|
|
margin: 16px 0;
|
|
|
|
|
}
|
|
|
|
|
:deep(th),
|
|
|
|
|
:deep(td) {
|
|
|
|
|
border: 1px solid #d1d5db;
|
|
|
|
|
padding: 8px 12px;
|
|
|
|
|
text-align: left;
|
|
|
|
|
}
|
|
|
|
|
:deep(th) {
|
|
|
|
|
background: #f3f4f6;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
}
|
|
|
|
|
:deep(strong),
|
|
|
|
|
:deep(b) {
|
|
|
|
|
font-weight: bold !important;
|
|
|
|
|
color: inherit !important;
|
|
|
|
|
font-style: normal !important;
|
|
|
|
|
}
|
|
|
|
|
:deep(em),
|
|
|
|
|
:deep(i) {
|
|
|
|
|
font-style: italic !important;
|
|
|
|
|
color: inherit !important;
|
|
|
|
|
}
|
|
|
|
|
:deep(a) {
|
|
|
|
|
color: #007bff !important;
|
|
|
|
|
text-decoration: none !important;
|
|
|
|
|
&:hover {
|
|
|
|
|
text-decoration: underline !important;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.no-scroll {
|
|
|
|
|
overflow: hidden !important;
|
|
|
|
|
}
|
|
|
|
|
</style>
|