feat(web-admin): TinyMCE 表格类 Excel 调宽调高,并优化出入库/分装/送货单排版
支持合同、报价与入库/分装/送(提)货单在富文本中拖拽调整列宽行高;单据侧加宽物料编号与名称、收窄规格单位、放大 logo、加宽条款区,并弱化调整手柄绿色阴影。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
2380b01a4f
commit
3d5866aa14
13 files changed
+31815
-30418
No files matched your search
@@ -10,6 +10,7 @@ import Editor from '@tinymce/tinymce-vue';
|
||||
import { fetchUploadAttachment } from '@/api/admin';
|
||||
import { resolveCrmAttachmentUrl } from '@/utils/crm-attachment';
|
||||
import { buildAttachmentUploadFormData, CRM_UPLOAD_BIZ_TYPE } from '@/utils/crm-upload';
|
||||
import { setupExcelLikeTableResize } from '@/utils/tinymce-table-excel-resize';
|
||||
|
||||
/** 须高于 ElConfigProvider 初始 z-index(3000) 及多层 el-dialog 叠加 */
|
||||
const TINYMCE_Z_INDEX_FLOOR = 10000;
|
||||
@@ -180,12 +181,13 @@ const editorInit = computed(() => {
|
||||
]
|
||||
: [],
|
||||
|
||||
// 工具栏 - 简化并突出表格功能,添加盖章按钮
|
||||
// 工具栏:突出表格排版(合并/拆分、单元格属性、对齐、换行)+ 盖章
|
||||
toolbar: props.toolbar
|
||||
? 'undo redo | ' +
|
||||
'bold italic underline | ' +
|
||||
'alignleft aligncenter alignright | ' +
|
||||
'table | ' +
|
||||
'table tableprops tablecellprops tablemergecells tablesplitcells | ' +
|
||||
'tablecellhalign tablecellvalign tablecellwrap | ' +
|
||||
'bullist numlist | ' +
|
||||
'link image | ' +
|
||||
'sealMode cancelSeal | ' +
|
||||
@@ -206,24 +208,41 @@ const editorInit = computed(() => {
|
||||
width: 100%;
|
||||
}
|
||||
${backgroundStyle}
|
||||
/* 确保所有内容在水印上方 */
|
||||
body > * {
|
||||
/* 确保内容在水印上方;排除 snooker / Excel 调整层 */
|
||||
body > *:not(.ephox-snooker-resizer-bar):not(#sx-excel-resize-layer) {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
/* 表格:固定布局;不抢占内联宽高/对齐/边框 */
|
||||
table {
|
||||
border-collapse: collapse !important;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
margin-bottom: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
table td, table th {
|
||||
border: 1px solid #ddd !important;
|
||||
padding: ${props.tableCellPadding} !important;
|
||||
border: 1px solid #ddd;
|
||||
padding: ${props.tableCellPadding};
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
white-space: normal;
|
||||
vertical-align: middle;
|
||||
cursor: inherit;
|
||||
/* 与 getBoundingClientRect 量到的边框盒宽度一致,避免快照写回时每列被放大 */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
table th {
|
||||
background-color: #f5f5f5 !important;
|
||||
font-weight: bold !important;
|
||||
text-align: center !important;
|
||||
background-color: #f5f5f5;
|
||||
font-weight: bold;
|
||||
}
|
||||
/* 原生调整条仅作可视提示,勿改 width/height/margin(会破坏拖拽几何) */
|
||||
.ephox-snooker-resizer-bar {
|
||||
background-color: #10b981 !important;
|
||||
}
|
||||
.ephox-snooker-resizer-bar:hover,
|
||||
.ephox-snooker-resizer-bar.ephox-snooker-resizer-bar-dragging {
|
||||
opacity: 0.9 !important;
|
||||
}
|
||||
h1 {
|
||||
text-align: center;
|
||||
@@ -269,12 +288,14 @@ const editorInit = computed(() => {
|
||||
extended_valid_elements: '*[*]',
|
||||
valid_elements: '*[*]',
|
||||
|
||||
// 表格配置
|
||||
// 表格配置:像素列宽 + 拖拽条,表格总宽在拖列时尽量保持(更接近 Excel)
|
||||
table_toolbar:
|
||||
'tableprops tabledelete | tableinsertrowbefore tableinsertrowafter tabledeleterow | tableinsertcolbefore tableinsertcolafter tabledeletecol',
|
||||
'tableprops tablecellprops tabledelete | tablemergecells tablesplitcells | tableinsertrowbefore tableinsertrowafter tabledeleterow | tableinsertcolbefore tableinsertcolafter tabledeletecol | tablecellhalign tablecellvalign tablecellwrap',
|
||||
table_appearance_options: true,
|
||||
table_grid: true,
|
||||
table_resize_bars: true,
|
||||
table_sizing_mode: 'fixed',
|
||||
table_column_resizing: 'preservetable',
|
||||
table_use_colgroups: true,
|
||||
table_default_attributes: {
|
||||
border: '1'
|
||||
@@ -336,8 +357,8 @@ const editorInit = computed(() => {
|
||||
image_caption: true,
|
||||
image_title: true,
|
||||
|
||||
// 允许调整图片大小
|
||||
object_resizing: true,
|
||||
// 图片可拖拽缩放;表格列宽/行高改由 setupExcelLikeTableResize(类 Excel 边线拖拽)
|
||||
object_resizing: 'img,figure.image,div,video,iframe',
|
||||
|
||||
// 允许拖拽图片
|
||||
draggable_modal: false,
|
||||
@@ -345,6 +366,65 @@ const editorInit = computed(() => {
|
||||
// 初始化回调
|
||||
setup: (editor: any) => {
|
||||
props.editorSetupExtra?.(editor)
|
||||
setupExcelLikeTableResize(editor)
|
||||
|
||||
const applyCellStyle = (style: string, value: string) => {
|
||||
if (editor.queryCommandSupported('mceTableApplyCellStyle')) {
|
||||
editor.execCommand('mceTableApplyCellStyle', false, { [style]: value });
|
||||
}
|
||||
};
|
||||
|
||||
// 单元格水平对齐(table 插件自带垂直对齐 tablecellvalign,水平需自建)
|
||||
editor.ui.registry.addMenuButton('tablecellhalign', {
|
||||
icon: 'align-center',
|
||||
tooltip: '单元格水平对齐',
|
||||
fetch: (callback: (items: any[]) => void) => {
|
||||
callback([
|
||||
{
|
||||
type: 'menuitem',
|
||||
text: '左对齐',
|
||||
icon: 'align-left',
|
||||
onAction: () => applyCellStyle('text-align', 'left')
|
||||
},
|
||||
{
|
||||
type: 'menuitem',
|
||||
text: '居中',
|
||||
icon: 'align-center',
|
||||
onAction: () => applyCellStyle('text-align', 'center')
|
||||
},
|
||||
{
|
||||
type: 'menuitem',
|
||||
text: '右对齐',
|
||||
icon: 'align-right',
|
||||
onAction: () => applyCellStyle('text-align', 'right')
|
||||
}
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
// 单元格文字换行
|
||||
editor.ui.registry.addMenuButton('tablecellwrap', {
|
||||
icon: 'line',
|
||||
tooltip: '单元格文字换行',
|
||||
fetch: (callback: (items: any[]) => void) => {
|
||||
callback([
|
||||
{
|
||||
type: 'menuitem',
|
||||
text: '自动换行',
|
||||
onAction: () => {
|
||||
applyCellStyle('white-space', 'normal');
|
||||
applyCellStyle('word-wrap', 'break-word');
|
||||
applyCellStyle('overflow-wrap', 'break-word');
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'menuitem',
|
||||
text: '不换行',
|
||||
onAction: () => applyCellStyle('white-space', 'nowrap')
|
||||
}
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
const refreshFloatingLayers = () => {
|
||||
const z = resolveTinyMceBaseZIndex();
|
||||
|
||||
Reference in new issue
Block a user