codemirror构建一个xml编辑器

定义一个html使用形式的Vue组件:

Vue.component("v-codemirror-editor", {
    data() {
        return {
            editor: null,
            style: {},
            max: false,
            json: this.value,
            internalChange: false,
            defaultOptions: {
                tabSize: 4,
                mode: "text/x-groovy",   //默认groovy
                lineNumbers: true,       //显示行号
                lineWrapping: true,      //代码折叠
                styleActiveLine: true,   // 当前行背景高亮
                indentUnit: 4,           // 缩进单位为4
                matchBrackets: true,     //括号匹配
                smartIndent: true,       // 自动缩进
                autofocus: true,         // 自动焦点
                autoCloseBrackets: true  // 自动补全括号
            }
        }
    },
    props: {
        options: {
            type: Object,
            default: () => {
                return {
                    mode: "text/x-groovy"
                }
            }
        },
        modes: {
            type: Array,
            default: function() {
                return ["text/x-groovy", "text/x-java", "text/x-scala", "text/x-go", "text/javascript", "application/xml"];
            }
        },
        value: {
            type: String,
            default: ''
        },
        height: {
            type: String
        },
        schema: null,
        autosize:  {
            type: Object,
            default: () => {
                return {
                    maxHeight: 500,
                    minHeight: 200
                }
            }
        }
    },
    methods: {
        onChange() {
            try {
                let json = this.editor.get();
                if (this.editor) {
                    this.internalChange = true;
                    this.json = json;
                    this.$emit("code-change", json);
                    this.$nextTick(() => {
                        this.internalChange = false
                    })
                }
            } catch (err) {
                this.$emit("code-error", err);
            }
        },
        initView() {
            const self = this;
            const _options = Object.assign(this.defaultOptions, this.options);
            console.log("CodeMirror options: ", _options)
            this.editor = CodeMirror.fromTextArea(this.$el.querySelector('textarea'), _options)
            this.editor.setValue(this.value)
            this.editor.on('change', function(cm) {
                if (!!self.$emit) {
                    self.$emit('code-change', cm.getValue());
                    self.$emit('input', cm.getValue());
                }
            });
            this.editor.on('keyup', function(cm, event) {
                //console.log(event.keyCode)
                if(!cm.state.completionActive && ((event.keyCode >= 65 && event.keyCode <= 90)
                    || event.keyCode === 52 || event.keyCode === 219 || event.keyCode === 190
                    || event.keyCode === 188 || event.keyCode === 57) ) {
                    CodeMirror.commands.autocomplete(cm, null, {completeSingle:false})
                }
            });
            self.$emit('code-init', this, this.editor, this.editor.getValue());
        },
        refresh() {
            this.$nextTick(() => {
                this.editor.refresh()
            })
        },
        destroyView() {
            if (this.editor) {
                // garbage cleanup
                const element = this.editor.doc.cm.getWrapperElement()
                element && element.remove && element.remove();
                this.editor = null;
            }
        },
        handlerCodeChange(newVal) {
            var editorValue = this.editor.getValue();
            if (newVal !== editorValue) {
                var scrollInfo = this.editor.getScrollInfo();
                this.editor.setValue(newVal)
                this.editor.scrollTo(scrollInfo.left, scrollInfo.top)
            }
        },
        async setEditor(value) {
            if (this.editor) {
                //this.json = value;
                this.editor.setValue(value);
            }
        }
    },
    watch: {
        options: {
            deep: true,
            handler(options) {
                for (const key in options) {
                    this.editor.setOption(key, options[key])
                }
            }
        },
        value(newVal) {
            this.handlerCodeChange(newVal);
        },
        // value: {
        //     immediate: true,
        //     async handler(val) {
        //         //console.log("val:" + JSON.stringify(val));
        //         if (!this.internalChange) {
        //             //await this.setEditor(val);
        //             this.setEditor(val);
        //         }
        //     },
        //     deep: true
        // },
        max(value) {
            this.$nextTick(() => {
                this.initView()
            })
        }
    },
    mounted() {
        this.initView()
    },
    beforeDestroy() {
        this.destroyView()
    },
    computed: {
        getHeight() {
            if (!this.max) {
                console.log(this)
                console.log(this.$el)
                console.log("this.height: ", typeof this.$el)
                console.log("this.height: ", typeof this)
                if(this.$el) {
                    console.log("this.offsetWidth: ", this.$el.offsetWidth)
                }
                //console.log("autosize:" + JSON.stringify(this.autosize));
                let h = this.height;
                let maxHeight = this.autosize.maxHeight;
                let minHeight = this.autosize.minHeight;
                if (this.editor) {

                    let json = JSON.stringify(this.editor.getValue());

                    // console.log("jsonlength : ", json.length);
                    // console.log("json : ", json);

                    let ch = 0;
                    if(undefined !== json && null !== json && this.$el) {
                        ch = (json.length / this.$el.offsetWidth) * 140 + 50;
                        if(json.indexOf('\n') > -1) {
                            console.log("json split: ", json.split('\n').length);
                            ch = ch + json.split('\n').length * 80;
                        }
                    }

                    if(maxHeight && ch > maxHeight) {
                        ch = maxHeight;
                    }
                    if(minHeight && ch < minHeight) {
                        ch = minHeight;
                    }
                    h = ch + "px";
                    console.log("getHeight:" + h);
                }
                return {
                    height: h
                }
            }
            return {}
        }
    },
    template: '  <div class="ele-form-codemirror" :class="{\'max-box\':max,\'min-box\':!max}" :style="getHeight">' +
        '        <textarea :style="getHeight"></textarea>' +
        '      </div>'

});

