| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- <!-- 移动端自定义文本编辑组件 - 使用 renderjs 支持 contenteditable -->
- <template>
- <view class="custom-text-container">
- <view id="htmlContent" class="content-editable" :contenteditable="!readonly" v-html="form" :prop="renderProps"
- :change:prop="renderScript.handlePropChange">
- </view>
- </view>
- </template>
- <script>
- export default {
- props: {
- id: {
- type: String,
- default: "",
- },
- readonly: {
- default: false,
- type: Boolean,
- },
- },
- data() {
- return {
- form: null,
- valueObj: {},
- equation: {},
- units: {},
- domId: "",
- cachedHtml: "",
- equationData: null,
- };
- },
- computed: {
- // 合并所有需要传递给 renderjs 的数据
- renderProps() {
- return {
- form: this.form,
- valueObj: this.valueObj,
- equationData: this.equationData,
- equation: this.equation,
- readonly: this.readonly,
- timestamp: Date.now(), // 确保每次都有变化
- };
- },
- },
- methods: {
- // renderjs 回调:失去焦点
- onHtmlBlur({
- html
- }) {
- this.cachedHtml = html;
- },
- onInputINPUT(data) {
- console.log("input 值变化:", data);
- if (data.inputId) {
- if (data.inputType === "checkbox") {
- this.valueObj[data.inputId] = data.checked;
- } else {
- this.valueObj[data.inputId] = data.value;
- }
- }
- this.$emit("calculation");
- },
- equationValue({
- domId,
- value
- }) {
- console.log(value, "value");
- this.valueObj[domId] = value;
- this.equationData = {
- domId: domId,
- value: value,
- timestamp: Date.now(), // 确保每次都能触发 change
- };
- console.log(this.equationData, "this.equationData");
- },
- // 获取值
- getValue() {
- return {
- form: this.cachedHtml || this.form || "",
- valueObj: this.valueObj,
- equation: this.equation,
- units: this.units,
- };
- },
- // 初始化
- init({
- form,
- valueObj,
- equation,
- units
- }) {
- this.form = form || "";
- this.valueObj = valueObj || {};
- console.log(this.valueObj, "this.valueObj");
- this.equation = equation || {};
- this.units = units || {};
- this.cachedHtml = this.form;
- },
- },
- };
- </script>
- <script module="renderScript" lang="renderjs">
- export default {
- data() {
- return {
- };
- },
- mounted() {
- console.log('renderjs mounted');
- this.initEditor();
- },
- methods: {
- // 统一处理所有 prop 变化
- handlePropChange(newVal, oldVal) {
- if (!newVal) return;
- console.log('renderjs 收到数据:', newVal);
- // 处理初始化数据 (valueObj)
- if (newVal.valueObj && Object.keys(newVal.valueObj).length > 0) {
- this.initValues(newVal.valueObj);
- }
- // 处理公式计算数据 (equationData)
- if (newVal.equationData && newVal.equationData.domId) {
- this.updateEquationValue(newVal.equationData);
- }
- if (newVal.readonly) {
- if (this.readonly) {
- let inputs = document.querySelectorAll('.templateInput');
- inputs.forEach((item) => {
- item.setAttribute('readonly', 'readonly');
- });
- }
- }
- if (newVal.equation.length) {
- for (key in newVal.equation) {
- const dom = document.getElementById(key);
- dom.setAttribute('readonly', 'readonly');
- }
- }
- },
- // 初始化 input 值
- initValues(valueObj) {
- console.log('初始化值:', valueObj);
- for (let key in valueObj) {
- const dom = document.getElementById(key);
- if (dom && dom.tagName === 'INPUT') {
- if (dom.type === 'checkbox') {
- dom.checked = valueObj[key];
- } else {
- dom.value = valueObj[key];
- }
- }
- }
- },
- // 更新公式计算值
- updateEquationValue(equationData) {
- console.log('更新公式值:', equationData);
- const {
- domId,
- value
- } = equationData;
- const input = document.getElementById(domId);
- if (input && input.tagName === 'INPUT') {
- input.value = value;
- // // 触发 input 事件通知逻辑层
- // const event = new Event('input', { bubbles: true });
- // input.dispatchEvent(event);
- }
- },
- // 初始化编辑器
- initEditor() {
- const el = document.getElementById('htmlContent');
- if (!el) {
- console.log('htmlContent 元素不存在');
- return;
- }
- // el.style.border = '1px solid #ddd';
- el.style.padding = '10px';
- el.style.minHeight = '100px';
- el.style.overflow = 'auto';
- // 监听 input 事件
- el.addEventListener('input', this.handleInput.bind(this));
- console.log('renderjs 编辑器初始化完成');
- },
- // 处理 input 事件
- handleInput(e) {
- const html = e.target.innerHTML;
- // 通知逻辑层 HTML 内容变化
- if (e.target.tagName === 'INPUT') {
- const data = {
- inputId: e.target.id,
- value: e.target.value,
- checked: e.target.checked,
- inputType: e.target.type
- };
- this.$ownerInstance.callMethod('onInputINPUT', data);
- } else {
- this.$ownerInstance.callMethod('onHtmlBlur', {
- html
- });
- }
- },
- }
- };
- </script>
- <style lang="scss" scoped>
- .custom-text-container {
- width: 100%;
- min-height: 200rpx;
- position: relative;
- background-color: #fff;
- }
- .content-editable {
- width: 100%;
- min-height: 150rpx;
- padding: 10px;
- background-color: #fff;
- border-radius: 4px;
- font-size: 14px;
- line-height: 1.5;
- word-wrap: break-word;
- }
- /* contenteditable 内部样式 */
- .content-editable :deep(input) {
- border: 1px solid #ddd;
- padding: 2px 5px;
- border-radius: 3px;
- font-size: 14px;
- }
- .content-editable :deep(input:focus) {
- outline: none;
- border-color: #007aff;
- }
- </style>
|