123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071 |
- <template>
- <div class="template-textarea">
- <template v-if="isEdit == 1">
- <div class="editor-area sticky-editor">
- <ckeditor
- ref="editor"
- v-model="com.content"
- @focus="onFocus"
- @blur="onBlur"
- @input="onInputText"
- @ready="onEditorReady"
- :config="editorConfig"
- :editorUrl="editorUrl"
- ></ckeditor>
- </div>
- </template>
- <template v-else>
- <div
- class="rich-editor"
- ref="richEditor"
- v-html="content"
- @click="handleImageClick"
- ></div>
- </template>
- <div v-if="loading" class="overlay">
- <el-progress
- :percentage="progress"
- class="full-width-progress"
- ></el-progress>
- </div>
- </div>
- </template>
- <script>
- // import CKEditor from "ckeditor4-vue";
- import { findData, uploadImage } from "@/api/sourceData";
- import axios from "axios"; // 确保导入 axios
- import { data } from "jquery";
- export default {
- name: "app",
- emits: ["onUpdate", "onUpdateAttr", "onUpdateProdAttr"],
- compnents: {
- // ckeditor: CKEditor.component
- },
- props: {
- coms: {
- type: Array,
- default: () => {
- return [];
- },
- },
- isEdit: {
- type: Number,
- default: 2,
- },
- isAdmin: {
- type: Number,
- default: 2,
- },
- currentIndex: {
- type: Number,
- default: 0,
- },
- com: {
- type: Object,
- default: null,
- },
- insertCmd: {
- type: Object,
- default: null,
- },
- },
- watch: {
- isEdit: {
- handler(val) {
- let _this = this;
- if (_this.com != null) return;
- _this.replaceData(_this.com.content).then((res) => {
- _this.content = res;
- _this.$nextTick(() => {
- _this.bindEvents();
- });
- });
- },
- immediate: true,
- deep: true,
- },
- com: {
- async handler(val) {
- let _this = this;
- if (val == null) return;
- if (val.content == undefined || val.content == null) return;
- try {
- let res = await _this.replaceData(val.content);
- _this.content = res;
- _this.$nextTick(() => {
- _this.bindEvents();
- _this.initializeInputWidths();
- });
- } catch (error) {
- console.error("处理 com 时出错:", error);
- }
- },
- immediate: true,
- deep: true,
- },
- insertCmd: {
- handler(val) {
- if (val == null || this.isEdit != 1) return;
- let data = this.$refs.editor.instance.getSelection().getSelectedText();
- if (val.content.indexOf("Directory", 0) >= 0) {
- //执行的是目录
- this.$emit(
- "onUpdateAttr",
- this.currentIndex,
- this.com.attrs.length - 1,
- data
- );
- this.$refs.editor.instance.execCommand("delete");
- }
- this.$refs.editor.instance.insertHtml(val.content);
- },
- immediate: true,
- deep: true,
- },
- },
- data() {
- return {
- editorUrl: "/ckeditor/ckeditor.js",
- editorConfig: {
- language: "zh-cn",
- height: "650px",
- },
- content: "",
- editor: null,
- loading: false,
- progress: 0,
- isEditing: false,
- focusedInputId: null,
- variableNullInputs: {},
- };
- },
- mounted() {
- this.$nextTick(() => {
- this.initializeInputWidths();
- });
- },
- // 记得在组件销毁时移除事件监听器
- beforeDestroy() {
- this.$el.removeEventListener("input", this.handleInputChange);
- this.$el.removeEventListener("input", this.handleVariableNullInput);
- this.$el.removeEventListener("blur", this.handleVariableNullBlur, true);
- },
- methods: {
- async replaceData(data) {
- let _this = this;
- // 定义数学函数和 IF 函数
- const mathFunctions = {
- abs: Math.abs,
- ceil: Math.ceil,
- floor: Math.floor,
- max: Math.max,
- min: Math.min,
- round: Math.round,
- sqrt: Math.sqrt,
- IF: (condition, trueValue, falseValue) =>
- condition ? trueValue : falseValue,
- // 添加其他需要的数学函数
- };
- for (var i = 0; i < _this.com.attrs.length; i++) {
- let attrId = _this.com.attrs[i].id;
- if (_this.com.attrs[i].type == "variable") {
- let item = _this.com.attrs[i];
- if (item.data.value_type == 2) {
- //多选
- let dataItem = item.data.value_item.split(",");
- let selectHtml =
- '<select id="' +
- attrId +
- '" data-index="' +
- i +
- '" class="text-input-box">';
- for (var l = 0; l < dataItem.length; l++) {
- if (item.content == dataItem[l]) {
- selectHtml +=
- '<option value="' +
- dataItem[l] +
- '" selected>' +
- dataItem[l] +
- "</option>";
- } else {
- selectHtml +=
- '<option value="' +
- dataItem[l] +
- '">' +
- dataItem[l] +
- "</option>";
- }
- }
- selectHtml += "</select>";
- data = data.replace("{{" + item.id + "}}", selectHtml);
- } else {
- //文本
- data = data.replace(
- "{{" + attrId + "}}",
- /* `<input type="text" class="text-input-box" data-index="${i}" value="${_this.com.attrs[i].content}" @input="updateContent('${_this.com.attrs[i].id}', $event)" id="${attrId}">`, */
- '<input type="text" ref="input_' +
- attrId +
- '" name="' +
- _this.com.attrs[i].name +
- '" id="' +
- attrId +
- '" data-index="' +
- i +
- '" class="text-input-box auto-width" value="' +
- _this.com.attrs[i].content +
- '">'
- );
- }
- } else if (_this.com.attrs[i].type == "variableNull") {
- let item = _this.com.attrs[i];
- // 使用唯一的标识符来初始化每个输入框的值
- this.variableNullInputs[attrId] = item.content;
- data = data.replace(
- "{{" + attrId + "}}",
- '<input type="text" ' +
- 'ref="input_' +
- attrId +
- '" ' +
- 'name="' +
- item.name +
- '" ' +
- 'id="' +
- attrId +
- '" ' +
- 'data-index="' +
- i +
- '" ' +
- 'data-attr-id="' +
- attrId +
- '" ' +
- 'class="text-input-boxs auto-width" ' +
- 'value="' +
- item.content +
- '">'
- );
- } else if (_this.com.attrs[i].type == "ProductAttr") {
- //处理产品属性值
- let item = _this.com.attrs[i];
- let prodAttrId = item.id + "_" + i;
- if (item.content == "") {
- item.content = item.attrs.value;
- }
- if (item.attrs.type == 1) {
- //输入框
- data = data.replace(
- "{{" + item.id + "}}",
- '<input type="text" id="' +
- prodAttrId +
- '" data-index="' +
- i +
- '" class="text-input-box" value="' +
- item.content +
- '">'
- );
- } else {
- //选择框
- let dataItem = item.attrs.valueItems.split(",");
- let selectHtml =
- '<select id="' +
- prodAttrId +
- '" data-index="' +
- i +
- '" class="text-input-box">';
- for (var l = 0; l < dataItem.length; l++) {
- if (item.content == dataItem[l]) {
- selectHtml +=
- '<option value="' +
- dataItem[l] +
- '" selected>' +
- dataItem[l] +
- "</option>";
- } else {
- selectHtml +=
- '<option value="' +
- dataItem[l] +
- '">' +
- dataItem[l] +
- "</option>";
- }
- }
- selectHtml += "</select>";
- data = data.replace("{{" + item.id + "}}", selectHtml);
- }
- } else if (_this.com.attrs[i].type == "formual") {
- //处理计算公式 不处理
- let formual = await _this.analysisFormual(_this.com.attrs[i]);
- let point = _this.com.attrs[i].data.point;
- formual = await _this.getRemote(formual);
- /* console.log("处理的公式:", formual); // 添加日志 */
- // 收集公式中使用的变量
- const variables = {};
- const variableRegex = /\b[a-zA-Z_][a-zA-Z0-9_]*\b/g;
- const matches = formual.match(variableRegex);
- if (matches) {
- for (const varName of matches) {
- if (
- varName !== "IF" &&
- !Object.keys(mathFunctions).includes(varName)
- ) {
- variables[varName] = `${varName}`; // 默认值设为0,您可以根据需要修改
- }
- }
- }
- /* console.log("识别的变量:", variables); // 添加日志 */
- // 定义一个安全的评估函数
- const safeEval = (formula, variables) => {
- // 创建一个新的函数,将数学函数和变量作为参数传入
- const func = new Function(
- ...Object.keys(mathFunctions),
- ...Object.keys(variables),
- `return ${formula}`
- );
- // 执行函数,传入数学函数和变量作为参数
- return func(
- ...Object.values(mathFunctions),
- ...Object.values(variables)
- );
- };
- try {
- const result = safeEval(formual, variables);
- /* console.log("计算结果:", result); // 添加日志 */
- let formattedResult;
- if (typeof result === "number" && !isNaN(result)) {
- formattedResult = result.toFixed(point);
- } else if (typeof result === "boolean") {
- formattedResult = result ? "1" : "0";
- } else {
- formattedResult = String(result);
- }
- _this.com.attrs[i].content = formattedResult;
- data = data.replace(
- "{{" + _this.com.attrs[i].id + "}}",
- formattedResult
- );
- } catch (error) {
- console.error("处理公式时出错:", error);
- console.error("错误的公式:", formual);
- _this.com.attrs[i].content = "计算错误";
- data = data.replace(
- "{{" + _this.com.attrs[i].id + "}}",
- "计算错误"
- );
- }
- /* let formual = await _this.analysisFormual(_this.com.attrs[i]);
- formual = await _this.getRemote(formual);
- // 使用 try-catch 来处理可能的计算错误
- try {
- let result = eval(formual);
- data = data.replace("{{" + attrId + "}}", result);
- } catch (error) {
- data = data.replace("{{" + attrId + "}}", "计算错误");
- } */
- } else if (_this.com.attrs[i].type == "sourceData") {
- let result = await _this.getRemote1(_this.com.attrs[i].formula);
- data = data.replace("{{" + attrId + "}}", result);
- } else if (_this.com.attrs[i].type == "Directory") {
- const directoryContent = _this.com.attrs[i].content;
- const level = _this.com.attrs[i].level || 1; // 默认为1级目录
- const attrId = _this.com.attrs[i].id;
- // 创建一个更灵活的正则表达式模式,匹配可能存在的div包裹
- const directoryRegex = new RegExp(
- `<div[^>]*>\\s*{{\\s*${attrId}\\s*}}\\s*</div>|{{\\s*${attrId}\\s*}}`,
- "g"
- );
- // 替换内容,直接生成标题标签
- data = data.replace(directoryRegex, (match, offset, string) => {
- // 根据级别创建适当的HTML标签
- const tag = `h${Math.min(level, 6)}`; // 限制最大级别为h6
- const className = `directory-level-${level}`;
- return `<${tag} class="${className}">${directoryContent}</${tag}>`;
- });
- //处理目录
- /* data = data.replace(
- "<p>{{" + attrId + "}}</p>",
- "<h1>" + _this.com.attrs[i].content + "</h1>"
- );
- data = data.replace(
- "<div>{{" + attrId + "}}</div>",
- "<h1>" + _this.com.attrs[i].content + "</h1>"
- );
- data = data.replace(
- "<span>{{" + attrId + "}}</span>",
- "<h1>" + _this.com.attrs[i].content + "</h1>"
- ); */
- //处理目录
- /* const directoryContent = _this.com.attrs[i].content;
- const directoryRegex = new RegExp(
- `<(p|div|span)>{{${attrId}}}</(p|div|span)>`,
- "g"
- );
- data = data.replace(directoryRegex, `<h1>${directoryContent}</h1>`); */
- } else {
- //处理常量及其它
- data = data.replace("{{" + attrId + "}}", _this.com.attrs[i].content);
- }
- }
- this.$nextTick(() => {
- this.addInputListeners();
- this.initializeInputWidths();
- this.addVariableNullListeners();
- });
- return data;
- },
- // 新增方法:为 variableNull 类型的输入框添加事件监听器
- addVariableNullListeners() {
- this.$el.addEventListener("input", this.handleVariableNullInput);
- this.$el.addEventListener("blur", this.handleVariableNullBlur, true);
- },
- handleVariableNullInput(event) {
- if (event.target.classList.contains("text-input-boxs")) {
- const attrId = event.target.dataset.attrId;
- const newValue = event.target.value;
- // 只更新特定输入框的值
- this.$set(this.variableNullInputs, attrId, newValue);
- }
- },
- handleVariableNullBlur(event) {
- if (event.target.classList.contains("text-input-boxs")) {
- const index = parseInt(event.target.dataset.index, 10);
- const attrId = event.target.dataset.attrId;
- const newValue = this.variableNullInputs[attrId];
- // 只更新特定属性的内容
- this.updateVariableNullContent(index, attrId, newValue, true);
- }
- },
- updateVariableNullContent(index, attrId, newValue, emitEvent = false) {
- if (this.com && this.com.attrs && this.com.attrs[index]) {
- if (this.com.attrs[index].id === attrId) {
- // 只更新特定属性的内容
- this.$set(this.com.attrs[index], "content", newValue);
- // 更新输入框的值
- this.$nextTick(() => {
- const input = this.$el.querySelector(`#${attrId}`);
- if (input) {
- input.value = newValue;
- }
- });
- // 触发事件
- if (emitEvent) {
- this.$emit("onUpdata", this.currentIndex, index, attrId, newValue);
- }
- }
- }
- },
- addInputListeners() {
- // 使用事件委托来处理所有的 .text-input-box 元素
- this.$el.addEventListener("blur", this.handleInputChange, true);
- this.$el.addEventListener("input", this.adjustInputWidth, true);
- },
- initializeInputWidths() {
- const inputs = this.$el.querySelectorAll(
- ".text-input-box, .text-input-boxs"
- );
- inputs.forEach((input) => this.adjustInputWidth({ target: input }));
- },
- // 修改这个方法,使其同时处理 variableNull 类型的输入框
- adjustInputWidth(event) {
- if (
- event.target.classList.contains("text-input-box") ||
- event.target.classList.contains("text-input-boxs")
- ) {
- const input = event.target;
- const sizeCalculator = document.createElement("span");
- sizeCalculator.className = "size-calculator";
- sizeCalculator.textContent = input.value || input.placeholder || "0";
- document.body.appendChild(sizeCalculator);
- const styles = window.getComputedStyle(input);
- sizeCalculator.style.font = styles.font;
- sizeCalculator.style.fontSize = styles.fontSize;
- sizeCalculator.style.fontWeight = styles.fontWeight;
- sizeCalculator.style.letterSpacing = styles.letterSpacing;
- const width = sizeCalculator.offsetWidth;
- input.style.width = `${width + 10}px`; // Add some padding
- document.body.removeChild(sizeCalculator);
- }
- },
- // 修改这个方法,使其同时处理 variableNull 类型的输入框
- handleInputChange(event) {
- if (
- event.target.classList.contains("text-input-box") ||
- event.target.classList.contains("text-input-boxs")
- ) {
- const attrId = event.target.id;
- const attrName = event.target.name;
- const dataIndex = parseInt(event.target.dataset.index, 10);
- const newValue = event.target.value;
- // 更新数据
- if (this.com && this.com.attrs && this.com.attrs[dataIndex]) {
- this.$set(this.com.attrs[dataIndex], "content", newValue);
- this.com.attrs.forEach((el) => {
- if (el.name === attrName) {
- this.$set(el, "content", newValue);
- }
- });
- this.$emit("onUpdateAttr", this.currentIndex, dataIndex, newValue);
- } else {
- console.warn(`Unable to find attribute at index ${dataIndex}`);
- }
- }
- },
- bindEvents() {
- let _this = this;
- for (var i = 0; i < _this.com.attrs.length; i++) {
- let attrId = _this.com.attrs[i].id;
- let item = _this.com.attrs[i];
- if (_this.com.attrs[i].type == "variable") {
- //变量事件
- let input = _this.$el.querySelector("#" + attrId);
- if (input) {
- if (item.data.value_type == 2) {
- //下拉选择
- input.addEventListener("change", _this.handleInput);
- } else {
- //文本输入
- input.addEventListener("blur", _this.handleInput);
- }
- }
- } else if (_this.com.attrs[i].type == "ProductAttr") {
- //绑定产品属性事件
- let prodAttrId = item.id + "_" + i;
- let input = _this.$el.querySelector("#" + prodAttrId);
- if (input) {
- if (item.attrs.type == 1) {
- input.addEventListener("blur", _this.handleInputProduct);
- } else {
- input.addEventListener("change", _this.handleChangeProduct);
- }
- }
- }
- }
- },
- //分析公式
- async analysisFormual(attrs) {
- let _this = this;
- /* console.log("开始分析公式:", attrs.formula); */
- let formual = attrs.formula;
- // 处理 [T][...][...] 引用
- const tPattern = /\[T\]\[(.*?)\]\[(.*?)\]/g;
- formual = await this.replaceAsync(
- formual,
- tPattern,
- async (match, p1, p2) => {
- try {
- let data = await _this.getModuleData(p1, p2);
- /* console.log(`获取到的数据: ${match} = ${data}`); */
- if (data === null || data === undefined) {
- console.warn(`获取到的数据无效: ${match}`);
- return "''"; // 返回空字符串而不是 0
- } else {
- return typeof data === "string" ? `${data}` : data;
- }
- } catch (error) {
- console.error(`处理 ${match} 时出错:`, error);
- return "''";
- }
- }
- );
- // 处理嵌套的 IF 语句
- const ifPattern = /IF\s*\((.*?),(.*?),(.*?)\)/gi;
- let depth = 0;
- while (formual.match(ifPattern) && depth < 10) {
- formual = formual.replace(
- ifPattern,
- (match, condition, trueValue, falseValue) => {
- // 递归处理嵌套的 IF 语句
- if (
- trueValue.includes("IF(") ||
- falseValue.includes("IF(") ||
- trueValue.includes("if(") ||
- falseValue.includes("if(")
- ) {
- return `(${condition} ? (${trueValue}) : (${falseValue}))`;
- }
- return `(${condition} ? ${trueValue} : ${falseValue})`;
- }
- );
- depth++;
- }
- /* console.log("分析后的公式:", formual); */
- return formual;
- },
- // 辅助方法:异步替换
- async replaceAsync(str, regex, asyncFn) {
- const promises = [];
- str.replace(regex, (match, ...args) => {
- const promise = asyncFn(match, ...args);
- promises.push(promise);
- });
- const data = await Promise.all(promises);
- return str.replace(regex, () => data.shift());
- },
- // 辅助方法:异步替换
- async replaceAsync(str, regex, asyncFn) {
- const promises = [];
- str.replace(regex, (match, ...args) => {
- const promise = asyncFn(match, ...args);
- promises.push(promise);
- });
- const data = await Promise.all(promises);
- return str.replace(regex, () => data.shift());
- },
- async getFormualData(formualItem, data) {
- let _this = this;
- // console.log("开始获取公式数据:", formualItem);
- var pattern = /\[(.*?)\]\[(.*?)\]\[(.*?)\]/;
- var reg = new RegExp(pattern);
- let items = formualItem.match(reg);
- // console.log("解析结果:", items);
- let calResult = 0;
- if (items && items[1] == "T") {
- calResult = await _this.getModuleData(items[2], items[3]);
- } else {
- console.warn("无法解析公式项:", formualItem);
- }
- /* console.log("计算结果:", formualItem,data); */
- return calResult;
- },
- async getRemote(formual) {
- let _this = this;
- var pattern = /\[(.*?)\]\[(.*?)\]\[(.*?)\]\[(.*?)\]/;
- var reg = new RegExp(pattern);
- while (true) {
- let items = formual.match(reg);
- if (items == null) break;
- if (items[1] == "R") {
- //表示获取远程数据
- var dataIndex = items[4];
- dataIndex = items[4].split(",");
- let calResult = await _this.getRemoteData(
- items[2],
- items[3],
- dataIndex[0],
- dataIndex[1]
- );
- let itemName = items[0];
- // 检查calResult是否为数字
- if (!isNaN(calResult)) {
- formual = formual.replace(
- itemName,
- "(" + parseFloat(calResult) + ")"
- );
- } else {
- formual = formual.replace(itemName, `"${calResult}"`);
- }
- formual = formual.replace(
- itemName,
- "(" + parseFloat(calResult) + ")"
- );
- }
- }
- return formual;
- },
- async getRemote1(formual) {
- let _this = this;
- var pattern = /\[(.*?)\]\[(.*?)\]\[(.*?)\]\[(.*?)\]/;
- var reg = new RegExp(pattern);
- while (true) {
- let items = formual.match(reg);
- if (items == null) break;
- if (items[1] == "R") {
- //表示获取远程数据
- var dataIndex = items[4];
- dataIndex = items[4].split(",");
- let calResult = await _this.getRemoteData(
- items[2],
- items[3],
- dataIndex[0],
- dataIndex[1]
- );
- let itemName = items[0];
- // 检查calResult是否为数字
- if (!isNaN(calResult)) {
- formual = formual.replace(
- itemName,
- "(" + parseFloat(calResult) + ")"
- );
- } else {
- formual = formual.replace(itemName, `"${calResult}"`);
- }
- /* formual=formual.replace(itemName,parseFloat(calResult)); */
- }
- }
- return formual;
- },
- onFocus() {
- this.isEditing = true;
- },
- onBlur() {
- this.isEditing = false;
- },
- async getRemoteData(code, sheet, row, col) {
- let _this = this;
- let result = 0;
- let par = {
- code: code,
- sheetName: sheet,
- row: row,
- col: col,
- };
- /* if (!this.isEditing) {
- this.loading = true;
- this.progress = 0;
- try {
- const updateProgress = setInterval(() => {
- if (this.progress < 90) {
- this.progress += 10;
- }
- }, 100);
- let res = await findData(par);
- if (res.status == 200) {
- result = res.data.result;
- }
- this.progress = 100;
- clearInterval(updateProgress);
- } catch (error) {
- console.error("Error fetching remote data:", error);
- } finally {
- setTimeout(() => {
- this.loading = false;
- this.progress = 0;
- }, 1000);
- }
- } else { */
- // 如果正在编辑,直接获取数据而不显示进度条
- try {
- let res = await findData(par);
- if (res.status == 200) {
- result = res.data.result;
- // 添加数据类型检查和转换
- if (typeof result === "string" && !isNaN(result)) {
- result = parseFloat(result);
- }
- }
- } catch (error) {
- console.error("获取远程数据错误:", error);
- }
- /* } */
- return result;
- },
- //获取本地文档模块数据
- async getModuleData(code, attrName) {
- let _this = this;
- /* console.log(`尝试获取模块数据: code=${code}, attrName=${attrName}`);
- console.log("当前 coms:", _this.coms); */
- let item = _this.coms.filter((o) => o.name == code);
- /* console.log(`找到的模块:`, item); */
- if (item.length > 0) {
- let attr = item[0].attrs.filter((o) => o.name == attrName);
- /* console.log(`找到的属性:`, attr); */
- if (attr.length > 0) {
- /* console.log(`返回的值:`, attr[0].content); */
- return attr[0].content; // 返回原始值,不进行转换
- }
- }
- /* console.log("未找到匹配的模块或属性,返回空字符串"); */
- return ""; // 返回空字符串而不是 0
- },
- handleChangeProduct(e) {
- let dataIndex = e.target.dataset.index;
- this.$emit(
- "onUpdateProdAttr",
- this.currentIndex,
- dataIndex,
- e.target.value
- );
- },
- handleInputProduct(e) {
- let dataIndex = e.target.dataset.index;
- this.$emit(
- "onUpdateProdAttr",
- this.currentIndex,
- dataIndex,
- e.target.value
- );
- },
- handleInput(e) {
- let dataIndex = e.target.dataset.index;
- this.$emit("onUpdateAttr", this.currentIndex, dataIndex, e.target.value);
- },
- onEditorReady(editor) {},
- onInputText(e) {
- this.$emit("onUpdate", this.currentIndex, e);
- },
- /* 点击替换图片 */
- handleImageClick(event) {
- if (event.target.tagName === "IMG") {
- this.replaceImage(event.target);
- }
- },
- selectImage() {
- return new Promise((resolve) => {
- const input = document.createElement("input");
- input.type = "file";
- input.accept = "image/*";
- input.onchange = (e) => resolve(e.target.files[0]);
- input.click();
- });
- },
- async uploadImage(formData) {
- try {
- const response = await axios.post(
- "http://58.246.234.210:8084/upload/image",
- formData,
- {
- headers: {
- "Content-Type": "multipart/form-data",
- },
- }
- );
- console.log("Upload response:", response);
- if (response.status === 200 && response.data && response.data.url) {
- return response.data.url;
- } else {
- throw new Error("Invalid upload response");
- }
- } catch (error) {
- console.error("Error uploading image:", error);
- throw error;
- }
- },
- /* updateContentWithNewImage(imgElement) {
- // 更新 content 中的图片 URL
- const tempDiv = document.createElement('div');
- tempDiv.innerHTML = this.content;
- const images = tempDiv.getElementsByTagName('img');
- for (let img of images) {
- if (img.src === imgElement.src) {
- img.src = imgElement.src;
- break;
- }
- }
- this.content = tempDiv.innerHTML;
- this.$emit('onUpdate', this.currentIndex, this.content);
- }, */
- async replaceImage(imgElement) {
- try {
- const file = await this.selectImage();
- if (file) {
- const formData = new FormData();
- formData.append("upload", file);
- const uploadedUrl = await this.uploadImage(formData);
- // Update the image element in the DOM
- imgElement.src = uploadedUrl;
- // Update the content and notify parent component
- this.$nextTick(() => {
- this.updateContentWithNewImage(imgElement, uploadedUrl);
- });
- }
- } catch (error) {
- console.error("Error replacing image:", error);
- }
- },
- updateContentWithNewImage(imgElement, newImageUrl) {
- // Get the rich-editor div
- const richEditor = this.$refs.richEditor;
- // Create a new Image element with the new URL
- const newImg = document.createElement("img");
- newImg.src = newImageUrl;
- // Copy attributes from the old image to the new one
- for (let attr of imgElement.attributes) {
- if (attr.name !== "src") {
- newImg.setAttribute(attr.name, attr.value);
- }
- }
- // Replace the old image with the new one
- imgElement.parentNode.replaceChild(newImg, imgElement);
- // Update this.content with the latest DOM content
- this.content = richEditor.innerHTML;
- // Update the com object
- this.com.content = this.content;
- // Emit an event to update the parent component
- this.$emit("updateComContent", this.currentIndex, this.com);
- },
- /* updateComsData(newImageUrl) {
- // 找到当前组件在 coms 数组中的索引
- const comIndex = this.coms.findIndex((com) => com.name === this.com.name);
- if (comIndex !== -1) {
- // 创建 coms 的深拷贝
- const updatedComs = JSON.parse(JSON.stringify(this.coms));
- // 更新特定组件的 content
- updatedComs[comIndex].content = this.content;
- // 如果有特定的图片属性,也更新它
- const imgAttr = updatedComs[comIndex].attrs.find(
- (attr) => attr.type === "image"
- );
- if (imgAttr) {
- imgAttr.content = newImageUrl;
- }
- // 更新 coms
- this.$emit("update:coms", updatedComs);
- }
- }, */
- /* onFocus(e) {
- // var range = e.editor.getSelection().getRanges()[0];
- // range.collapse( true );
- // range.setStartAt( e.editor.editable(), CKEDITOR.POSITION_AFTER_START );
- // e.editor.insertText("AAA");
- },
- onBlur(e) {
- //// console.log(' onBlur e',e);
- // this.$emit("onUploadAttr",this.dataIndex,this.dataAttr);
- }, */
- },
- };
- </script>
- <style lang="scss" scoped>
- @import "./index.scss";
- .template-textarea {
- position: relative;
- }
- .overlay {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background: rgba(0, 0, 0, 0.5); // Semi-transparent background
- display: flex;
- align-items: center;
- justify-content: center;
- z-index: 10; // Ensure it is above other content
- }
- .full-width-progress {
- width: 80%; // Adjust as needed
- color: inherit; // Ensure the color remains unchanged
- }
- .auto-width-wrapper {
- display: inline-block;
- position: relative;
- }
- .size-calculator {
- position: absolute;
- top: -9999px;
- left: -9999px;
- white-space: pre;
- font-family: inherit;
- font-size: inherit;
- font-weight: inherit;
- padding: 2px 4px;
- }
- .editor-wrapper {
- position: relative;
- }
- .sticky-toolbar {
- position: sticky;
- top: 0;
- z-index: 1000;
- background-color: #fff;
- border-bottom: 1px solid #d1d1d1;
- }
- .editor-area {
- ::v-deep .cke_top {
- display: block; // Hide the original toolbar
- }
- }
- ::v-deep .directory-level-1 {
- font-size: 24px;
- font-weight: bold;
- margin-left: 0;
- }
- ::v-deep .directory-level-2 {
- font-size: 20px;
- font-weight: bold;
- margin-left: 20px;
- }
- ::v-deep .directory-level-3 {
- font-size: 18px;
- font-weight: bold;
- margin-left: 40px;
- }
- ::v-deep .directory-level-4 {
- font-size: 16px;
- font-weight: bold;
- margin-left: 60px;
- }
- ::v-deep .directory-level-5 {
- font-size: 14px;
- font-weight: bold;
- margin-left: 80px;
- }
- ::v-deep .directory-level-6 {
- font-size: 12px;
- font-weight: normal;
- margin-left: 100px;
- }
- </style>
|