页面使用:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <link rel="icon" href="/static/favicon.ico">
    <!--    <meta name="viewport" content="width=device-width, initial-scale=1">-->
    <!-- 引入样式 -->
    <link rel="stylesheet" href="/static/vue/element-ui.css">
    <link rel="stylesheet" href="/static/css/main.css">
    <link rel="stylesheet" href="/static/css/jsoneditor.css">
    <link rel="stylesheet" href="/static/css/v-json-editor.css">

    <link href="/static/codemirror/codemirror.css" rel="stylesheet">
    <link href="/static/codemirror/monokai.css" rel="stylesheet">
    <link href="/static/codemirror/show-hint.css" rel="stylesheet">
    <style>
        .el-table .warning-row {
            background: oldlace;
        }

        .el-table .success-row {
            background: #f0f9eb;
        }

        .el-table__expanded-cell[class*=cell] {
            padding: 2px 2px;
        }

        .blank_col {
            height: 20px;
        }
        .CodeMirror {
            height: auto;
        }
    </style>
</head>
<body>
<div id="app">

    <el-container style="border: 1px solid #eee" class="main-container">
        <!-- container aside -->
        <el-aside width="200px" style="background-color: rgb(238, 241, 246)">
            <el-menu :default-openeds="['1', '3']">
      <el-submenu index="1">
        <template slot="title"><i class="el-icon-message"></i>导航一</template>
        <el-menu-item-group>
          <template slot="title">分组一</template>
          <el-menu-item index="1-1">选项1</el-menu-item>
          <el-menu-item index="1-2">选项2</el-menu-item>
        </el-menu-item-group>
        <el-menu-item-group title="分组2">
          <el-menu-item index="1-3">选项3</el-menu-item>
        </el-menu-item-group>
        <el-submenu index="1-4">
          <template slot="title">选项4</template>
          <el-menu-item index="1-4-1">选项4-1</el-menu-item>
        </el-submenu>
      </el-submenu>
      <el-submenu index="2">
        <template slot="title"><i class="el-icon-menu"></i>导航二</template>
        <el-menu-item-group>
          <template slot="title">分组一</template>
          <el-menu-item index="2-1">选项1</el-menu-item>
          <el-menu-item index="2-2">选项2</el-menu-item>
        </el-menu-item-group>
        <el-menu-item-group title="分组2">
          <el-menu-item index="2-3">选项3</el-menu-item>
        </el-menu-item-group>
        <el-submenu index="2-4">
          <template slot="title">选项4</template>
          <el-menu-item index="2-4-1">选项4-1</el-menu-item>
        </el-submenu>
      </el-submenu>
      <el-submenu index="3">
        <template slot="title"><i class="el-icon-setting"></i>导航三</template>
        <el-menu-item-group>
          <template slot="title">分组一</template>
          <el-menu-item index="3-1">选项1</el-menu-item>
          <el-menu-item index="3-2">选项2</el-menu-item>
        </el-menu-item-group>
        <el-menu-item-group title="分组2">
          <el-menu-item index="3-3">选项3</el-menu-item>
        </el-menu-item-group>
        <el-submenu index="3-4">
          <template slot="title">选项4</template>
          <el-menu-item index="3-4-1">选项4-1</el-menu-item>
        </el-submenu>
      </el-submenu>
    </el-menu>
        </el-aside>
        <!-- container body start -->
        <el-container class="body-container">
             <el-header style="text-align: right; font-size: 12px">
      <el-dropdown>
        <i class="el-icon-setting" style="margin-right: 15px"></i>
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item>查看</el-dropdown-item>
          <el-dropdown-item>新增</el-dropdown-item>
          <el-dropdown-item>删除</el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
      <span>王小虎</span>
    </el-header>
            <el-main>
                <div>
                    <el-backtop target=".el-main"></el-backtop>
                </div>
                <el-tag type="">解决方案</el-tag>
                <el-form :model="formInline" :rules="formRules" ref="formInline" class="demo-form-inline"
                         label-width="100px" size="medium">
                    
                    <el-row>
                        <el-col :span="7">
                            <el-form-item label="状态" prop="status">
                                <el-select v-model="formInline.status" placeholder="状态">
                                    <el-option
                                            v-for="(item,index) in statusOptions"
                                            :key="item.value"
                                            :label="item.label"
                                            :value="item.value"
                                    ></el-option>
                                </el-select>
                            </el-form-item>
                        </el-col>
                        
                    </el-row>
                    


                    <template  >
                        <div >
                            <v-codemirror-editor
                                    :autosize="{ maxHeight: 2000, minHeight: 900}"
                                    :options="codeOptions"
                                    v-model="formInline.attribute.flow"
                                    @code-change="(v)=> { console.log('code-change: ', v); formInline.attribute.flow = v; }"
                            />
                        </div>
                    </template>


                  
                    <!-- start 测试流程动作 table -->
                    <el-table :data="formInline.process_list" ref="formInline.process_list" default-expand-all="true"
                              :border="true"
                              :header-cell-style="{background:'#DCDFE6',color:'#303133'}"
                              :row-style="{background:'#F3F4F7',color:'#303133'}" v-if="activeName == 'info'">
                        <!-- start  测试流程动作断言列表  -->
                        <el-table-column type="expand" fixed>
                            <template slot-scope="props">
                                <!--                                <el-tag type="danger">断言:</el-tag>-->
                                <el-table v-if="props.row.ability != undefined" :data="props.row.ability"
                                          ref="props.row.ability" size="small" stripe="true"
                                          border="true" style="border-color: #f94928;">

                                    <el-table-column prop="name" label="能力名称" min-width="180" fixed>
                                    </el-table-column>
                                    <el-table-column prop="description" label="能力描述" min-width="180">
                                    </el-table-column>
                                    <el-table-column prop="sort_index" label="能力排序" min-width="60">
                                    </el-table-column>
                                    <el-table-column prop="args" label="参数" min-width="200">
                                        <template slot-scope="scope">
                                            <span v-html="JSON.stringify(scope.row.args)"></span>
                                        </template>
                                    </el-table-column>
                                    <el-table-column
                                            fixed="right"
                                            label="操作"
                                            min-width="120">
                                        <template slot-scope="scope">
                                            <el-button @click="delRowClick(scope.$index, scope.row, props.$index)"
                                                       type="text" size="small" style="color: #909399;">删除
                                            </el-button>
                                            <el-button @click="copyRowClick(scope.$index, scope.row, props.$index)"
                                                       type="text" size="small" style="color: #f8bf03;">复制
                                            </el-button>
                                            <el-button @click="editRowClick(scope.$index, scope.row, props.$index)"
                                                       type="text" size="small" style="color: #f94928;">编辑
                                            </el-button>
                                        </template>
                                    </el-table-column>
                                </el-table>
                            </template>
                        </el-table-column>
                        <!-- end  测试流程动作断言列表  -->
                        <el-table-column prop="id" label="组件ID" min-width="60" fixed>
                        </el-table-column>

                        <el-table-column prop="name" label="组件名称" min-width="140" fixed>
                        </el-table-column>

                        <el-table-column prop="description" label="描述" min-width="180">
                        </el-table-column>
                        <el-table-column prop="type" label="组件类型" min-width="200">
                        </el-table-column>

                        <el-table-column prop="cp_code" label="CP编码" min-width="100">
                        </el-table-column>

                        <el-table-column prop="input_class" label="组件入参" min-width="160" show-overflow-tooltip>
                        </el-table-column>

                        <el-table-column prop="status" label="组件状态" min-width="80">
                            <template slot-scope="scope">
                                <span v-html="getStatus(scope.row, scope.row.status)"></span>
                            </template>
                        </el-table-column>

                        <el-table-column prop="target_role" label="触发角色" min-width="80">
                        </el-table-column>
                        <el-table-column prop="component_group" label="分组" min-width="80">
                        </el-table-column>

                        <el-table-column
                                fixed="right"
                                label="操作"
                                min-width="120">
                            <template slot-scope="scope">
                                <el-button @click="editActionClick(scope.$index, scope.row)" type="text" size="small">
                                    编辑
                                </el-button>
                                <el-button @click="addRowClick(scope.$index, scope.row)" type="text" size="small">添加能力
                                </el-button>
                            </template>
                        </el-table-column>
                    </el-table>

                    <div class="blank_col"></div>
                    <el-row>
                        <el-col :span="8">
                            <el-tag type="">
                                <el-button @click="runHandleClick(0, formInline)" type="text" size="small"
                                           style="color: #e84c48">履约拓扑
                                </el-button>
                            </el-tag>
                        </el-col>
                        <el-col :span="8">
                            <template  v-if="activeName == 'info'">
                                <el-form-item>
                                    <el-button type="primary" @click="(v)=> { activeName = 'flow' }">下一步</el-button>
                                </el-form-item>
                            </template>
                            <template v-else>
                                <el-form-item>
                                    <el-button type="primary" @click="(v)=> { activeName = 'info' }">上一步</el-button>
                                    <el-button type="primary" @click="saveDetailFrom">保存方案</el-button>
                                </el-form-item>
                            </template>
                        </el-col>
                    </el-row>
                </el-form>
            </el-main>
            <!--   start  流程动作  dialog     <-->
            <el-dialog title="组件" :visible.sync="actionDialogEdit">
                <el-form :model="actionForm" :rules="actionFormRules" ref="actionForm" label-width="100px"
                         class="demo-ruleForm">
                    <el-row>
                        <el-col :span="12">
                            <el-form-item label="组件ID" prop="id">
                                <el-input v-model="actionForm.id" disabled></el-input>
                            </el-form-item>
                        </el-col>
                        <el-col :span="12">
                            <el-form-item label="组件名称" prop="name">
                                <el-input v-model="actionForm.name"></el-input>
                            </el-form-item>
                        </el-col>
                    </el-row>
                    <el-row>
                        <el-col :span="12">
                            <el-form-item label="组件类型" prop="type">
                                <my-select v-model="actionForm.type" :options-list="componentTypeOptions"
                                           @change="(v) => { if(isEmpty(actionForm.name)) {actionForm.name=v.label} }"
                                >
                                </my-select>
                            </el-form-item>
                        </el-col>
                        <el-col :span="12">
                            <el-form-item label="编码" prop="cp_code">
                                <my-select-remote v-model="actionForm.cp_code"
                                                  :remote-method="remoteScene"
                                                  :options-list="cpCodeOptions"
                                                  @focus="() => { if(getLength(cpCodeOptions)==0){remoteScene()} }">
                                </my-select-remote>
                            </el-form-item>
                        </el-col>
                    </el-row>
                    <el-row>
                        <el-col :span="12">
                            <el-form-item label="组件描述" prop="description">
                                <el-input type="textarea" v-model="actionForm.description"></el-input>
                            </el-form-item>
                        </el-col>
                        <el-col :span="12">
                            <el-form-item label="触发角色" prop="target_role">
                                <my-select v-model="actionForm.target_role" :options-list="targetRoleOptions">
                                </my-select>
                            </el-form-item>
                        </el-col>
                    </el-row>

                    <el-row>
                        <el-col :span="24">
                            <el-form-item label="执行规则" prop="execute_rule">
                                <el-input type="textarea" v-model="actionForm.execute_rule" ></el-input>
                            </el-form-item>
                        </el-col>
                    </el-row>
                    <el-row>
                        <el-col :span="12">
                            <el-form-item label="完成状态" prop="success_status">
                                <el-input v-model="actionForm.success_status" ></el-input>
                            </el-form-item>
                        </el-col>
                        <el-col :span="12">
                            <el-form-item label="组件锁" prop="lock_type">
                                <el-input  v-model="actionForm.lock_type" ></el-input>
                            </el-form-item>
                        </el-col>
                    </el-row>
                    <el-row>
                        <el-col :span="16">
                            <el-form-item label="组件入参" prop="input_class" >
                                <my-select style="width: 100%" v-model="actionForm.input_class" :options-list="componentInputOptions">
                                </my-select>
                            </el-form-item>
                        </el-col>
                        <el-col :span="8">
                            <el-form-item label="事件发送" prop="event_trigger" >
                                <my-select-remote style="width: 100%" v-model="actionForm.event_trigger" :options-list="eventTriggerOptions">
                                </my-select-remote>
                            </el-form-item>
                        </el-col>
                    </el-row>

                    <el-form-item label="组件参数" prop="args">
                        <template slot-scope="scope">
                            <div>
                                <v-json-editor :plus="true" height="100px" v-model="actionForm.args"
                                               :menu="false" :autosize="{ maxHeight: 600, minHeight: 100}">
                                </v-json-editor>
                            </div>
                        </template>
                    </el-form-item>

                    <el-row>
                        <el-col :span="12">
                            <el-form-item label="组件状态" prop="status">
                                <el-select v-model="actionForm.status" placeholder="组件状态">
                                    <el-option
                                            v-for="(item,index) in statusOptions"
                                            :key="item.value"
                                            :label="item.label"
                                            :value="item.value"
                                    ></el-option>
                                </el-select>
                            </el-form-item>
                        </el-col>
                        <el-col :span="12">
                            <el-form-item label="组件分组" prop="component_group">
                                <el-select v-model="actionForm.component_group" placeholder="组件分组">
                                    <el-option
                                            v-for="(item,index) in statusOptions"
                                            :key="item.value"
                                            :label="item.label"
                                            :value="item.value"
                                    ></el-option>
                                </el-select>
                            </el-form-item>
                        </el-col>
                    </el-row>
                    <el-row>
                        <el-col :span="12">
                            <el-form-item label="可达组件" prop="possible_target">
                                <my-select-remote v-model="actionForm.possible_target"
                                                  :options-list="componentTypeOptions"
                                                  :multiple="true"
                                >
                                </my-select-remote>
                            </el-form-item>
                        </el-col>
                        <el-col :span="12">
                            <el-form-item label="到达组件" prop="target">
                                <my-select-remote v-model="actionForm.target" :options-list="componentTypeOptions"
                                                  :multiple="true"
                                >
                                </my-select-remote>
                            </el-form-item>
                        </el-col>
                    </el-row>
                    <el-form-item>
                        <el-button type="primary" @click="submitActionForm('actionForm')">保存</el-button>
                        <el-button @click="actionDialogEdit = false">取消</el-button>
                    </el-form-item>
                </el-form>
            </el-dialog>
            <!--   end  流程动作  dialog     <-->

            <!--   start  断言  dialog     <-->
            <el-dialog title="能力信息" :visible.sync="assertDialogEdit">
                <el-form :model="assertForm" :rules="assertFormRules" ref="assertForm" label-width="100px"
                         class="demo-ruleForm">
                    <el-row>
                        <el-col :span="22">
                            <el-form-item label="能力名称" prop="name">
