添加合同页面

dev
suixy 2 months ago
parent b19cfd7864
commit 81e0356656

@ -22,6 +22,7 @@
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "2.3.1", "@element-plus/icons-vue": "2.3.1",
"@highlightjs/vue-plugin": "2.1.0", "@highlightjs/vue-plugin": "2.1.0",
"@umoteam/editor": "^8.1.0",
"@vueup/vue-quill": "1.2.0", "@vueup/vue-quill": "1.2.0",
"@vueuse/core": "13.1.0", "@vueuse/core": "13.1.0",
"animate.css": "4.1.1", "animate.css": "4.1.1",
@ -31,11 +32,11 @@
"docx": "^9.5.1", "docx": "^9.5.1",
"echarts": "5.6.0", "echarts": "5.6.0",
"element-plus": "2.9.8", "element-plus": "2.9.8",
"file-saver": "2.0.5",
"highlight.js": "11.9.0", "highlight.js": "11.9.0",
"image-conversion": "2.1.1", "image-conversion": "2.1.1",
"js-cookie": "3.0.5", "js-cookie": "3.0.5",
"jsencrypt": "3.3.2", "jsencrypt": "3.3.2",
"mammoth": "^1.11.0",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"pinia": "3.0.2", "pinia": "3.0.2",
"screenfull": "6.0.2", "screenfull": "6.0.2",

@ -54,4 +54,10 @@ app.use(plugins);
// 自定义指令 // 自定义指令
directive(app); directive(app);
if (typeof window !== 'undefined') {
import('mammoth/mammoth.browser').then((mammoth) => {
(window as any).mammoth = mammoth;
});
}
app.mount('#app'); app.mount('#app');

@ -1,9 +1,212 @@
<template> <template>
<div>123</div> <div>
{{ options }}
<umo-editor v-bind="options" ref="editorRef" />
</div>
</template> </template>
<script setup> <script setup>
import { Document, Packer, Paragraph, TextRun } from 'docx'; import { AlignmentType, Document, Footer, Packer, Paragraph, TextRun } from 'docx';
import { UmoEditor } from '@umoteam/editor';
const editorRef = ref();
const docData = {
'甲方': '青岛xxx科技有限公司',
'合同表格表头': ['序号', '产品名称', '规格描述', '数量', '单位', '单价', '小记']
};
const createContractTable = () => {
const rows = 3;
const cols = docData['合同表格表头'].length;
const head = docData['合同表格表头'];
return {
type: 'table',
attrs: { id: 'contractTable', style: 'width:100%;border-collapse:collapse;' },
content: [
...Array.from({ length: rows }).map((_, k) => ({
type: 'tableRow',
content:
k === 0
? head.map((i) => ({
type: 'tableHeader',
attrs: { style: 'border:1px solid #ccc;padding:4px;height:40px;' },
content: [
{
type: 'paragraph',
content: [{ type: 'text', text: i }]
}
]
}))
: Array.from({ length: cols }).map((__, kk) => ({
type: 'tableCell',
attrs: { style: 'border:1px solid #ccc;padding:4px;height:40px;' },
content:
kk === 0
? [
{
type: 'paragraph',
content: [{ type: 'text', text: '' + k }]
}
]
: [
{
type: 'paragraph',
content: [{ type: 'text', text: ' ' }]
}
]
}))
})),
{
type: 'tableRow',
content: [
{
type: 'tableCell',
attrs: { colspan: 6 },
content: [
{
type: 'paragraph',
attrs: { textAlign: 'center' },
content: [{ type: 'text', text: '合计' }]
}
]
},
{
type: 'tableCell',
attrs: {},
content: [
{
type: 'paragraph',
content: [{ type: 'text', text: ' ' }]
}
]
}
]
},
{
type: 'tableRow',
content: [
{
type: 'tableCell',
attrs: { colspan: 7 },
content: [
{
type: 'paragraph',
attrs: { textAlign: 'center' },
content: [{ type: 'text', text: '合同总价: ¥ 大写:人民币 整' }]
}
]
}
]
}
]
};
};
const options = ref({
document: {
title: '',
content: {
type: 'doc',
content: [
{
type: 'heading',
attrs: { level: 1, textAlign: 'center' },
content: [{ type: 'text', text: '合 同' }]
},
{
type: 'paragraph',
attrs: { textAlign: 'right' },
content: [{ type: 'text', text: '合同编号111' }]
},
{
type: 'paragraph',
content: [
{
type: 'text',
attrs: { textAlign: 'left' },
text: `甲方:${docData['甲方']}\t\t乙方青岛海威物联科技有限公司`
}
]
},
{
type: 'paragraph',
content: [{ type: 'text', text: '1.产品名称、规格、供货范围和价款 币种:人民币 单位:元' }]
},
createContractTable()
]
},
placeholder: {
en_US: 'Please enter the document content...',
zh_CN: '请输入文档内容...'
},
enableSpellcheck: true,
enableMarkdown: true,
enableBubbleMenu: true,
enableBlockMenu: true,
readOnly: false,
autofocus: true,
characterLimit: 0,
typographyRules: {},
editorProps: {},
parseOptions: {
preserveWhitespace: 'full'
},
autoSave: {
enabled: true,
interval: 300000
}
},
onSave: async (e) => {
const editor = editorRef.value;
const html = editor.getHTML();
console.log(html);
// const doc = new Document({
// sections: [{ children: parseHTML(editor.getHTML()) }]
// });
// await download(doc);
},
onChanged: async (e) => {
const editor = editorRef.value;
const json = editor.getJSON();
console.log(json);
console.log(json.content.find((v) => v.type === 'table' && v.attrs?.id === 'contractTable'));
// json
editor.setContent(json, { emitUpdate: false });
// const doc = new Document({
// sections: [{ children: prseHTML(editor.getHTML()) }]
// });
// await download(doc);
}
});
function parseHTML(html) {
const div = document.createElement('div');
div.innerHTML = html;
const children = [];
div.childNodes.forEach((node) => {
if (node.nodeType === 3) {
children.push(new Paragraph(node.textContent));
} else if (node.nodeType === 1) {
console.log(node);
console.log(node.tagName);
if (node.tagName === 'H1') {
children.push(new Paragraph({ text: node.textContent, heading: 'Heading1' }));
} else if (node.tagName === 'P') {
const runs = [];
node.childNodes.forEach((n) => {
const props = {};
if (n.tagName === 'B' || n.tagName === 'STRONG') props.bold = true;
if (n.tagName === 'I' || n.tagName === 'EM') props.italics = true;
runs.push(new TextRun({ text: n.textContent, ...props }));
});
children.push(new Paragraph({ children: runs }));
}
}
});
return children;
}
// //
const doc = new Document({ const doc = new Document({
@ -29,7 +232,6 @@ const download = async (doc) => {
link.href = URL.createObjectURL(blob); link.href = URL.createObjectURL(blob);
link.download = 'document.docx'; link.download = 'document.docx';
// Click the link to download the file
document.body.appendChild(link); document.body.appendChild(link);
link.click(); link.click();
document.body.removeChild(link); document.body.removeChild(link);

@ -66,8 +66,10 @@ export default defineConfig(({ mode, command }) => {
'vue-i18n', 'vue-i18n',
'@vueup/vue-quill', '@vueup/vue-quill',
'image-conversion', 'image-conversion',
'element-plus/es/components/**/css' 'element-plus/es/components/**/css',
] 'mammoth'
],
exclude: ['fs', 'path']
} }
}; };
}); });

Loading…
Cancel
Save