前提:在做项目中有个需求是填写表单后生成一份文档,文档可以编辑、保存。
这部分用富文本处理了,涉及到的逻辑就是对象-->富文本标签形式
在给后端传的数据格式再把富文本标签形式-->对象形式。
涉及到文字,图片、表格,以及图片表格的标题。
数据截取处理
// 数据截取处理extractString(str, startChar, endChar) {const pattern = `${startChar}(.*?)${endChar}`;const regex = new RegExp(pattern);const matches = str.match(regex);return matches ? matches[1] : '';},
用法:
let a = this.extractString(item, '<img', '</p>')
item就是要处理的字串,后面一个开始元素,一个结束元素。
富文本去除所有标签
str='<div class="proposal-content" style="text-indent:2em; font-size:16px; line-height:1.5">光伏组件在运行过程中,光电转换效率会受到影响,输出功率有所降低。本报告年衰减率根据《光伏制造行业规范条件(2021年本)》计算,晶硅组件衰减率首年不高于2.5%,后续每年不高于0.6%。</div>'
let a = str.replace(/<[^>]+>/g, '')
.replace替换其他数据:
proposalString = proposalString.replace(new RegExp('<p data-we-empty-p="" style="padding-left:2em;">', 'g'), paragraph);
‘g’是全局替换,不然只会替换第一个。
富文本转对象大致实现思路:
因为要数据对应,以下是后端传过来的数据:
let obj = [{content:'合浦位于广西壮族自治区北海市合浦县合浦闸口镇。项目所在地的经纬度坐标为21.69°N, 109.52°E。\n合浦县,属亚热带季风型海洋性气候区,日照较强,热量充足,雨量充沛,夏热冬暖,无霜期长。气候受季风环流控制,雨热同季。冬干夏湿,夏无酷暑,冬无严寒,盛行风向有明显的季节性转换,在沿海乡镇还有昼夜交替的海陆风出现。由于各季节雨热不均以及濒临北部湾,主要气象灾害有台风、暴雨、干旱、低温阴雨及霜冻、冰雹、雷电和龙卷风等。主要气候特征是年平均气温偏高,年总降雨量偏多,年总日照时数偏多。\n',image: {title: '项目所在位置图',path: 'https://xidianai.oss-cn-hangzhou.aliyuncs.com/xdai_78abb1eb_loc_map.png',index: 1,},table: {title: '',rowNum: '',colNum: '',head: [],content: [],},},];
对应回显在富文本,
思路:遍历数据结构,加上标签,富文本本身是会回显标签的
this.$nextTick(() => {let content = '';this.chapterList.chapterContent.forEach(item => {if (item.content) {content += item.content.replace(/\n\n\n/g, '<br/> ').replace(/\n\n/g, '<br/> ');content = content.replace(/\n/g, `<br/> `);}// 图片回显if (item.image.path) {content += `<div class="img" style="width: 100%;display: flex;flex-direction: column;justify-content: center;align-items: center;"><img src=${item.image.path} /><div style="font-size: 14px;">图${this.chapterList.chapterIndex}-${item.image.index} <span class="img-title">${item.image.title}</span></div></div><br/> `;}// 表格回显if (item.table.title) {content += `<div class="table" style="width:100%;display: flex;flex-direction: column;justify-content: center;align-items: center;"><span>表${this.chapterList.chapterIndex}-${item.table.index} ${item.table.title}</span><table border="1" cellspacing="0" cellpadding="0" style="width: 100%;"><tbody><tr>`;item.table.head.forEach(item => {content += `<th>${item}</th>`;});content += `<tr>`;item.table.content.forEach(item => {content += `<tr>`;item.forEach(item => {content += `<td>${item}</td>`;});content += `</tr>`;});content += `</tbody></table></div><div class="proposal-content" style="text-indent:2em; font-size:16px; line-height:1.5"></div>`;}});content = `<div class="proposal-content" style="text-indent:2em; font-size:16px; line-height:1.5">${content.replace(`<br/> `, ``).replace(new RegExp('°E。'), `°E。<br/> `)}</div>`;this.editor.txt.html(content);});
用户编辑完成后保存,富文本转对象操作思路:特定标签用replace()替换后,split()成数组,这样obj就拿到了,然后遍历,分开处理content文字,图片,以及图片标题,表格以及表格标题。
// 保存saveProposal() {console.log(this.editor.txt.html());let obj = [{content:'合浦位于广西壮族自治区北海市合浦县合浦闸口镇。项目所在地的经纬度坐标为21.69°N, 109.52°E。\n合浦县,属亚热带季风型海洋性气候区,日照较强,热量充足,雨量充沛,夏热冬暖,无霜期长。气候受季风环流控制,雨热同季。冬干夏湿,夏无酷暑,冬无严寒,盛行风向有明显的季节性转换,在沿海乡镇还有昼夜交替的海陆风出现。由于各季节雨热不均以及濒临北部湾,主要气象灾害有台风、暴雨、干旱、低温阴雨及霜冻、冰雹、雷电和龙卷风等。主要气候特征是年平均气温偏高,年总降雨量偏多,年总日照时数偏多。\n',image: {title: '项目所在位置图',path: 'https://xidianai.oss-cn-hangzhou.aliyuncs.com/xdai_78abb1eb_loc_map.png',index: 1,},table: {title: '',rowNum: '',colNum: '',head: [],content: [],},},];// 段落let paragraph = '<div class="proposal-content" style="text-indent:2em; font-size:16px; line-height:1.5">';let proposalArr = [];// let proposalString =// '<div class="proposal-content" style="text-indent:2em; font-size:16px; line-height:1.5">光伏组件在运行过程中,光电转换效率会受到影响,输出功率有所降低。本报告年衰减率根据《光伏制造行业规范条件(2021年本)》计算,晶硅组件衰减率首年不高于2.5%,后续每年不高于0.6%,25年内不。本项目运营期内逐年上网电量见下表。<div class="table" style="width:100%;display: flex;flex-direction: column;justify-content: center;align-items: center;"><span>表6-1 本项目运营期逐年上网电量统计表</span></div><table border="0" width="100%" cellpadding="0" cellspacing="0"><tbody><tr><th>年份</th><th>年发电量万kWh</th><th>累计发电量万kWh</th><th>年利用小时数h</th></tr><tr></tr><tr><td>1</td><td>59525.59</td><td>59525.59</td><td>1026.3</td></tr><tr><td>19</td><td>55196.46</td><td>1089859.46</td><td>951.66</td></tr></tbody></table><p><br/></p> </div>';let proposalString = this.editor.txt.html();// text-align:left; text-align:center;替换(图后文本)proposalString = proposalString.replace(new RegExp('<div class="proposal-content" style="text-indent:2em; font-size:16px; line-height:1.5; text-align:center;">','g'),paragraph);proposalString = proposalString.replace(new RegExp('<div class="proposal-content" style="text-indent:2em; font-size:16px; line-height:1.5; text-align:left;">','g'),paragraph);// 新增文本proposalString = proposalString.replace(new RegExp('<p data-we-empty-p="" style="padding-left:2em;">', 'g'), paragraph);proposalString = proposalString.replace(new RegExp(paragraph), ``).replace(new RegExp(paragraph, 'g'), `aabb`).split('aabb');proposalString.forEach(item => {let content = '';let image = {};let table = {};// 处理图片数据if (this.extractString(item, 'src="', '"').length > 0) {image.path = this.extractString(item, 'src="', '"');if (item.includes('<span class="img-title">')) {// 图片标题image.title = this.extractString(item, '<span class="img-title">', '</span>');item = item.replace(this.extractString(item, '<img', '</span>'), '');} else {// 编辑图片标题(居中)image.title = this.extractString(item, '<p data-we-empty-p="" style="text-align:center;">', ' ');image.title = this.extractString(item, image.title, '</p>');// 去除img文字item = item.replace(this.extractString(item, '<img', '</p>'), '');}} else {image.path = '';image.title = '';}// 处理表格数据if (item.indexOf('tbody><tr><th>') > -1) {let tableData = this.extractString(item, '<table', '</table>');let tableHeadArr = []; // 截取的要处理的数据let head = []; // 表头let contentList = []; // 表格内容// 获取表头if (item.indexOf('<th>') > -1) {tableHeadArr = tableData.replace(new RegExp('<th>', 'g'), 'tableHead').split('tableHead');}tableHeadArr.forEach(m => {if (m.indexOf('</th>') > -1) {head.push(this.extractString(m, '', '</th>'));}});// 获取表格内容let tableContentOld = tableData.split('</th></tr>')[1]if (tableContentOld.indexOf('<tr><td>') > -1) {tableContentOld = tableContentOld.replace(new RegExp('<tr><td>', 'g'), 'tableContent').split('tableContent');tableContentOld.forEach(m => {let contentArr = []if(m.replace(/<[^>]+>/g, '')){m.replace(new RegExp('</td>', 'g'),'cloumn').replace(new RegExp('<td>', 'g'),'').split('cloumn').forEach((n)=>{if(n.replace(/<[^>]+>/g, '')){contentArr.push(n);}})contentList.push(contentArr);}})// 去除table文字item = item.replace(this.extractString(item, '<img', '</p>'), '');}// table.title = title;table.head = headtable.content = contentListtable.colNum = head.lengthtable.rowNum = contentList.length}// 段落文字处理(去除图片、表格数据、标签、占位符等)content = item.replace(new RegExp('<br/> ', 'g'), '\n').replace(/<[^>]+>/g, '');proposalArr.push({ content: content, image: image, table: table });});console.log(proposalArr);},
代码贴在这里,存在冗余,大致提供一个思路,因为需求还没评审,暂时把这部分功能做出来了。