<!--                                <el-input v-model="assertForm.name"></el-input>-->
                                <my-select-remote v-model="assertForm.name" :options-list="abilityOptions"
                                                  :allow-create="true"
                                                  @xchange="(v) => { if(isEmpty(assertForm.description)){ assertForm.description=v.label } }"
                                >
                                </my-select-remote>
                            </el-form-item>
                        </el-col>
                    </el-row>
                    <el-form-item label="能力描述" prop="description">
                        <el-input v-model="assertForm.description" type="textarea"
                                  :autosize="{ minRows: 3, maxRows: 200}"></el-input>
                    </el-form-item>

                    <el-form-item label="能力排序" prop="sort_index">
                        <el-input-number v-model="assertForm.sort_index" controls-position="right"
                                         @change="(v) => { assertForm.sort_index=parseInt(v) }"
                        ></el-input-number>
                    </el-form-item>

                    <el-form-item label="能力参数" prop="args">
                        <template slot-scope="scope">
                            <div>
                                <v-json-editor :plus="true" height="80px" v-model="assertForm.args"
                                               :menu="false" :autosize="{ maxHeight: 600, minHeight: 80}">
                                </v-json-editor>
                            </div>
                        </template>
                    </el-form-item>

                    <el-form-item>
                        <el-button type="primary" @click="submitAssertForm('assertForm')">保存</el-button>
                        <el-button @click="assertDialogEdit = false">取消</el-button>
                    </el-form-item>
                </el-form>
            </el-dialog>
            <!--   end  断言  dialog     <-->

        </el-container>
        <!-- container body end -->
    </el-container>
