|
|
@@ -0,0 +1,274 @@
|
|
|
+<template>
|
|
|
+ <el-dialog
|
|
|
+ title="教材标题设置"
|
|
|
+ :visible="visible"
|
|
|
+ width="1200px"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ class="book-unified-title"
|
|
|
+ @close="dialogClose"
|
|
|
+ >
|
|
|
+ <div class="setting-top">
|
|
|
+ <div class="form">
|
|
|
+ <el-form ref="form" :model="formModel" label-width="50" size="small">
|
|
|
+ <!-- 5列标题级别设置 -->
|
|
|
+ <div class="levels-container">
|
|
|
+ <div class="level-column" v-for="(item, index) in titleSettings" :key="index">
|
|
|
+ <div class="level-header">{{ item.level_title }}</div>
|
|
|
+
|
|
|
+ <!-- 字体 -->
|
|
|
+ <el-form-item label="字体">
|
|
|
+ <el-select v-model="item.font" placeholder="请选择字体" style="width: 120px">
|
|
|
+ <el-option label="宋体" value="宋体,微软雅黑" />
|
|
|
+ <el-option label="楷体" value="楷体,微软雅黑" />
|
|
|
+ <el-option label="黑体" value="黑体,微软雅黑" />
|
|
|
+ <el-option label="Arial" value="Arial,Helvetica,sans-serif" />
|
|
|
+ <el-option label="Times New Roman" value="Times New Roman,times,serif" />
|
|
|
+ <el-option label="拼音" value="League" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 字号 -->
|
|
|
+ <el-form-item label="字号">
|
|
|
+ <el-select v-model="item.font_size" placeholder="请选择字号" style="width: 100px">
|
|
|
+ <el-option v-for="size in fontSizeList" :key="size" :label="size" :value="size" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 加粗 -->
|
|
|
+ <el-form-item label="加粗">
|
|
|
+ <el-switch v-model="item.bold" active-value="true" inactive-value="false" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 斜体 -->
|
|
|
+ <el-form-item label="斜体">
|
|
|
+ <el-switch v-model="item.italic" active-value="true" inactive-value="false" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 文字颜色 -->
|
|
|
+ <el-form-item label="文字颜色">
|
|
|
+ <el-color-picker v-model="item.text_color" style="width: 40px" />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <!-- 缩进 -->
|
|
|
+ <el-form-item label="缩进">
|
|
|
+ <div style="display: flex; align-items: center">
|
|
|
+ <el-input-number
|
|
|
+ v-model="item.indent"
|
|
|
+ :min="0"
|
|
|
+ :max="10"
|
|
|
+ :step="1"
|
|
|
+ controls-position="right"
|
|
|
+ placeholder="0"
|
|
|
+ style="width: 80px"
|
|
|
+ />
|
|
|
+ <span style="margin-left: 8px; font-size: 12px; color: #909399">字符</span>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button @click="dialogClose">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="saveBookUnifiedTitle">确 定</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { GetTitleStyle, ApplyBookUnifiedAttrib, SaveTitleStyle } from '@/api/book';
|
|
|
+import { unified_title } from '@/common/data';
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'BookUnifiedTitlePage',
|
|
|
+ props: {
|
|
|
+ visible: {
|
|
|
+ type: Boolean,
|
|
|
+ required: true,
|
|
|
+ },
|
|
|
+ bookId: {
|
|
|
+ type: String,
|
|
|
+ required: true,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ fontSizeList: [
|
|
|
+ '8pt',
|
|
|
+ '10pt',
|
|
|
+ '12pt',
|
|
|
+ '14pt',
|
|
|
+ '16pt',
|
|
|
+ '18pt',
|
|
|
+ '20pt',
|
|
|
+ '22pt',
|
|
|
+ '24pt',
|
|
|
+ '26pt',
|
|
|
+ '28pt',
|
|
|
+ '30pt',
|
|
|
+ '32pt',
|
|
|
+ '34pt',
|
|
|
+ '36pt',
|
|
|
+ ],
|
|
|
+ titleSettings: [],
|
|
|
+ defaultTitleSettings: [],
|
|
|
+ formModel: {},
|
|
|
+ };
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ visible(newVal) {
|
|
|
+ if (newVal) {
|
|
|
+ this.getBookUnifiedTitle();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.initTitleSettings();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ initTitleSettings() {
|
|
|
+ // 各级别的默认字号
|
|
|
+ const defaultFontSizes = ['16pt', '14pt', '12pt', '10pt', '8pt'];
|
|
|
+
|
|
|
+ this.defaultTitleSettings = Array.from({ length: 5 }, (_, index) => {
|
|
|
+ return {
|
|
|
+ level: index + 1,
|
|
|
+ level_title: this.getLevelLabel(index + 1),
|
|
|
+ font: unified_title.font,
|
|
|
+ font_size: defaultFontSizes[index] || unified_title.font_size,
|
|
|
+ text_color: unified_title.text_color,
|
|
|
+ bold: unified_title.bold,
|
|
|
+ italic: unified_title.italic,
|
|
|
+ indent: unified_title.indent,
|
|
|
+ };
|
|
|
+ });
|
|
|
+ },
|
|
|
+ getLevelLabel(level) {
|
|
|
+ const labels = ['一级标题', '二级标题', '三级标题', '四级标题', '五级标题'];
|
|
|
+ return labels[level - 1];
|
|
|
+ },
|
|
|
+ async getBookUnifiedTitle() {
|
|
|
+ this.titleSettings = [];
|
|
|
+ let isSuccess = false;
|
|
|
+ await GetTitleStyle({ book_id: this.bookId }).then(({ title_list }) => {
|
|
|
+ if (title_list && title_list.length > 0) {
|
|
|
+ isSuccess = true;
|
|
|
+
|
|
|
+ for (let i = 1; i <= 5; i++) {
|
|
|
+ let en = title_list.find((x) => x.level == i);
|
|
|
+ let style = en.style ? JSON.parse(en.style) : {};
|
|
|
+ let defStyle = this.defaultTitleSettings[i - 1];
|
|
|
+ style = Object.assign({}, defStyle, style);
|
|
|
+
|
|
|
+ // 但这样会覆盖所有默认值,需要额外处理空值
|
|
|
+ Object.keys(style).forEach((key) => {
|
|
|
+ if (!style[key] && style[key] !== 0) {
|
|
|
+ style[key] = defStyle[key] || ''; // 用默认值替换空值
|
|
|
+ }
|
|
|
+ });
|
|
|
+ this.titleSettings.push(style);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!isSuccess) this.titleSettings = this.defaultTitleSettings;
|
|
|
+ },
|
|
|
+ applyBookUnifiedAttr() {
|
|
|
+ let loading = this.$loading({ fullscreen: true, text: '正在应用,请稍后...' });
|
|
|
+ ApplyBookUnifiedAttrib({
|
|
|
+ book_id: this.bookId,
|
|
|
+ content: JSON.stringify(this.unified_title),
|
|
|
+ })
|
|
|
+ .then(() => {
|
|
|
+ this.$message.success('应用成功');
|
|
|
+ this.dialogClose();
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ loading.close();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ saveBookUnifiedTitle() {
|
|
|
+ let title_list = [];
|
|
|
+ this.titleSettings.forEach((config, index) => {
|
|
|
+ let tmp = { level: config.level, style: JSON.stringify(config) };
|
|
|
+ title_list.push(tmp);
|
|
|
+ });
|
|
|
+
|
|
|
+ let data = { book_id: this.bookId, title_list: title_list };
|
|
|
+
|
|
|
+ SaveTitleStyle(data).then(() => {
|
|
|
+ this.$message.success('保存成功');
|
|
|
+ this.dialogClose();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ dialogClose() {
|
|
|
+ this.$emit('update:visible', false);
|
|
|
+ this.$emit('close');
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.book-unified-title {
|
|
|
+ .setting-top {
|
|
|
+ display: flex;
|
|
|
+
|
|
|
+ .form {
|
|
|
+ flex: 1;
|
|
|
+
|
|
|
+ .levels-container {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: repeat(5, 1fr);
|
|
|
+ gap: 15px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .level-column {
|
|
|
+ padding: 12px;
|
|
|
+
|
|
|
+ // background: #fafafa;
|
|
|
+ border: 1px solid #ebeef5;
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .level-header {
|
|
|
+ padding-bottom: 6px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #333;
|
|
|
+ text-align: center;
|
|
|
+ border-bottom: 1px solid #ebeef5;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-select {
|
|
|
+ width: 150px !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-input-number {
|
|
|
+ width: calc(100% - 40px) !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .color-group {
|
|
|
+ display: flex;
|
|
|
+ column-gap: 10px;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ span {
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .setting-bottom {
|
|
|
+ display: flex;
|
|
|
+ column-gap: 10px;
|
|
|
+ align-items: center;
|
|
|
+ padding-top: 20px;
|
|
|
+ margin-top: 20px;
|
|
|
+ border-top: $border;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|