做几方面优化

This commit is contained in:
hero920103 committed 2026-09-25 00:27:15 +08:00
1 parent eafa5e1cf4
commit 92403171d4
14 files changed
+2142 -258

No files matched your search

@@ -82,14 +82,16 @@
</div>
</div>
<!-- 新建 / 编辑 -->
<el-dialog
<!-- 新建 / 编辑:右侧滑出抽屉,纵向空间比居中弹窗更充足 -->
<el-drawer
v-model="dialogVisible"
:title="editing ? '编辑模板' : '新建模板'"
width="820px"
size="min(1200px, 92vw)"
:close-on-click-modal="false"
class="template-drawer"
@closed="editorReady = false"
>
<el-form :model="form" label-width="100px">
<el-form :model="form" label-width="100px" class="template-form">
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="模板名称" required>
@@ -130,15 +132,19 @@
<el-form-item label="模板描述">
<el-input v-model="form.description" type="textarea" :rows="2" placeholder="模板适用场景说明" />
</el-form-item>
<el-form-item label="模板正文">
<el-input v-model="form.content" type="textarea" :rows="12" placeholder="标书模板内容" />
<el-form-item label="模板正文" class="editor-form-item">
<div class="template-editor-box">
<UmoEditor v-if="editorReady" v-model="form.content" />
</div>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" :loading="submitting" @click="handleSubmit">保存</el-button>
<div class="drawer-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" :loading="submitting" @click="handleSubmit">保存</el-button>
</div>
</template>
</el-dialog>
</el-drawer>
<!-- 预览 -->
<el-dialog v-model="previewVisible" :title="previewRow?.template_name || '模板预览'" width="800px">
@@ -150,7 +156,13 @@
<el-descriptions-item label="引用次数">{{ previewRow?.use_count || 0 }}</el-descriptions-item>
</el-descriptions>
<el-divider />
<div class="preview-content">{{ previewRow?.content || "(空)" }}</div>
<!-- 富文本内容按 HTML 渲染;旧数据为纯文本时保持原样换行展示 -->
<div
v-if="isRichText(previewRow?.content)"
class="preview-content is-rich"
v-html="previewRow.content"
></div>
<div v-else class="preview-content">{{ previewRow?.content || "(空)" }}</div>
<template v-if="previewRow?.file_url">
<el-divider />
<el-link :href="previewRow.file_url" target="_blank" type="primary">打开模板文件</el-link>
@@ -160,7 +172,7 @@
</template>
<script setup>
import { ref, reactive, onMounted } from "vue";
import { ref, reactive, onMounted, nextTick } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { Plus, Search, Refresh, RefreshLeft } from "@element-plus/icons-vue";
import {
@@ -170,6 +182,7 @@ import {
deleteTemplate,
} from "@/api/crmBidding";
import { bidTemplateTypeOptions, templateTypeText } from "@/views/apps/crm/dict";
import UmoEditor from "@/views/components/UmoEditor.vue";
const loading = ref(false);
const tableData = ref([]);
@@ -181,6 +194,8 @@ const previewVisible = ref(false);
const previewRow = ref(null);
const editing = ref(null);
const submitting = ref(false);
// UmoEditor 只在创建时读取一次初始值,故每次打开弹窗重建实例以保证载入当前内容
const editorReady = ref(false);
const emptyForm = () => ({
template_name: "",
@@ -225,10 +240,19 @@ function resetFilters() {
handleSearch();
}
// 每次打开都重建编辑器实例,避免残留上一条模板的内容
function openEditorDialog() {
editorReady.value = false;
dialogVisible.value = true;
nextTick(() => {
editorReady.value = true;
});
}
function openCreate() {
editing.value = null;
Object.assign(form, emptyForm());
dialogVisible.value = true;
openEditorDialog();
}
function openEdit(row) {
@@ -242,7 +266,7 @@ function openEdit(row) {
file_url: row.file_url || "",
status: Number(row.status) || 1,
});
dialogVisible.value = true;
openEditorDialog();
}
async function handleSubmit() {
@@ -288,11 +312,70 @@ function openPreview(row) {
previewRow.value = row;
previewVisible.value = true;
}
// 判断内容是否为富文本 HTML(旧数据由纯文本 textarea 保存,需保持原样展示)
function isRichText(content) {
return /<(p|div|br|h[1-6]|ul|ol|li|table|img|strong|b|span)\b[\s\S]*>/i.test(content || "");
}
</script>
<style lang="less" scoped src="../../styles/crm-page.less"></style>
<style scoped>
/* 抽屉主体改为纵向 flex:表单撑满,正文编辑区吃掉剩余高度(真正的自适应) */
.template-drawer :deep(.el-drawer__body) {
display: flex;
flex-direction: column;
overflow: hidden;
padding: 16px 20px;
}
.template-form {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
}
.drawer-footer {
display: flex;
justify-content: flex-end;
gap: 12px;
}
/* 正文字段吃掉表单剩余高度,内容区同样撑满 */
.editor-form-item {
flex: 1;
min-height: 0;
:deep(.el-form-item__content) {
flex: 1;
min-height: 0;
display: flex;
}
}
/* umo-editor 以 100% 填充父容器;宽度锁死为容器宽度,杜绝横向拉伸 */
.template-editor-box {
width: 100%;
max-width: 100%;
min-width: 0;
flex: 1;
min-height: 320px;
border: 1px solid #dcdfe6;
border-radius: 4px;
overflow: hidden;
background: #fff;
}
.template-editor-box :deep(.umo-editor),
.template-editor-box :deep(umo-editor) {
width: 100% !important;
max-width: 100% !important;
min-width: 0 !important;
height: 100%;
}
.preview-content {
white-space: pre-wrap;
word-break: break-word;
@@ -300,4 +383,25 @@ function openPreview(row) {
font-size: 14px;
min-height: 120px;
}
/* 富文本预览:按 HTML 结构展示,图片自适应 */
.preview-content.is-rich {
white-space: normal;
:deep(img) {
max-width: 100%;
height: auto;
}
:deep(table) {
border-collapse: collapse;
width: 100%;
th,
td {
border: 1px solid #dcdfe6;
padding: 8px 12px;
}
}
}
</style>
+3 -1
View File
@@ -20,6 +20,7 @@ import {
handleAuthorizeCallback,
redirectToAuthorize,
fetchUserInfo,
resolveTenantName,
} from "@/utils/authClient";
const error = ref("");
@@ -38,7 +39,8 @@ async function saveUserInfo() {
name: info.name || info.nickname || "",
group_id: info.group_id || "",
tid: info.tid || "",
tenant_name: (info.tenants || []).map((t) => t.tenant_name).join("、"),
// 顶部展示的是当前登录的企业,不是该账号可进入的全部企业
tenant_name: resolveTenantName(info),
avatar: info.avatar || "",
type: "backend",
};
+20 -2
View File
@@ -1,5 +1,5 @@
<template>
<div class="umo-editor-wrapper">
<div class="umo-editor-wrapper" :style="wrapperStyle">
<umo-editor
ref="editorRef"
v-bind="options"
@@ -11,7 +11,7 @@
</template>
<script setup>
import { ref, watch } from 'vue'
import { ref, watch, computed } from 'vue'
import { UmoEditor } from '@umoteam/editor'
import '@umoteam/editor/style'
import { uploadFile } from '@/api/file'
@@ -21,6 +21,16 @@ const props = defineProps({
type: String,
default: '',
},
// 编辑器高度:默认填满父容器(父容器需有确定高度);
// 传 'auto' 时由 minHeight 兜底,配合父容器自适应高度
height: {
type: String,
default: '100%',
},
minHeight: {
type: Number,
default: 0,
},
})
const emit = defineEmits(['update:modelValue'])
@@ -29,6 +39,11 @@ const content = ref(props.modelValue)
const editorRef = ref(null)
const isCreated = ref(false)
const wrapperStyle = computed(() => ({
height: props.height,
minHeight: props.minHeight ? props.minHeight + 'px' : '',
}))
const options = {
height: '100%',
// umo-editor 会定时触发自动保存(onSave),内容已随表单统一提交,这里给空实现避免控制台报错
@@ -77,10 +92,13 @@ watch(
box-sizing: border-box;
overflow: hidden;
}
/* 注意:必须是 :deep,写成 ::deep 会被浏览器当作无效选择器丢弃,
导致宽度限制失效、编辑器被横向拉伸出滚动条 */
:deep(.umo-editor),
:deep(umo-editor) {
width: 100% !important;
max-width: 100% !important;
min-width: 0 !important;
box-sizing: border-box;
}
</style>