</div>
</body>
<!-- 先引入 Vue -->
<script src="/static/vue/vue-2.6.10.min.js"></script>
<!-- 引入组件库 --><!-- import Vue before Element -->
<script src="/static/vue/element-ui-2.13.2-index.js"></script>
<script src="/static/vue/vue-resource-1.5.1.min.js"></script>
<script src="/static/vue/moment-2.24.0.min.js"></script>
<script src="/static/vue/vue-router-3.0.7.min.js"></script>
<!-- import app JavaScript -->
<script src="/static/js/main.js"></script>
<script src="/static/js/jsoneditor.js" type="text/javascript"></script>
<script src="/static/js/v-json-editor.js" type="text/javascript"></script>
<script src="/static/js/my-ui.js" type="text/javascript"></script>
<!-- codemirror -->
<script src="/static/codemirror/codemirror.min.js"></script>
<script src="/static/codemirror/xml.min.js"></script>
<script src="/static/codemirror/show-hint.js"></script>
<script src="/static/codemirror/xml-hint.js"></script>
<!--<script src="/static/codemirror/matchtags.js"></script>-->
<!--<script src="/static/codemirror/xml-fold.js"></script>-->
<script type="text/javascript" src="/static/js/v-codemirror-editor.js"></script>
<!-- import template JavaScript -->
{{template "router" .}}
<script>

    const __data = "{{.data}}";

    console.log(JSON.parse(__data));
    // console.log(__data);
    const __form = JSON.parse(__data);
    if (!__form.args) {
        __form.args = {};
    }
    if (!__form.attribute) {
        __form.attribute = {};
    }
    if (__form.process_list) {
        __form.process_list = __form.process_list.map(function (item, index, arr) {
            if (!item.status) {
                item.status = 0;
            }
            if (item.ability) {
                item.ability = item.ability.map(function (it, index, arr) {
                    it.sort_index = index + 1;
                    if (it.args && it.args.length > 0) {
                        it.args = JSON.parse(it.args);
                    }
                    return it;
                })
            } else {
                item.ability = [];
            }
            if (item.target) {
                item.target = item.target.filter((item) => {
                    if (item && item.length > 0) {
                        return true;
                    }
                    return false;
                });
            }
            if (item.possible_target) {
                item.possible_target = item.possible_target.filter((item) => {
                    if (item && item.length > 0) {
                        return true;
                    }
                    return false;
                });
            }
            return item;
        })
        __form.process_list.sort(function (a, b) {
            return a.id - b.id
        });
    } else {
        __form.process_list = [];
    }

    function completeAfter(cm, pred) {
        var cur = cm.getCursor();
        if (!pred || pred()) setTimeout(function() {
            if (!cm.state.completionActive)
                cm.showHint({completeSingle: false});
        }, 100);
        return CodeMirror.Pass;
    }

    function completeIfAfterLt(cm) {
        return completeAfter(cm, function() {
            var cur = cm.getCursor();
            return cm.getRange(CodeMirror.Pos(cur.line, cur.ch - 1), cur) == "<";
        });
    }

    function completeIfInTag(cm) {
        return completeAfter(cm, function() {
            var tok = cm.getTokenAt(cm.getCursor());
            if (tok.type == "string" && (!/['"]/.test(tok.string.charAt(tok.string.length - 1)) || tok.string.length == 1)) return false;
            var inner = CodeMirror.innerMode(cm.getMode(), tok.state).state;
            return inner.tagName;
        });
    }
    function tagAutocomplete(cm) {
        var cursor = cm.getCursor();
        var curLine = cm.getLine(cursor.line);
        var end = cursor.ch, start = end;
        let result = {
            list: ["SWITCH", "THEN", "to"],
            from: CodeMirror.Pos(cursor.line, start),
            to: CodeMirror.Pos(cursor.line, end)
        };
        return result;
    }
    var nameTags = [ 'ORDER_CANCEL', 'ORDER_SUBMIT', 'ORDER_DETAIL', 'ORDER_PAY_EXPIRED', 'ORDER_REFUND_SUCCESS', 'ORDER_PAY_STR'];
    var chainTags = ["THEN","SWITCH", "WHEN", "to"]

    var codeTags =  {
        "!flow": ["flow"],
        // "!attrs": {
        //     id: null,
        //     class: ["A", "B", "C"]
        // },
        flow : {
            attrs: {},
            children: ["nodes", "chain"]
        },
        nodes: {
            attrs: {
                lang: ["en", "de", "fr", "nl"],
                    freeform: null
            },
            children: ["node"]
        },
        node: {
            attrs: {
                name: nameTags,
                type: ["switch_script", "script"]
            },
            children: []
        },
        chain: {
            attrs: {
                name: nameTags
            },
            children: chainTags,
            search: nameTags,
        },
    };
    const v_vue = new Vue({
        el: '#app',
        router: router,
        data: {
            isCollapse:true,
            statusOptions: [{"label": "有效", "value": 1}, {"label": "无效", "value": 0}],
            assertRuleTypeOptions: [{"label": "GO", "value": 1}, {"label": "JS", "value": 2}],
            failedOptions: [{"label": "继续", "value": 1}, {"label": "停止", "value": 0}],
            bizTypeOptions: [{"label": "RESCUE", "value": 70}, {"label": "Hotel", "value": 1}],
            eventTriggerOptions: [
                {"label": "不发", "value": ""},
                {"label": " 成功发送", "value": "succeed"},
                {"label": " 失败发送", "value": "failed"},
                {"label": " 全部发送", "value": "all"},
            ],
            targetRoleOptions: [{"label": "买家", "value": "BUYER"}, {"label": "卖家", "value": "SELLER"}, {"label": "系统", "value": "SYSTEM"}],
            componentInputOptions: [
               
            ],
            abilityOptions: [],
            cpCodeOptions: [],
            componentTypeOptions: [],
            formInline: __form,
            formRules: {
                "name": [
                    {required: true, message: '名称', trigger: 'blur'},
                    {min: 1, max: 1000, message: '长度在 3 到 1000 个字符', trigger: 'blur'}
                ],
                "biz_type": [
                    {required: true, message: '请选择', trigger: 'change'}
                ],
                "status": [
                    {required: true, message: '请选择', trigger: 'change'}
                ],
            },
            activeName: "info",
            codeOptions: {
                // matchTags: {bothTags: true},
                // alignCDATA: false,
                // indentWithTab: true,
                mode: "application/xml",
                matchBrackets: true,
                styleActiveLine: true,
                extraKeys: {
                    "'<'": completeAfter,
                    "'/'": completeIfAfterLt,
                    "' '": completeIfInTag,
                    "'='": completeIfInTag,
                    "Ctrl-Space": "autocomplete",
                    // 'Tab': tagAutocomplete
                },
                hintOptions: {
                    // completeSingle:false,
                    schemaInfo: codeTags,
                    // tables: {
                    //     "S": ["SWITCH"],
                    //     "T": ["THEN"]
                    // }
                },
                theme: 'monokai',
            },
            actionDialogEdit: false,
            actionForm: {},
            actionFormRules: {
                "name": [
                    {required: true, message: '名称', trigger: 'blur'},
                    {min: 1, max: 1000, message: '长度在 3 到 1000 个字符', trigger: 'blur'}
                ],
                // "args": [
                //     {required: true, message: '参数', trigger: 'blur'},
                //     {min: 1, max: 5000, message: '长度在 1 到 5000 个字符', trigger: 'blur'}
                // ],
                "type": [
                    {required: true, message: '请选择', trigger: 'change'}
                ],
                "status": [
                    {required: true, message: '请选择', trigger: 'change'}
                ],
            },
            assertDialogEdit: false,
            assertForm: {},
            assertFormRules: {
                "name": [
                    {required: true, message: '名称', trigger: 'blur'},
                    {min: 1, max: 1000, message: '长度在 3 到 1000 个字符', trigger: 'blur'}
                ],
                "rule": [
                    {required: true, message: '名称', trigger: 'blur'},
                    {min: 1, max: 1000, message: '长度在 1 到 1000 个字符', trigger: 'blur'}
                ],
                "status": [
                    {required: true, message: '请选择', trigger: 'change'}
                ],
            },
            metaInfoAll: [],
            sceneOptions: [],
            remoteSceneParam: {},
        },
        methods: {
            runHandleClick(index, row) {
                let url = "/admin/biz/graphic/detail?type=status&id=" + row.id
                window.open(url, '_blank');
            },
            assertStatusHandle(index, row, actionIndex) {
                if (!row.status) {
                    row.status = 0;
                }
                const status = row.status;
                if (Number(status, 10) === 1) {
                    row["status"] = 0;
                }
                if (Number(status, 10) === 0) {
                    row["status"] = 1;
                }
                this.formInline.action_list[actionIndex].assert_list[index] = row;
            },
            assertCellHandle(row, column, cell, event) {
                // console.log(column)
                // console.log(row)
                // console.log(cell)
                // console.log(event)
                if ("status" === column.property) {
                    const status = row[column.property] || 0;
                    //console.log("status: ", status);
                    if (Number(status, 10) === 1) {
                        row["status"] = 0;
                        this.$forceUpdate();
                    }
                    if (Number(status, 10) === 0) {
                        row["status"] = 1;
                        this.$forceUpdate();
                    }
                }
            },
            addActionClick() {
                this.actionForm = {
                    pipe_id: this.formInline.id,
                    id: 0,
                    name: '',
                    action_key: '',
                    args: {},
                    sort_index: getLength(this.formInline.action_list) + 1,
                    status: 1,
                    before_waiting: 0,
                    skip_failed: 1,
                    actionIndex: -1,
                };
                this.actionDialogEdit = true;
            },
            editActionClick(index, row) {
                this.actionForm = row;
                this.actionForm.actionIndex = index;
                if (!this.actionForm.args) {
                    this.actionForm.args = {};
                }
                if (!this.actionForm.status) {
                    this.actionForm.status = 0;
                }
                console.log('editActionClick: ' + JSON.stringify(this.actionForm));
                this.actionDialogEdit = true;
            },
            addRowClick(actionIndex, row) {
                this.assertForm = {
                    name: '',
                    description: '',
                    args: {},
                    sort_index: getLength(row.ability) + 1,
                    actionIndex: actionIndex,
                };
                console.log('addRowClick: ' + JSON.stringify(this.assertForm));
                this.assertDialogEdit = true;
            },
            delRowClick(index, row, actionIndex) {
                this.formInline.process_list[actionIndex].ability.splice(index, 1);
                if (0 === row.id) {
                    return;
                }
                console.log('delRowClick: ' + JSON.stringify({ids: [row.id]}));
            },
            copyRowClick(index, row, actionIndex) {
                let action = this.formInline.process_list[actionIndex];
                console.log("action: ", JSON.stringify(action));
                let newRow = JSON.parse(JSON.stringify(row));
                newRow.sort_index = row.sort_index + 1;
                newRow.id = 0;
                this.formInline.process_list[actionIndex].ability.push(newRow);
            },
            editRowClick(index, row, actionIndex) {
                this.assertForm = row;
                this.assertForm.assertIndex = index;
                this.assertForm.actionIndex = actionIndex;
                if (!this.assertForm) {
                    this.assertForm.args = {};
                }
                if (!this.assertForm.status) {
                    this.assertForm.status = 0;
                }
                console.log('editRowClick: ' + JSON.stringify(this.assertForm));
                this.assertDialogEdit = true;
            },
            saveDetailFrom() {
                this.$refs["formInline"].validate((valid) => {
                    if (valid) {
                        let list = JSON.parse(JSON.stringify(this.formInline));
                        list.process_list = list.process_list.map(function (item, index, arr) {
                            if (item.ability) {
                                item.ability = item.ability.map(function (it, index, arr) {
                                    return {
                                        name: it.name,
                                        description: it.description,
                                        args: JSON.stringify(it.args),
                                    };
                                })
                            }
                            return item;
                        })
                        console.log('saveDetailFrom: ' + JSON.stringify(list));
                        this.$http.post('/admin/solution/save', list).then(response => {
                            //console.log("response" + JSON.stringify(response));
                            if (response.body.success) {
                                this.$message({
                                    message: '保存成功,solution=' + response.body.model.id,
                                    type: 'success'
                                });
                                window.location.href = '/admin/solution/' + response.body.model.id
                            } else {
                                this.$message.error('保存失败:' + response.body.code);
                            }
                        }, response => {
                            // error callback
                            this.$message.error('保存失败');
                        });
                        return true;
                    } else {
                        return false;
                    }
                });
            },
            submitActionForm(formName) {
                this.$refs[formName].validate((valid) => {
                    if (valid) {
                        let process_list = this.formInline.process_list;
                        if (isEmpty(process_list)) {
                            this.formInline.process_list = [this.actionForm];
                        } else {
                            let index = this.actionForm.actionIndex;
                            if (undefined === index || -1 === index) {
                                this.formInline.process_list.push(this.actionForm);
                            } else {
                                this.formInline.process_list[index] = this.actionForm;
                            }
                        }
                        console.log("process_list: ", JSON.stringify(this.formInline.process_list));
                        this.actionDialogEdit = false;
                        return true;
                    } else {
                        return false;
                    }
                });
            },
            submitAssertForm(formName) {
                this.$refs[formName].validate((valid) => {
                    if (valid) {
                        this.assertDialogEdit = false;
                        let actionIndex = this.assertForm.actionIndex;
                        let action = this.formInline.process_list[actionIndex];
                        console.log("action: ", JSON.stringify(action));
                        if (isEmpty(action.ability)) {
                            console.log("action.ability:isEmpty ");
                            //this.$forceUpdate();
                            this.formInline.process_list[actionIndex].ability = [this.assertForm];
                            console.log("action: ", JSON.stringify(this.formInline.action_list[actionIndex]));
                        } else {
                            let index = this.assertForm.assertIndex;
                            if (undefined === index || -1 === index) {
                                this.formInline.process_list[actionIndex].ability.push(this.assertForm);
                            } else {
                                this.formInline.process_list[actionIndex].ability[index] = this.assertForm;
                            }
                            this.formInline.process_list[actionIndex].ability.sort(function (a, b) {
                                return a.sort_index - b.sort_index
                            });
                        }
                        this.assertDialogEdit = false;
                        return true;
                    } else {
                        return false;
                    }
                });
            },
            remoteScene(query) {
                let parameter = this.remoteSceneParam;
                parameter.pageNo = 1
                parameter.pageSize = 30;
                if (query !== '') {
                    parameter.name = query;
                } else {
                    parameter.pageSize = 60;
                }
                console.log('remoteScene: ' + JSON.stringify(parameter));
                this.$http.post('/admin/cp/code/all', parameter).then(response => {
                    if (response.body.success) {
                        this.cpCodeOptions = response.body.model.data.filter((item) => {
                            if ("-1" == item.code) {
                                return false;
                            }
                            return true;
                        }).map((item, i, list) => {
                            return {
                                "key": item.enum_name,
                                "value": item.code,
                                "label": item.title
                            };
                        });
                        console.log('cpCodeOptions: ' + JSON.stringify(this.cpCodeOptions));
                    } else {
                        this.$message.error('查询列表失败:' + response.body.code);
                    }
                }, response => {
                    // error callback
                    this.$message.error('查询列表错误');
                });
            },
            getStatus(row, cellValue) {
                if (!cellValue) {
                    return '<span class="el-tag el-tag--danger el-tag--light">无效</span>';
                }
                const status = parseInt(cellValue, 10);
                if (status === 0) {
                    return '<span class="el-tag el-tag--danger el-tag--light">无效</span>';
                }
                return '<span class="el-tag el-tag el-tag--light">有效</span>';
            },
            actionKeyChanged(v) {
                console.log("actionKeyChanged: ", JSON.stringify(v));
                // this.$forceUpdate();
                //this.actionForm.args = v.args;
                this.$set(this.actionForm, "args", v.args);
            },
            loadBizTypeAll() {
                this.$http.post('/admin/biz/type/all').then(response => {
                    if (response.body.success) {
                        let data = response.body.model.data;
                        let count = response.body.model.total;

                        this.bizTypeOptions = response.body.model.data.map((item, index) => {
                            return {
                                "key": item.enum_name,
                                "label": item.name,
                                "value": item.code,
                            };
                        });
                        //console.log("metaInfoAll: ", JSON.stringify(this.metaInfoAll));
                    } else {
                        this.$message.error('查询业务类型失败:' + response.body.message);
                    }
                }, response => {
                    // error callback
                    this.$message.error('查询业务类型错误');
                });
            },
            loadComponentTypeAll() {
                this.$http.post('/admin/component/type/all').then(response => {
                    if (response.body.success) {
                        let data = response.body.model.data;
                        let count = response.body.model.total;

                        this.componentTypeOptions = response.body.model.data.map((item, index) => {
                            return {
                                "key": item.name,
                                "label": item.desc,
                                "value": item.name,
                            };
                        });
                        //console.log("metaInfoAll: ", JSON.stringify(this.metaInfoAll));
                    } else {
                        this.$message.error('查询业务类型失败:' + response.body.message);
                    }
                }, response => {
                    // error callback
                    this.$message.error('查询业务类型错误');
                });
            },
            postAbility(pageNo,pageSize) {
                let param = {pageNo:pageNo,pageSize:pageSize};
                console.log("postAbility: ", JSON.stringify(param));
                this.$http.post('/admin/ability/list', param).then(response => {
                    if (response.body.success) {
                        let temp = this.abilityOptions;
                        let total = response.body.model.total;
                        response.body.model.data.map((item, index) => {
                            return {
                                "key": item.clazz,
                                "label": item.description,
                                "value": item.ability_type,
                            };
                        }).forEach(item => {
                            temp.push(item);
                        });
                        this.abilityOptions = temp;
                        //console.log("metaInfoAll: ", JSON.stringify(this.metaInfoAll));
                        if (total > pageNo * pageSize) {
                            this.postAbility(pageNo + 1, pageSize);
                        }
                    } else {
                        this.$message.error('查询业务类型失败:' + response.body.message);
                    }
                }, response => {
                    // error callback
                    this.$message.error('查询业务类型错误');
                });
            },
            loadAbilityAll() {
                this.postAbility(1, 30);
            }
        },
        created: function () {
            console.log('created is: ' + this.isCollapse);
            this.loadBizTypeAll();
            this.loadComponentTypeAll();
        },
        mounted: function () {
            console.log('mounted is: ' + this.isCollapse);
            this.loadAbilityAll();
        }
    })
</script>
</html>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容