关于sortable用法与vuedraggable比较

都挺好,但是element table里用sortabe比较好,原因 https://segmentfault.com/a/1190000019411685?utm_source=tag-newest

然后今天用sortable的时候,一直没效果,不知道咋回事

看了几个地方  一个是要加row-key

而且row-key一定要对应好,别乱写,要写表格数据数组里每个对象的唯一字段,比如id

一个是要用$ref来取表格

<template>
    <div class="steptemp">
            <div class="temp-table-bottom">
                <el-table  ref="dragTable"  :data="tableData" class="data_table" style="width: 100%" border row-key="id">
                    <el-table-column  v-for="(item, index) in col"
                :key="`col_${index}`"
                :prop="item.prop"
                :label="item.label">
                    </el-table-column>
                </el-table>
                <div class="temp-count">
                    <p>共{{stempConfig.total}}条记录</p>
                </div>
            </div>
        </div>

        <!--<drag-table :theadConfig="col" :data="tableData" />-->

    </div>



</template>
<script lang="ts">
    import { Component, Vue, Prop, Watch } from 'vue-property-decorator';
    import { ApiWebComponentService } from 'mone-test/services';
     import DragTable from "mone-test/components/dragTable/index.vue";
    import Sortable from 'sortablejs'
    @Component({
        name: 'StepTemp',
        components: {
DragTable
        }
    })

    export default class StepTemp extends Vue {
        /*** props ***/
        // 通过一个统一props来确定,所以得操作是组件还是脚本
        @Prop({ type: Object, default: () => { return {}; } }) stepTempInfo;
        @Prop({ type: String, default: () => { return ''; } }) currentDirectoryName;

        tableData: Array =[
    {
          id: '1',
          date: '2016-05-01',
          name: '王小虎1',
          propVal: 'aaaaaaaaaa',
          required: true,
          address: '上海市普陀区金沙江路 101 弄'
        },
        {
          id: '2',
          date: '2016-05-02',
          name: '王小虎2',
          propVal: 'fdggd',
          required: false,
          address: '上海市普陀区金沙江路 102 弄'
        },
        {
          id: '3',
          date: '2016-05-03',
          name: '王小虎3',
          propVal: 'cccccccccccc',
          required: true,
          address: '上海市普陀区金沙江路 103 弄'
        },
        {
          id: '4',
          date: '2016-05-04',
          name: '王小虎4',
          propVal: 'tttttttttttttt',
          required: true,
          address: '上海市普陀区金沙江路 104 弄'
        }
];

        stempConfig: Object = {
            createTime: "yyyy-MM-dd HH:mm:ss",
            creator: "string",
            deleted: true,
            directoryPath: "string",
            directoryName: "",
            id: 0,
            key: "string",
            moduleDesc: "string",
            moduleName: "string",
            moduleTags: "string",
            rewriter: "string",
            tags: [
                "string"
            ],
            updateTime: "yyyy-MM-dd HH:mm:ss",
            versionId: 0,
            webModules: [
                null
            ]
        }
        total = 0
        formLabelWidth: String = '120px';
        stepFormVisible: Boolean = false;
        stepForm: Object = {
            name: '',
            eventParam: '',
            latencyTime: 0,// /1
        };
        col = [
    {
      label: '日期',
      prop: 'date',
      type: 'select',
      options: [
          {value: '1', label: '呵呵'},
          {value: '2', label: '是非得失'},
          {value: '3', label: '等各方面'},
      ],
    },
    {
      label: '姓名',
      prop: 'name',
      type: 'slot'
    },
    {
      label: '属性值',
      prop: 'propVal',
      type: 'input',
    },
    {
      label: '必填',
      prop: 'required',
      type: 'checkbox',
    },
    {
      label: '地址',
      prop: 'address'
    },
    {
      label: '操作',
      prop: 'operate',
      type: 'slot'
    },
];
        dropCol = [
            {
                label: '日期',
                prop: 'date'
            },
            {
                label: '姓名',
                prop: 'name'
            },
            {
                label: '地址',
                prop: 'address'
            }
        ]



        constructor() {
            // this.initData()
        }
        initData() {

        }
        mounted() {
            this.rowDrop();
        }



        // 行拖拽
         rowDrop () {
        const _this = this
        const table = _this.$refs.dragTable;
        const tbody = table.$el.querySelector('.el-table__body-wrapper tbody');
        Sortable.create(tbody, {
            onEnd ({ newIndex, oldIndex }) {
                const currRow = _this.tableData.splice(oldIndex, 1)[0]
                _this.tableData.splice(newIndex, 0, currRow)
            }
        })
    }
    }

</script>
<style scoped lang="scss">
   
</style>

 

const table = _this.$refs.dragTable; 这句代码最为关键,加上就有效果了

发现封装真的舒服,重复代码不用写了很多,多封装

<template>
    <div class="steptemp">

            <div class="temp-table-bottom">
                <el-table ref="dragTable" :data="tableData" class="data_table" style="width: 100%" border row-key="id">
                    <el-table-column v-for="(item, index) in col" :key="`col_${index}`"  header-align="center" align="center" :prop="item.prop" :label="item.label">
                        <template slot-scope="scope">
                            <div v-if="item.type=='sort'" style="text-align: center;">
                                <el-button size="mini" type="parmary" @click="handleStepEdit">
                                    拖拽
                                </el-button>
                            </div>
                            <div v-if="item.type=='execute'" style="text-align: center;">
                                <el-checkbox v-model="scope.row.executed"></el-checkbox>
                            </div>
                            <div v-if="item.type=='operation'" style="text-align: center;">
                                <el-button size="mini" type="parmary" @click="handleStepEdit">
                                    编辑
                                </el-button>
                                <el-button size="mini" type="parmary">
                                    删除
                                </el-button>
                            </div>
                            <span v-else>{{ scope.row[item.prop] }}</span>
                        </template>
                    </el-table-column>
                </el-table>
                <div class="temp-count">
                    <p>共{{stempConfig.total}}条记录</p>
                </div>
            </div>
        </div>


    </div>



</template>
<script lang="ts">
    import { Component, Vue, Prop, Watch } from 'vue-property-decorator';
    import { ApiWebComponentService } from 'mone-test/services';
    import Sortable from 'sortablejs'
    @Component({
        name: 'StepTemp',
        components: {
        }
    })

    export default class StepTemp extends Vue {
        /*** props ***/
        // 通过一个统一props来确定,所以得操作是组件还是脚本
        @Prop({ type: Object, default: () => { return {}; } }) stepTempInfo;
        @Prop({ type: String, default: () => { return ''; } }) currentDirectoryName;

        tableData: Array = [
            {
                id: '1',
                date: '2016-05-01',
                name: '王小虎1',
                propVal: 'aaaaaaaaaa',
                required: true,
                address: '上海市普陀区金沙江路 101 弄'
            },
            {
                id: '2',
                date: '2016-05-02',
                name: '王小虎2',
                propVal: 'fdggd',
                required: false,
                address: '上海市普陀区金沙江路 102 弄'
            },
            {
                id: '3',
                date: '2016-05-03',
                name: '王小虎3',
                propVal: 'cccccccccccc',
                required: true,
                address: '上海市普陀区金沙江路 103 弄'
            },
            {
                id: '4',
                date: '2016-05-04',
                name: '王小虎4',
                propVal: 'tttttttttttttt',
                required: true,
                address: '上海市普陀区金沙江路 104 弄'
            }
        ];

        stempConfig: Object = {
            createTime: "yyyy-MM-dd HH:mm:ss",
            creator: "string",
            deleted: true,
            directoryPath: "string",
            directoryName: "",
            id: 0,
            key: "string",
            moduleDesc: "string",
            moduleName: "string",
            moduleTags: "string",
            rewriter: "string",
            tags: [
                "string"
            ],
            updateTime: "yyyy-MM-dd HH:mm:ss",
            versionId: 0,
            webModules: [
                null
            ]
        }
        total = 0
        formLabelWidth: String = '120px';
        stepFormVisible: Boolean = false;
        stepForm: Object = {
            name: '',
            eventParam: '',
            latencyTime: 0,// /1
        };
        col = [
            {
                label: '顺序',
                type: 'sort'

            },
            {
                label: '序号',
                prop: 'sort',
            },
            {
                label: '执行',
                type: 'execute'

            },
            {
                label: '步骤分类',
                prop: 'type',
                type: 'prop'
            },
            {
                label: '步骤名称',
                prop: 'name',
                type: 'prop'
            },
            {
                label: '等待时间(s)',
                prop: 'latencyTime',
                type: 'prop'
            },
            {
                label: '操作',
                type: 'operation'
            },
        ];



        constructor() {
            // this.initData()
        }
        initData() {

        }
        mounted() {
            this.rowDrop();
        }

        // 行拖拽
        rowDrop() {
            const _this = this
            const table = _this.$refs.dragTable;
            const tbody = table.$el.querySelector('.el-table__body-wrapper tbody');
            Sortable.create(tbody, {
                onEnd({ newIndex, oldIndex }) {
                    const currRow = _this.tableData.splice(oldIndex, 1)[0]
                    _this.tableData.splice(newIndex, 0, currRow)
                }
            })
        }
    }

</script>
<style scoped lang="scss">
</style>

第二个点,如何只让表格中的某一个列具有拖拽功能,其他列没有

可以看看这两篇文章https://www.jianshu.com/p/dcdf1c0b8aab http://www.itxst.com/sortablejs/mbe73qrv.html

<template>
    <div class="steptemp">
        <!--脚本与组件 步骤调节组件 通过标示区分是调节脚本还是组件-->
        <!--头部toolbars-->
        <div class="toolbars">
            <ul>
                <!--这里的下面三个调用弹框 传编辑,复制,删除所需要的数据就行了,这个数据,这里单独发请求到了-->
                <li @click="handleEvent(tableEdit)">
                    <i class="el-icon-edit"></i>
                    <span>编辑</span>
                </li>
                <li @click="handleEvent(tableCopy)">
                    <i class="el-icon-document-copy"></i>
                    <span>复制</span>
                </li>
                <li @click="handleEvent(tableDel)">
                    <i class="el-icon-delete"></i>
                    <span>删除</span>
                </li>
                <li>
                    <i class="el-icon-upload2"></i>
                    <span>导入</span>
                </li>
            </ul>
            <ol>
                <li>
                    <el-button size="mini" style="margin-bottom:5px;" type="primary" @click="handleSaveStep">保存</el-button>
                </li>
                <li @click="toStepTemp">
                    <i class="el-icon-back"></i>
                </li>
            </ol>
        </div>
        <!--信息数据-->
        <div class="info">
            <h2>{{stempConfig.moduleName}}</h2>
            <div class="info-detail">
                <p>创建人:{{stempConfig.creator}}</p>
                <p>所属分组:{{currentDirectoryName}}</p>
                <p>更新时间:{{stempConfig.updateTime}}</p>
            </div>
        </div>
        <!--表格部分-->
        <div class="temp-table">
            <div class="temp-table-top">
                <div class="el-dropdown-link">
                    <el-button type="primary" icon="el-icon-plus" class="btn_new_group" @click="handleStepAdd">添加执行步骤</el-button>
                </div>
            </div>
            <div class="temp-table-bottom">
                <el-table ref="dragTable" :data="tableData" class="data_table" style="width: 100%" border row-key="stepId">
                    <el-table-column v-for="(item, index) in col" :key="`col_${index}`" header-align="center" align="center" :width="item.formLabelWidth?item.formLabelWidth:'auto'"
                        :prop="item.prop" :label="item.label">
                        <template slot-scope="scope">
                            <div class="allowDrag" v-if="item.type=='sort'" style="text-align: center;">
                                <i class="el-icon-sort" style="cursor:pointer;"></i>
                            </div>

                            <div v-else-if="item.type=='operation'" style="text-align: center;display: flex;justify-content: space-between">
                                <!--增加和删除按钮-->
                                <i size="small" class="el-icon-circle-plus-outline fs20" @click="handleStepAdd"></i>
                                <i class="el-icon-remove-outline fs20" @click="handleStepDelete(scope.$index)"></i>
                            </div>
                            <div v-else-if="item.type=='selectEvent'">
                                <el-select style="width:100%" v-model="scope.row.event">
                                    <el-option v-for="item1 in eventList" :key="`${item1.value}event`" :label="item1.value" :value="item1.value">
                                        <span style="float: left">{{ item1.value }}</span>
                                        <span style="float: right; color: #8492a6; font-size: 13px">{{ item1.label }}</span>
                                    </el-option>
                                </el-select>
                            </div>
                            <div v-else-if="item.type=='selectAlert'">
                                <el-select style="width:100%" v-model="scope.row.alertRule">
                                    <el-option v-for="item2 in alertRuleList" :key="`${item2.value}alertRule`" :label="item2.value" :value="item2.value">
                                        <span style="float: left">{{ item2.value }}</span>
                                        <span style="float: right; color: #8492a6; font-size: 13px">{{ item2.label }}</span>
                                    </el-option>
                                </el-select>
                            </div>
                            <div class="event_param" v-else-if="item.type=='triplingParam'">
                                <ul v-show="scope.row.isEventParamShow">
                                    <li @mousedown="handleParam('comParam',scope.$index,'triplingParam')">引入公共参数</li>
                                    <li>引入步骤参数</li>
                                    <li @mousedown="handleParam('paramconstr',scope.$index,'triplingParam')">参数构造器</li>
                                </ul>
                                <el-input @input="handleParamInput(scope.$index)" @blur="handleParamBlur(scope.$index)" @focus="handleParamFocus(scope.$index)"
                                    v-model="scope.row.eventParam"></el-input>
                            </div>

                            <div class="event_param" v-else-if="item.type=='singleParam'">
                                <ul v-show="scope.row.isPositionParamShow">
                                    <li @mousedown="handleParam('comParam',scope.$index,'singleParam')">引入公共参数</li>
                                    <!--<li>引入步骤参数</li>-->
                                </ul>
                                <el-input @input="handleParamInput1(scope.$index)" @blur="handleParamBlur1(scope.$index)" @focus="handleParamFocus1(scope.$index)"
                                    v-model="scope.row.locationProperty"></el-input>

                            </div>
                            <span v-else-if="item.type=='inputNum'">
                                <!--<el-input-number style="width: 100px;" placeholder="请输入等待时间" v-model="scope.row.latencyTime" controls-position="right" :min="0" :max="60"></el-input-number>-->
                                 <el-input v-model="scope.row[item.prop]" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
                            </span>
                            <span v-else>
                                <el-input ondragstart="return false" v-model="scope.row[item.prop]"></el-input>
                            </span>
                        </template>
                        </el-table-column>
                </el-table>
            </div>
        </div>



        <!--公共参数弹框-->
        <CommonParam v-if="isComParamShow.flag" :isComParamShow="isComParamShow" @commonParamClick="commonParamClick" :treeConfig="{filter: true}"
            :treeReqParams="treeReqParams"></CommonParam>
            <!--参数构造器弹框-->
            <ParamConstructor v-if="isParamConstrShow.flag" @paramConstructorClick="paramConstructorClick" :isParamConstrShow="isParamConstrShow"></ParamConstructor>

    </div>



</template>
<script lang="ts">
                                                       import { Component, Vue, Prop, Watch } from 'vue-property-decorator';
                                                       import { ApiWebComponentService } from 'mone-test/services';
                                                       import Sortable from 'sortablejs'
                                                       import CommonParam from 'mone-test/components/commonQuote/commonParam/index.vue'
                                                       import ParamConstructor from 'mone-test/components/commonQuote/paramConstructor/index.vue'
                                                       @Component({
                                                           name: 'StepTempWeb',
                                                           components: {
                                                               CommonParam, ParamConstructor
                                                           }
                                                       })

                                                       export default class StepTemp extends Vue {
                                                           /*** props ***/
                                                           // 通过一个统一props来确定,所以得操作是组件还是脚本
                                                           @Prop({ type: Object, default: () => { return {}; } }) stepTempInfo;
                                                           @Prop({ type: String, default: () => { return ''; } }) currentDirectoryName;
                                                           @Prop({ type: Object, default: () => { return {}; } }) treeConfig;
                                                           @Prop({ type: Object, default: () => { return {}; } }) treeReqParams;
                                                           // get tableDataBySort() {
                                                           //     const self = this as any
                                                           //     self.tableData.sort((a, b) => {
                                                           //         return a.sort - b.sort
                                                           //     })
                                                           //     return self.tableData
                                                           // }


                                                           // id需要我传时间戳,如果是新增,那么就传个时间戳
                                                           // 如果是编辑再保存,就不用再传时间戳,就传它请求到底传来的那个id
                                                           // 也就是通过他本来有没有id来判断是新增还是编辑
                                                           tableData: object[] = [
                                                           ];
                                                           stempConfig: object = {
                                                               createTime: "yyyy-MM-dd HH:mm:ss",
                                                               creator: "string",
                                                               deleted: true,
                                                               directoryPath: "string",
                                                               directoryName: "",
                                                               id: 0,
                                                               key: "string",
                                                               moduleDesc: "string",
                                                               moduleName: "string",
                                                               moduleTags: "string",
                                                               rewriter: "string",
                                                               tags: [
                                                                   "string"
                                                               ],
                                                               updateTime: "yyyy-MM-dd HH:mm:ss",
                                                               versionId: 0,
                                                               webModules: [
                                                                   null
                                                               ]
                                                           }
                                                           total: number = 0
                                                           stepStartFormVisible: boolean = false;
                                                           formLabelWidth: string = '120px'
                                                           col: object[] = [
                                                               // {
                                                               //     label: 'id',
                                                               //     prop: 'id',
                                                               //     type: 'prop',
                                                               //     formLabelWidth: '100px'
                                                               // },
                                                               {
                                                                   label: '顺序',
                                                                   type: 'sort',
                                                                   formLabelWidth: '50px'
                                                               },
                                                               {
                                                                   label: '步骤名称',
                                                                   prop: 'name',
                                                                   formLabelWidth: '130px'
                                                               },
                                                               {
                                                                   label: '事件',
                                                                   prop: 'event',
                                                                   type: 'selectEvent',
                                                                   formLabelWidth: '130px',
                                                                   // selectOption:this.eventList
                                                               },
                                                               {
                                                                   label: '定位属性',
                                                                   prop: 'locationProperty',
                                                                   type: 'singleParam',
                                                                   formLabelWidth: '150px'
                                                               },
                                                               {
                                                                   label: '参数',
                                                                   prop: 'eventParam',
                                                                   type: 'triplingParam',
                                                                   formLabelWidth: '300px'
                                                               },
                                                               {
                                                                   label: '等待时间(s)',
                                                                   prop: 'latencyTime',
                                                                   type: 'inputNum',
                                                                   formLabelWidth: '112px'
                                                               },
                                                               {
                                                                   label: '断言规则',
                                                                   prop: 'alertRule',
                                                                   type: 'selectAlert',
                                                                   formLabelWidth: '130px',
                                                                   // selectOption:this.alertRuleList
                                                               },
                                                               {
                                                                   label: '预期结果',
                                                                   prop: 'expect',
                                                                   formLabelWidth: '130px'
                                                               },
                                                               {
                                                                   label: '设置变量',
                                                                   prop: 'var',
                                                                   formLabelWidth: '130px'
                                                               },
                                                               {
                                                                   label: '操作',
                                                                   type: 'operation',
                                                                   formLabelWidth: '60px'
                                                               },
                                                           ];
                                                           operation: Number = 1
                                                           eventList: object[] = [
                                                               { positionInsist: true, paramInsist: false, label: "获取html标签文本值", value: "getText" },
                                                               { positionInsist: true, paramInsist: false, label: "获取html标签属性", value: "getAttribute" },
                                                               { positionInsist: true, paramInsist: false, label: "获取html标签内部html文本", value: "getInnerHTML" },
                                                               { positionInsist: true, paramInsist: false, label: "获取html标签内部文本", value: "getInnerText" },
                                                               { positionInsist: true, paramInsist: false, label: "清空输入框", value: "clear" },
                                                               { positionInsist: true, paramInsist: true, label: "向输入框输入内容", value: "fill" },
                                                               { positionInsist: true, paramInsist: false, label: "鼠标单击", value: "click" },
                                                               { positionInsist: true, paramInsist: false, label: "鼠标双击", value: "dblclick" },
                                                               { positionInsist: true, paramInsist: false, label: "鼠标悬停", value: "hover" },
                                                               { positionInsist: true, paramInsist: false, label: "标签元素聚焦", value: "focus" },
                                                               { positionInsist: true, paramInsist: false, label: "判断元素是否可用(反义isDisabled)", value: "isEnabled" },
                                                               { positionInsist: true, paramInsist: false, label: "判断元素是否禁用", value: "isDisabled" },
                                                               { positionInsist: true, paramInsist: false, label: "判断元素是否可编辑", value: "isEditable" },
                                                               { positionInsist: true, paramInsist: false, label: "判断元素是否可视化(反义isHidden)", value: "isVisible" },
                                                               { positionInsist: true, paramInsist: false, label: "判断元素是否隐藏", value: "isHidden" },
                                                               { positionInsist: true, paramInsist: false, label: "单选框或复选框选中", value: "check" },
                                                               { positionInsist: true, paramInsist: false, label: "单选框或复选框取消选中", value: "uncheck" },
                                                               { positionInsist: true, paramInsist: false, label: "判断单选框或复选框选中状态", value: "isChecked" },
                                                               { positionInsist: true, paramInsist: true, label: "模拟键盘输入", value: "type" },
                                                               { positionInsist: true, paramInsist: true, label: "模拟键盘按下,通常是快捷键", value: "press" },
                                                               { positionInsist: true, paramInsist: true, label: "上传文件,输入是完整文件路径或相对路径", value: "upload" },
                                                               { positionInsist: false, paramInsist: true, label: "下载文件,输入下载的指定目录", value: "download" },
                                                               { positionInsist: false, paramInsist: true, label: "使用JavaScript", value: "excuteJS" },
                                                               { positionInsist: false, paramInsist: true, label: "打开一个浏览器页签", value: "open" },
                                                               { positionInsist: false, paramInsist: false, label: "关闭一个浏览器页签", value: "close" },
                                                               { positionInsist: false, paramInsist: false, label: "页面重新加载", value: "reload" },
                                                               { positionInsist: false, paramInsist: true, label: "获取当前页签标题", value: "getTitle" },
                                                               { positionInsist: false, paramInsist: false, label: "对话框点击确定", value: "confirm" },
                                                               { positionInsist: false, paramInsist: false, label: "对话框点击取消", value: "dismiss" },
                                                               { positionInsist: false, paramInsist: true, label: "对话框输入文本", value: "accept" },
                                                               { positionInsist: false, paramInsist: false, label: "页面前进", value: "goForward" },
                                                               { positionInsist: false, paramInsist: false, label: "页面回退", value: "goBack" },
                                                               { positionInsist: true, paramInsist: true, label: "页面滚动(模拟滚动条滚动)", value: "tap" },
                                                               { positionInsist: false, paramInsist: true, label: "截图,输入是完整文件路径或相对路径", value: "screenshot" },
                                                               { positionInsist: false, paramInsist: true, label: "录制回放,输入是完整文件路径或相对路径", value: "record" }
                                                           ]
                                                           alertRuleList: object[] = [
                                                               { label: '包含', value: 'contain' },
                                                               { label: '等于[=]', value: 'equal' },
                                                               { label: '不等于[!=]', value: 'notEqual' }
                                                           ]
                                                           paramToolShow: boolean = false
                                                           expectToolShow: boolean = false
                                                           isComParamShow: object = { flag: false }
                                                           isParamConstrShow: object = { flag: false }
                                                           currentParamType: string = "param" //默认事件参数输入框吧
                                                           isPositionInsist: boolean = true;//步骤是否支持事件
                                                           isParamInsist: boolean = true;//步骤是否支持参数

                                                           currentTableIndex: number = 0;
                                                           currentTableInputType: string = '';


                                                           constructor() {
                                                               super()
                                                           }

                                                           mounted() {
                                                               this.rowDrop();
                                                           }

                                                           created() {
                                                               if (this.stepTempInfo && this.stepTempInfo.row && this.stepTempInfo.row.id) {
                                                                   this.getWebModuleSingle()
                                                               }
                                                           }
                                                           // handleParam(inputType, diaType) {
                                                           //     // 第一个type是区分是把值给哪个输入框,事件参数,还是断言预期参数
                                                           //     // 第二type,是去分是弹哪个弹框
                                                           //     // 不管是那种,都要执行这步,这样谈框点确定触发回调改值,才知道要改的是哪个输入框的值
                                                           //     this.currentParamType = inputType
                                                           //     if (diaType == 'comParam') {
                                                           //         this.isComParamShow['flag'] = true
                                                           //     } else if (diaType == 'paramconstr') {
                                                           //         this.isParamConstrShow['flag'] = true
                                                           //     }
                                                           // }
                                                           paramConstructorClick(param) {
                                                               const self = this as any
                                                               console.log(param, this.currentTableIndex, this.currentTableInputType)
                                                               //  this.currentTableIndex
                                                               // this.$set(this.stepPositiontForm, 'eventParam', param)
                                                               if (this.currentTableInputType == 'singleParam') {
                                                                   self.$set(self.tableData[self.currentTableIndex], 'locationProperty', param)
                                                               } else if (this.currentTableInputType == 'triplingParam') {
                                                                   self.$set(self.tableData[self.currentTableIndex], 'eventParam', param)
                                                               }
                                                               // self.tableData = self.tableData.concat()
                                                           }
                                                           commonParamClick(param) {
                                                               const self = this as any
                                                               console.log(param, this.currentTableIndex, this.currentTableInputType)
                                                               // 根据当前index,填充进table里
                                                               if (this.currentTableInputType == 'singleParam') {
                                                                   self.$set(self.tableData[self.currentTableIndex], 'locationProperty', param)
                                                               } else if (this.currentTableInputType == 'triplingParam') {
                                                                   self.$set(self.tableData[self.currentTableIndex], 'eventParam', param)
                                                               }
                                                               // self.tableData = self.tableData.concat()
                                                               // this.$set(this.stepPositiontForm, 'eventParam', param)
                                                           }
                                                           handleParamBlur(index) {
                                                               const self = this as any
                                                               // setTimeout(function () {
                                                               self.$set(self.tableData[index], 'isEventParamShow', false)
                                                               self.tableData = self.tableData.concat()
                                                               // });
                                                           }
                                                           handleParamInput(index) {
                                                               const self = this as any
                                                               this.$set(self.tableData[index], 'isEventParamShow', false)
                                                           }
                                                           handleParamFocus(index) {
                                                               const self = this as any
                                                               self.$set(self.tableData[index], 'isEventParamShow', true)
                                                               self.tableData = self.tableData.concat()
                                                           }
                                                           handleParamBlur1(index) {
                                                               const self = this as any
                                                               // setTimeout(function () {
                                                               self.$set(self.tableData[index], 'isPositionParamShow', false)
                                                               self.tableData = self.tableData.concat()
                                                               // });
                                                           }
                                                           handleParamInput1(index) {
                                                               const self = this as any
                                                               this.$set(self.tableData[index], 'isPositionParamShow', false)
                                                           }
                                                           handleParamFocus1(index) {
                                                               const self = this as any
                                                               self.$set(self.tableData[index], 'isPositionParamShow', true)
                                                               self.tableData = self.tableData.concat()
                                                           }
                                                           getWebModuleSingle() {
                                                               const self = this as any
                                                               ApiWebComponentService.getWebModuleSingle({ id: self.stepTempInfo.row.id }).then(res => {
                                                                   if (res.code == 200) {
                                                                       if (res.data.id) {
                                                                           // 这里做一个判断,如果有至少一条数据,那么tabledata中就不放
                                                                           // 默认的一条空数据,否则默认放一条空数据
                                                                           // 还有一个操作,就是查询的时候要给,每个数据两个属性,用于控制,参数选项是显示还是隐藏,
                                                                           // 对应的,保存的时候,也要删除这两个属性
                                                                           self.total = res.data.total
                                                                           self.stempConfig = Object.assign({}, res.data)
                                                                           if (res.data.steps && res.data.steps.length != 0) {
                                                                               // self.tableData = res.data.steps.concat()
                                                                               self.tableData = res.data.steps.map(el => {
                                                                                   el.isPositionParamShow = false
                                                                                   el.isEventParamShow = false
                                                                                   return el
                                                                               }).concat()
                                                                           } else {
                                                                               self.tableData = [{
                                                                                   name: '',
                                                                                   event: '',
                                                                                   locationProperty: '',
                                                                                   eventParam: '',
                                                                                   latencyTime: '',
                                                                                   alertRule: '',
                                                                                   expect: '',
                                                                                   var: '',
                                                                                   isPositionParamShow: false,
                                                                                   isEventParamShow: false
                                                                               }]
                                                                           }


                                                                           self.tableData = res.data.steps.concat()
                                                                       }
                                                                   }
                                                               })
                                                                   .catch(err => {
                                                                       // self.toStepTemp()
                                                                       // self.$emit('toStepTemp', true, self.stepTempInfo.row.directoryPath)
                                                                   })
                                                           }


                                                           toStepTemp() {
                                                               const self = this as any
                                                               this.$emit('toStepTemp', true, self.stepTempInfo.row.directoryPath)
                                                           }


                                                           handleEvent(funcName) {
                                                               let obj = { row: {} }
                                                               obj.row = Object.assign({}, this.stempConfig)
                                                               this.$parent[funcName](obj)
                                                           }
                                                           // 行拖拽
                                                           rowDrop() {
                                                               const _this = this as any
                                                               const table = _this.$refs.dragTable;
                                                               const tbody = table.$el.querySelector('.el-table__body-wrapper tbody');
                                                               Sortable.create(tbody, {
                                                                   handle: ".allowDrag",
                                                                   onEnd({ newIndex, oldIndex }) {
                                                                       const currRow = _this.tableData.splice(oldIndex, 1)[0]
                                                                       _this.tableData.splice(newIndex, 0, currRow)
                                                                       // 拖拽结束调用排序接口
                                                                       // id对应相应的顺序
                                                                       // const query = { orderMap: {} }
                                                                       // _this.tableData.map((el, index) => {
                                                                       //     query.orderMap[el.id] = index
                                                                       //     return el
                                                                       // })
                                                                       // ApiWebComponentService.setpSort(query).then(res => {
                                                                       //     if (res.code == 200) {
                                                                       //         _this.getWebModuleSingle()
                                                                       //     }

                                                                       // })
                                                                   }
                                                               })
                                                           }
                                                           handleParam(diaType, index, inputType) {
                                                               // 点击的时候,记录当前的index,用以确定参数放在哪一行
                                                               this.currentTableIndex = index
                                                               // 还要记录当前input类型,是三个的还是一个的
                                                               this.currentTableInputType = inputType
                                                               console.log('diaType', diaType)
                                                               if (diaType == 'paramconstr') {
                                                                   this.isParamConstrShow['flag'] = true
                                                               } else if (diaType == 'comParam') {
                                                                   this.isComParamShow['flag'] = true
                                                               }
                                                           }
                                                           handleStepAdd() {
                                                               const self = this as any
                                                               self.tableData.push({
                                                                   name: '',
                                                                   event: '',
                                                                   locationProperty: '',
                                                                   eventParam: '',
                                                                   latencyTime: '',
                                                                   alertRule: '',
                                                                   expect: '',
                                                                   var: '',
                                                                   isPositionParamShow: false,
                                                                   isEventParamShow: false
                                                               })

                                                           }
                                                           handleStepDelete(index) {
                                                               const self = this as any
                                                               self.tableData.splice(index, 1)
                                                           }
                                                           // 点击保存,保存步骤
                                                           handleSaveStep() {
                                                               // 有个校验,如果只有一条全空的数据
                                                               // 那么也请求接口,但是啥也不传
                                                               // 点击保存的时候,全为空的数据不传
                                                               // 传过去的时候,记得吧query里的那两个属性删除
                                                               const self = this as any
                                                               let query = self.tableData.map(el => {
                                                                   delete el.isPositionParamShow
                                                                   delete el.isEventParamShow
                                                                   return el
                                                               })
                                                                   .filter(el => {
                                                                       let flag = false
                                                                       for (const key in el) {
                                                                           // 存在一个不为空的,就可以发送这条数据
                                                                           if (el[key] != '') {
                                                                               flag = true
                                                                               break;
                                                                           }
                                                                       }
                                                                       return flag
                                                                   })
                                                               // .map(el => {
                                                               //     // 第二个判断是,没有id,加id字段为时间戳,有id的就不用管,
                                                               //     el.stepId = el.stepId ? el.stepId : new Date().getTime()
                                                               //     return el
                                                               // })
                                                               console.log('query', query);

                                                               // ApiWebComponentService.saveSteps(query).then(res => {
                                                               //     console.log('res', res)
                                                               // })
                                                           }
                                                       }

</script>
<style scoped lang="scss">
    .steptemp {
        flex: 1;
        overflow: auto;
        .toolbars {
            border-bottom: 1px solid #ccc;
            display: flex;
            justify-content: space-between;
            align-items: center;
            ul {
                display: flex;
                li {
                    margin: 0 10px;
                    cursor: pointer;
                }
            }
            ol {
                display: flex;
                align-items: center;
                li {
                    margin: 0 10px;
                    cursor: pointer;
                }
            }
        }
        .info {
            border-bottom: 1px solid #ccc;
            h2 {
                font-family: '微软雅黑 Bold', '微软雅黑 Regular', '微软雅黑';
                font-weight: 700;
                font-style: normal;
                font-size: 15px;
            }
            &-detail {
                display: flex;
                p {
                    font-size: 12px;
                    color: #7F7F7F;
                    margin-right: 10px;
                }
            }
        }
        .temp-table {
            margin-top: 5px;
            &-top {
                padding: 10px 0 10px 10px;
                border: 1px solid #ccc;
                .btn_new_group {
                    background: #0EAFC0;
                    border-color: #0EAFC0;
                    padding: 6px;
                    font-size: 12px;
                    border-radius: 0;
                    margin: 0;
                }
                .btn_new_group:hover {
                    background: #0adcf3;
                    border-color: #0adcf3;
                }
            }
            &-bottom {
                .data_table {
                    max-width: 1100px;
                    width: 100%;
                    ::v-deep th {
                        background-color: #f2eded;
                    }
                    .event_param {
                        position: relative;
                        ul {
                            position: absolute;
                            left: 50%;
                            top: -2px;
                            transform: translateX(-50%);
                            display: flex;
                            z-index: 1;
                            li {
                                margin-right: 5px;
                                font-weight: 250;
                                font-style: normal;
                                font-size: 11px;
                                text-align: center;
                                width: 80px;
                                padding: 0 4px;
                                height: 20px;
                                line-height: 20px;
                                background-color: rgba(0, 191, 191, 1);
                                border: none;
                                border-radius: 4px;
                                box-shadow: 2px 2px 2px rgba(0, 191, 191, .35);
                                font-family: '微软雅黑 Light', '微软雅黑 Regular', '微软雅黑';
                                color: #FFFFFF;
                                cursor: pointer;
                            }
                        }
                    }
                }
                .temp-count {
                    background-color: #F2F2F2;
                    p {
                        margin: 0;
                        height: 45px;
                        line-height: 45px;
                        padding-right: 10px;
                        font-family: 'Arial Normal', 'Arial';
                        font-weight: 400;
                        font-style: normal;
                        font-size: 13px;
                        letter-spacing: normal;
                        color: #333333;
                        text-align: right;
                    }
                }
            }
        }
        .fs20 {
            font-size: 20px;
            cursor: pointer;
        }
    }
</style>

如果又有问题,拖拽失效  @cell-mouse-enter.once="rowDrop"可以试试在el-table上写这个

第三点,如何让多个行,其中几行不能拖拽,不能拖动,去掉.allowdrop拖拽类名就行了,但是如何不被其他可拖拽的元素影响呢,可以用onMove做判断,给不能拖拽的行加类名,可以用:row-class-name="tableRowClassName"来给要加的行加 看element文档吧,然后在onMove里判断有没有类名,有就返回,不被其他拖拽影响

其中几行不能拖拽,在onend里判断也可以让这几行不能互相拖拽,但是还会有拖拽效果,能拖动,这样能拖动,结果虽然互相拖不会有影响,但是拖到能拖拽的元素又会换位置

所以需要用去掉.allowdrop拖拽类名,让他不能拖动比较好

代码

<template>
    <div id="mone_test_tmpl_detail" class="tmpl_detail">
        <template v-if="!isScriptShow&&!isApiEditShow">
            <div>
                <!--头部-->
                <div class="toolbars">
                    <ul>
                        <!--这里的下面三个调用弹框 传编辑,复制,删除所需要的数据就行了,这个数据,这里单独发请求到了-->
                        <li @click="toTmplDetail1">
                            <i class="el-icon-back"></i>
                        </li>
                        <li @click="handleEvent('tableEdit')">
                            <i class="el-icon-edit"></i>
                            <span>编辑</span>
                        </li>
                        <li @click="handleEvent('tableCopy')">
                            <i class="el-icon-document-copy"></i>
                            <span>复制</span>
                        </li>
                        <li @click="handleEvent('tableDel')">
                            <i class="el-icon-delete"></i>
                            <span>删除</span>
                        </li>
                    </ul>
                    <div class="enviroment">
                        <div class="enviroment_l">
                            <el-tooltip class="item" effect="dark" content="弹窗显示环境信息" placement="left">
                                <i class="el-icon-view"></i>
                            </el-tooltip>
                        </div>
                        <div class="enviroment_r">
                            <el-select v-model="value" placeholder="未设置环境">
                                <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">
                                </el-option>
                            </el-select>
                        </div>
                    </div>
                </div>
                <!--下面-->
                <div class="tab">
                    <ul class="tab_t">
                        <!--头部tab切换-->
                        <li @click="switchTab(1)" :class="{active:currentTabIndex==1}">测试流程</li>
                        <li @click="switchTab(2)" :class="{active:currentTabIndex==2}">测试数据</li>
                    </ul>
                    <div class="tab_b">
                        <!--底部切换的tab-->
                        <div v-if="currentTabIndex==1">
                            <!--信息数据-->
                            <div class="info">
                                <div class="info_t">
                                    <h2>{{stempConfig.templateName}}</h2>
                                    <div class="info_t_r">
                                        <div class="tr_l">
                                            <i class="el-icon-odometer" style="margin-right: 5px;"></i>
                                            <span>执行历史</span>
                                        </div>
                                        <div class="tr_r">
                                            <el-button size="mini" style="background-color: #0EAFC0;" type="primary" icon="el-icon-odometer">执行测试</el-button>
                                        </div>
                                    </div>
                                </div>
                                <div class="info_detail">
                                    <p>分组:{{currentDirectoryName}}</p>
                                    <p>创建人:{{stempConfig.creator}}</p>
                                    <p>更新时间:{{stempConfig.updateTime}}</p>
                                </div>
                            </div>

                            <!--表格部分-->
                            <div class="temp-table">
                                <div class="temp-table-top">
                                    <el-dropdown trigger="click" @command="handleCommand">
                                        <div class="el-dropdown-link">
                                            <el-button type="primary" icon="el-icon-plus" class="btn_new_group">添加测试步骤</el-button>
                                            <el-button type="primary" icon="el-icon-caret-bottom" class="btn_new_group"></el-button>
                                        </div>
                                        <el-dropdown-menu slot="dropdown">
                                            <el-dropdown-item command="a">选择api</el-dropdown-item>
                                            <el-dropdown-item command="b">新建脚本</el-dropdown-item>
                                            <el-dropdown-item command="c">新建数据库</el-dropdown-item>
                                        </el-dropdown-menu>
                                    </el-dropdown>
                                    <el-button size="mini" style="margin-left: 20px;padding:6px 5px;" type="danger" :disabled="tableLength" @click="handleCommandBatch">批量删除</el-button>
                                </div>
                                <div class="temp-table-bottom">
                                    <el-table ref="dragTable" :data="tableData" :header-cell-style="{background:'#F8F2F2'}" class="data_table" style="width: 100%"
                                        border :row-class-name="tableRowClassName"  row-key="id">
                                        <!--@cell-mouse-enter.once="rowDrop"-->
                                        <el-table-column :width="item.formLabelWidth" show-overflow-tooltip v-for="(item, index) in col" :render-header="(h,obj) => renderTooltip(h, obj)" :key="`col_${index}`" header-align="center"
                                            align="center" :prop="item.prop" :label="item.label">
                                            <!--:width="item.formLabelWidth?item.formLabelWidth:'auto'"-->
                                            <template slot-scope="scope">
                                                <div :class="scope.row.stepType=='js'?'':'allowDrag'" v-if="item.type=='sort'" style="text-align: center;">
                                                    <i class="el-icon-sort" style="cursor:pointer;"></i>
                                                </div>
                                                <div v-else-if="item.type=='singleCheck'">
                                                    <el-checkbox v-model="scope.row[item.prop]" @change="handleSingleCheck(scope.row,item.prop)"></el-checkbox>
                                                </div>
                                                <div class="tags" v-else-if="item.type=='tag'">
                                                    <div class="tag_api" v-if="scope.row[item.prop]!='db'&&scope.row[item.prop]!='js'">
                                                        {{scope.row[item.prop].toUpperCase()}}
                                                    </div>
                                                    <div class="tag_js" v-if="scope.row[item.prop]=='js'">
                                                        {{scope.row[item.prop].toUpperCase()}}
                                                    </div>
                                                    <div class="tag_db" v-if="scope.row[item.prop]=='db'">
                                                        {{scope.row[item.prop].toUpperCase()}}
                                                    </div>
                                                    <div class="tag_post" v-if="scope.row[item.prop]!='db'&&scope.row[item.prop]!='js'">
                                                        {{scope.row.requestType&&scope.row.requestType.toUpperCase()}}
                                                    </div>
                                                    <div class="tag_db" v-if="scope.row[item.prop]=='db'">
                                                        {{scope.row.requestType&&scope.row.requestType.toUpperCase()}}
                                                    </div>
                                                    <!--api, db, js, apiTpl, web-->
                                                </div>
                                                <div v-else-if="item.type=='result'">
                                                    <div v-if="scope.row[item.prop]=='successful'">
                                                        通过,查看详情
                                                    </div>
                                                    <div v-else-if="scope.row[item.prop]=='failing'">
                                                        未通过,查看详情
                                                    </div>
                                                    <div v-else>
                                                        尚无测试结果
                                                    </div>
                                                </div>
                                                <div v-else-if="item.type=='operation'">

                                                    <el-tooltip effect="dark" :content="oBtn.tooltip || oBtn.label" placement="top" v-for="oBtn in btns" :key="oBtn.id">
                                                        <el-button size="mini" type="text" class="operation_btn">
                                                            <i @click="triggerIconMethod(oBtn.clickEvent, {index: scope.$index, row: scope.row, currBtnConfig: oBtn })" v-if="oBtn.id == 'execute'"
                                                                :class="scope.row.currentStatus?oBtn.icon:oBtn.icon1"></i>
                                                                <i @click="triggerIconMethod(oBtn.clickEvent, {index: scope.$index, row: scope.row, currBtnConfig: oBtn })" v-else :class="oBtn.icon"></i>
                                                        </el-button>
                                                    </el-tooltip>
                                                </div>
                                                <div v-else  >
                                                    <!--<el-popover placement="top-start"  trigger="hover" :content="scope.row[item.prop]">
                                                        <p slot="reference" style="overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">{{scope.row[item.prop]}}</p>
                                                    </el-popover>-->
                                                    {{scope.row[item.prop]}}
                                                    
                                                </div>
                                            </template>
                                            </el-table-column>
                                            </el-table>
                                            <div class="temp_count">
                                                <p>共{{stempConfig.total}}条记录</p>
                                            </div>
                                </div>
                            </div>
                        </div>
                        <div v-else>
                            数据集
                        </div>
                    </div>
                </div>
            </div>
        </template>


        <api-choose v-if="isComParamShow.flag" :currentApiIdList="currentApiIdList" :isComParamShow="isComParamShow" @commonParamClick="commonParamClick"></api-choose>
        <create-js-script v-if="isScriptShow" :operateType="operateType" :reqConfig="reqConfig" @saveCallback="saveScriptCb"></create-js-script>
        <!--<create-database-script v-if="isScriptShow" @saveCallback="saveScriptCallback"></create-database-script>-->
        <create v-if="isApiEditShow" :editType="2" :apiEditCheck="apiEditCheck" :reqGet="createReqGet" :reqSave="createReqSave"
            @saveCallback="saveCreateEditCallback"></create>
            <!--步骤复制谈框-->
            <el-dialog :visible.sync="copyStepVisible">
                <div slot="title" class="title">
                    <i class="el-icon-circle-plus-outline" style="font-size:17px;"></i>复制步骤
                </div>
                <el-form :model="copyStepForm" :rules="copyStepFormRules" ref="copyStepRef">
                    <el-form-item label="步骤名称" label-width="120">
                        <el-input style="width:300px;" v-model="copyStepForm.stepName"></el-input>
                    </el-form-item>
                </el-form>
                <div slot="footer" class="dialog-footer">
                    <el-button size="mini" @click="copyStepVisible = false" class="btn1">取 消</el-button>
                    <el-button size="mini" type="primary" class="btn2" @click="handleCopyStep">确 定</el-button>
                </div>
            </el-dialog>
    </div>
</template>

<script lang="ts">
    declare function require(img: string): string;  // 声明
    import { Component, Vue, Prop } from 'vue-property-decorator';
    import { Action, State } from 'vuex-class';
    import ApiChoose from 'mone-test/components/commonDialog/apiChoose/index.vue'
    // import CreateDatabaseScript from 'mone-test/components/createDatabaseScript/index.vue'
    import CreateJsScript from 'mone-test/components/createJsScript/index.vue'
    import create from 'mone-test/viewModules/apiAutomation/apiManager/src/create/index.vue'
    import Sortable from 'sortablejs'
    import { ApiTempService } from 'mone-test/services';
    @Component({
        name: 'TmplDetail',
        components: {
            ApiChoose,
            // CreateDatabaseScript,
            CreateJsScript,
            create
        }
    })

    export default class TmplDetail extends Vue {
        @Prop({ type: String, default: () => { return ''; } }) currentDirectoryName;
        @Prop({ type: Object, default: () => { return {}; } }) stepTempInfo;
        // 定义变量
        value: string = ''
        options: object[] = [{
            value: '选项1',
            label: '未设置环境'
        }, {
            value: '选项2',
            label: '测试环境'
        }, {
            value: '选项3',
            label: '预发布环境'
        }]
        currentTabIndex: number = 1
        copyStepForm: object = {
            stepName: "",
        }
        copyStepFormRules: object = {
            stepName: [{ required: true, message: '请填写步骤名称', trigger: 'change' }],
        }
        copyStepVisible: boolean = false
        stempConfig: object = {
            "id": 20,
            "creator": "test",
            "rewriter": null,
            "createTime": "2021-04-02 17:35:37",
            "updateTime": null,
            "directoryPath": null,
            "templateName": "string22",
            "templateDesc": "string11",
            "templateResult": null,
            "projectEnvId": null,
            "versionId": 1,
            "deleted": false,
            "steps": [
            ],
            "total": 0,
            "pathName": "/api-template/api-template-group1"
        }
        col: object[] = [
            {
                label: '顺序',
                type: 'sort',
                formLabelWidth: '50px'
            },
            {
                label: '执行',
                type: 'singleCheck',
                prop: 'executed',
                // formLabelWidth: '50px'
            },
            {
                label: '锁定',
                type: 'singleCheck',
                prop: 'locked',
                // formLabelWidth: '50px'
            },
            {
                label: '步骤类型',
                prop: 'stepType',
                type: 'tag',
                // formLabelWidth: '130px'
            },
            {
                label: '步骤名称',
                prop: 'stepName',
                // formLabelWidth: '130px'
            },
            {
                label: 'URL',
                prop: 'url',
                // formLabelWidth: '130px'
            },
            {
                label: '最近测试结果',
                prop: 'stepResult',
                type: 'result',
                // formLabelWidth: '130px'
            },
            {
                label: '操作',
                type: 'operation',
                // formLabelWidth: '60px'
            },
        ];
        tableData: object[] = [

        ]
        btns: object[] = [
            { id: 'execute', label: '', tooltip: '执行', icon: ['el-icon-video-play'], icon1: ['el-icon-video-pause'], status: false, clickEvent: 'executeStep' },
            { id: 'edit', label: '', tooltip: '编辑', icon: ['el-icon-edit-outline'], clickEvent: 'editStep' },
            { id: 'copy', label: '', tooltip: '复制', icon: ['el-icon-document-copy'], clickEvent: 'copyStep' },
            { id: 'delete1', label: '', tooltip: '删除', icon: ['el-icon-delete'], clickEvent: 'deleteStep' }
        ]
        isComParamShow: object = { flag: false }//api新增页面显示
        isScriptShow: boolean = false//脚本新增页面显示
        isApiEditShow: boolean = false//步骤api编辑页面显示
        createReqGet: object = {
        };//步骤api编辑页面传值
        createReqSave: object = {
        };//步骤api编辑页面传值
        currentEditApiStepIndex: number = -1//当前api步骤编辑的api的id,这个可以点击编辑的时候拿到
        apiSteps: object[] = []
        executeCheck: boolean = false//执行的全选
        lockedCheck: boolean = false//锁定的全选
        currentApiIdList: number[] = []//当前api步骤id列表,
        // 这个id列表要时刻保持更新,意思是每次增删改查,它也要同步更新

        // 复制的肯定是不算选中的,再说了,这也不是通过id来的
        // 外面的是步骤id,里面的是api id 不一样的
        // 所以只能通过那个API名字来
        // 但是我如何区分复制和非复制的呢
        // 需不需要区分
        // 不需要
        // 为什么呢,因为我操作里面的api根本影响不到复制的哪些,名字都不一样
        // 其他的脚本啥的同理
        // 不过最好还是api模板里,我就传模板类型的步骤进去
        // api脚本里我就传脚本类型的步骤进去
        // web脚本里我就传js类型的步骤进去


        // 这个数据我要从当前编辑的步骤身上拿,有就拿,没有就传默认的数据结构进去,不过数组部分还是传空,懂吗
        // 然后api编辑里面,数组部分,我判断传过来的如果是空
        // apiEditCheck: object = {
        //     responseHeader: {
        //         header: [{
        //             id: new Date().getTime(),//什么时候需要这个,没有的时候就需要这个,数据传入的时候就check数据是什么就传什么
        //             // api哪里新增这个hander的时候,每次push的对象都是时间戳id,所以这个不必管
        //             name: "afasd",
        //             required: true,
        //             matchRule: "可选equal,notEqual",
        //             expect: "asdfasdf"

        //         }],
        //         checkRule: "可选check,notCheck"
        //     },
        //     responeBody: {
        //         checkRule: "可选notCheck,code,jsonPath,xpath,text,regex",
        //         statusCode: 200,
        //         jsonPath: [{
        //             value: "asfdasdf",
        //             matchRule: "可选notContian,contain,equal,notEqual,greaterThan,greatThanOrEqual,lessThan,lessThanOrEqual",
        //             expect: "asdfaf"
        //         }],
        //         xpath: "asfd",
        //         text: [{
        //             matchRule: "可选notContian,contain,equal",
        //             expect: "asdfasd"
        //         }],
        //         regex: "asfdasf"
        //     },
        //     // 我自己要带过去的数据,
        //     ownData:{
        //         failContinue:0,
        //         sleepTime:0
        //     }
        // }
        apiEditCheck: object = {
            responseHeader: {
                header: [],
                checkRule: ""
            },
            responeBody: {
                checkRule: "",
                statusCode: 200,
                jsonPath: [],
                xpath: "",
                text: [],
                regex: ""
            },
            // 我自己要带过去的数据,
            ownData: {
                failContinue: 0,
                sleepTime: 0
            }
        }

        tooltip1: any = require('mone-test/assets/img/tooltip1.png');
        tooltip2: any = require('mone-test/assets/img/tooltip2.png');
        operateType: number = 1; // 操作类型: 1-新增js脚本 , 2-编辑js脚本
        reqConfig: object = {
            getReq: {
                query: {
                    // id: 27
                },
            },
            saveReq: {
                data: {
                    type: 'template',
                    apiId: this.stepTempInfo.row.id,
                    // id: 27 // 新建脚本不需要传脚本id, 编辑脚本时需要传脚本id
                },
            }
        };
        // 实时步骤列白长度,以设置批量删除按钮的是否可点击
        get tableLength() {
            const self = this as any
            if (self.tableData.length == 0) {
                return true
            } else {
                return false
            }
        }

        constructor() {
            super()
        }

        created() {
            this.initData();
            if (this.stepTempInfo && this.stepTempInfo.row && this.stepTempInfo.row.id) {
                this.getApiTemp()
                // this.getApiTempStep()
            }
        }
        mounted() {
            const self = this as any
            this.rowDrop();
        }

        // mounted(){}

        // methods
        // 初始化数据
        initData() {

        }
        // 头部三个操作触发父组件函数
        handleEvent(funcName) {
            let obj = { row: {} }
            obj.row = Object.assign({}, this.stempConfig)
            this.$parent[funcName](obj)
        }
        handleSaveStep() {

        }
        // 触发步骤操作icon的回调
        triggerIconMethod(funName, data) {
            const self = this as any
            self[funName](data)
        }
        // 执行步骤
        executeStep(data) {
            const self = this as any
            self.tableData[data.index].currentStatus = !self.tableData[data.index].currentStatus
        }
        // 编辑步骤
        editStep(data) {
            const self = this as any
            // 这里要根据类型,判断不同的步骤,他们编辑是不同的
            // console.log()
            // 根据type和stepType来
            if (data.row.type == 'template' && data.row.stepType == 'api') {
                // this.currentEditApiStepIndex = data.row.index
                // 首先这些发过去,上部分数据
                this.createReqGet = {
                    url: `/test/api/management/${data.row.index}`
                };
                this.createReqSave = {
                    url: '/test/api/management',
                    data: {
                        ids: [data.row.index]
                    }
                };
                // 然后这部分要从步骤身身上取到check里的字段,没有就默认全传空,传空的结构过去
                self.getApiTempStep(data.row.id, res => {
                    console.log('res', res)
                    if (res.check) {
                        self.apiEditCheck=Object.assign({},res.check)
                        
                    }
                this.isApiEditShow = true
                })
            } else if (data.row.type == 'template' && data.row.stepType == 'js') {
                console.log('data', data)
                self.reqConfig.getReq.query.id = data.row.id
                self.reqConfig.saveReq.data.id = data.row.id
                console.log('self.reqConfig', self.reqConfig)
                this.operateType = 2
                this.isScriptShow = true
                //         reqConfig: object = {
                //     getReq: {
                //         query: {
                //             // id: 27
                //         },
                //     },
                //     saveReq: {
                //         data: {
                //             type: 'template',
                //             apiId: this.stepTempInfo.row.id,
                //             id: data.id // 新建脚本不需要传脚本id, 编辑脚本时需要传脚本id
                //         },
                //     }
                // };
            }
        }

        // 复制步骤谈框出现
        copyStep(data) {
            const self = this as any
            this.copyStepVisible = true;
            this.$set(self.copyStepForm, 'stepName', data.row.stepName)
            self.getApiTempStep(data.row.id, res => {
                self.copyStepForm = Object.assign({}, data.row, { input: res.request })
            })

        }
        // 确定复制步骤
        handleCopyStep() {
            const self = this as any
            self.apiSteps = []
            let query = { apiSteps: [] }
            let obj = {
                versionId: 1,//版本id
                type: 'template',//请求类型,template和sciprt,api模板中是template,其他地方都是script
                stepType: 'api',//步骤类型,api,apiTml,db,js,web五种,根据选择来
                sleepTime: self.copyStepForm.sleepTime,//休眠时间
                failContinue: Number(self.copyStepForm.failContinue),//失败后是否继续执行,传数字
                input: self.copyStepForm.input,//api传input,check里的下部分
                stepName: self.copyStepForm.stepName,//步骤名称
                index: self.copyStepForm.index,//api,API模板,web组件,那js和数据库需要传id吗,按理说也要啊。
                apiId: self.copyStepForm.apiId,//当前在表格中的id
                requestType: self.copyStepForm.requestType,//请求类型,这个api才有
                url: self.copyStepForm.url,//url有就传,这个api类型才传
                copy: 1//是否是复制,不是就不传,是就传1
            }
            self.apiSteps.push(obj)
            query.apiSteps = self.apiSteps.concat()
            ApiTempService.addApiTempStep(query).then(res => {
                if (res.code == 200) {
                    // 新增之后,刷新详情
                    this.copyStepVisible = false
                    self.getApiTemp()
                }
            })
        }
        // 删除步骤发请求
        handleDeleteStep(ids) {
            const self = this as any
            // 发个请求删除,然后更新
            this.$confirm('此操作将永久删除该步骤, 是否继续?', '提示', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
            }).then(() => {
                ApiTempService.delApiTempStep({ ids }).then(res => {
                    if (res.code == 200) {
                        self.$message({
                            message: '删除成功',
                            type: 'success'
                        });
                        self.getApiTemp()
                    } else {
                        self.$message({
                            message: '删除失败',
                            type: 'fail'
                        });
                    }
                })
            }).catch(() => {
                this.$message({
                    type: 'info',
                    message: '已取消删除'
                });
            });
        }
        // 单个删除步骤
        deleteStep(data) {
            const self = this as any
            let arr = [data.row.id]
            self.handleDeleteStep(arr)
        }
        // 返回表格页面
        toTmplDetail1() {
            const self = this as any
            // 返回的时候要保存
            // self.handleSaveStep('back')
            this.$emit('toTmplDetail1')
        }
        // 测试流程和测试数据切换
        switchTab(num) {
            this.currentTabIndex = num
        }
        // api选择谈框回调
        commonParamClick(param) {
            const self = this as any
            // 这里是api的回调,但实际上,有三个谈框,
            // 同一个接口,每个传的参数都有点区别,不过这里是api的
            // 在这里,批量删除与批量增加
            console.log('param', param)
            if (param.addList.length != 0) {
                self.apiSteps = []
                let query = { apiSteps: [] }
                param.addList.map(el => {
                    let obj = {
                        versionId: 1,
                        type: 'template',
                        stepType: 'api',
                        sleepTime: 0,
                        failContinue: 0,
                        input: JSON.parse(el.request),
                        stepName: el.apiName,
                        index: el.id,
                        apiId: self.stepTempInfo.row.id,
                        requestType: el.method.toLowerCase(),
                        url: el.host + el.path
                    }
                    self.apiSteps.push(obj)
                })
                query.apiSteps = self.apiSteps.concat()
                ApiTempService.addApiTempStep(query).then(res => {
                    if (res.code == 200) {
                        // 新增之后,刷新详情
                        self.getApiTemp()
                    }
                })
            }

            if (param.deleteList.length != 0) {
                // 根据api id找到步骤id列表
                let ids: any = []
                self.tableData.map(el => {
                    param.deleteList.map(item => {
                        if (el.index == item) {
                            if (!ids.includes(el.id)) {
                                ids.push(el.id)
                            }
                        }
                    })
                })
                if (ids.length > 0) {
                    ApiTempService.delApiTempStep({ ids }).then(res => {
                        if (res.code == 200) {
                            self.$message({
                                message: '删除成功',
                                type: 'success'
                            });
                            self.getApiTemp()
                        } else {
                            self.$message({
                                message: '删除失败',
                                type: 'fail'
                            });
                        }
                    })
                }
            }
        }
        // 脚本页面回调
        saveScriptCb(data) {
            this.isScriptShow = false
            this.getApiTemp()
            // self.apiSteps = []
            // let jsData= data.data.apiSteps[0]
            // if(jsData.length==0)return
            //     let query:any = { apiSteps: [] }
            //         let obj = {
            //             versionId: 1,
            //             type: 'template',
            //             stepType: 'js',
            //             sleepTime: jsData.sleepTime?Number(jsData.sleepTime):0,
            //             failContinue: Number(jsData.failContinue),
            //             // input: JSON.parse(el.request),
            //             stepName: jsData.stepName,
            //             // index: el.id,
            //             apiId: jsData.apiId,
            //             // requestType: el.method.toLowerCase(),
            //             input:jsData.input,
            //             output:jsData.output
            //         }
            //         // self.apiSteps.push(obj)
            //         query.apiSteps.push(obj)
            //     // query.apiSteps = self.apiSteps.concat()
            //     ApiTempService.addApiTempStep(query).then(res => {
            //         if (res.code == 200) {
            //             // 新增之后,刷新详情
            //             self.getApiTemp()
            //         }
            //     })
        }
        // api步骤编辑的回调 
        saveCreateEditCallback(res) {
            // 首先
            console.log('res{data,apiEditCheck}', res)
            this.isApiEditShow = false
            // self.apiSteps = []
            //     let query = { apiSteps: [] }
            //     param.addList.map(el => {
            //         let obj = {
            //             versionId: 1,
            //             type: 'template',
            //             stepType: 'api',
            //             sleepTime: 1000,
            //             failContinue: 0,
            //             input: el.request,
            //             stepName: el.apiName,
            //             index: el.id,
            //             apiId: self.stepTempInfo.row.id,
            //             requestType: el.method.toLowerCase(),
            //             url: el.host + el.path,
            //             check:{}
            //         }
            //         self.apiSteps.push(obj)
            //     })
            //     query.apiSteps = self.apiSteps.concat()
            //     ApiTempService.addApiTempStep(query).then(res => {
            //         if (res.code == 200) {
            //             // 新增之后,刷新详情
            //             self.getApiTemp()
            //         }
            //     })
        }
        // 步骤谈框选择,api,脚本,等
        handleCommand(command) {
            const self = this as any
            // 新增步骤
            // 启动和元素定位都是同一个接口,不过是传不同的东西,意思是两个都可以新增步骤
            // this.operation = 1//新增都要显示这个确定,不同的谈框中,没影响
            if (command == 'a') {
                self.isComParamShow.flag = true
            }
            else if (command == 'b') {
                // 如果是脚本类型,那么要重置一下参数
                self.reqConfig.getReq.query.id = ''
                self.reqConfig.saveReq.data.id = ''
                // console.log('self.reqConfig', self.reqConfig)
                this.operateType = 1
                this.isScriptShow = true
            }

        }
        // 批量删除步骤
        handleCommandBatch() {
            const self = this as any
            let arr = self.tableData.map(el => el.id)
            // let arr = [data.row.id]
            self.handleDeleteStep(arr)
        }
        // 获取api模板基本信息,包含粗略步骤列表
        getApiTemp() {
            const self = this as any
            ApiTempService.getApiTemp(self.stepTempInfo.row.id).then(res => {
                if (res.code == 200) {
                    self.stempConfig = Object.assign({}, res.data)

                    self.tableData = res.data.steps.concat()
                    // 每次查询,currentApiIdList也跟着跟新
                    self.currentApiIdList = self.tableData
                        .filter(el => el.stepType == 'api' && el.type == 'template' && el.copy != 1)
                        .map(el => el.index)
                    // 如果步骤的executed全都为true,那么
                    let exeFlag1 = self.tableData.every(el => el.executed)
                    if (self.tableData.length == 0) {
                        self.executeCheck = false
                    } else {
                        if (exeFlag1) {
                            self.executeCheck = true
                        } else {
                            self.executeCheck = false
                        }
                    }
                    let exeFlag2 = self.tableData.every(el => el.locked)
                    if (self.tableData.length == 0) {
                        self.lockedCheck = false
                    } else {
                        if (exeFlag2) {
                            self.lockedCheck = true
                        } else {
                            self.lockedCheck = false
                        }
                    }

                }
            })
                .catch(err => {
                    // self.toTmplDetail1()
                })
        }
        // 获取API模板步骤列表详情
        getApiTempStep(id, callback) {
            const self = this as any
            ApiTempService.getApiTempStep('', { id }).then(res => {
                if (res.code == 200) {
                    // self.total = res.data.total
                    // self.tableData = Object.assign({}, res.data)
                    callback(res.data)
                }
            })
                .catch(err => {
                    // self.toTmplDetail1()
                })
        }
        // 执行与锁定checkbox单选
        handleSingleCheck(data, prop) {
            const self = this as any
            let query: any = {}
            query.apiSteps = []
            if (prop == 'executed') {
                let exeFlag1 = self.tableData.every(el => el.executed)
                if (self.tableData.length == 0) {
                    self.executeCheck = false
                } else {
                    if (exeFlag1) {
                        self.executeCheck = true
                    } else {
                        self.executeCheck = false
                    }
                }
                query.apiSteps = [{ id: data.id, executed: data.executed }]
            } else if (prop == 'locked') {
                let exeFlag2 = self.tableData.every(el => el.locked)
                if (self.tableData.length == 0) {
                    self.lockedCheck = false
                } else {
                    if (exeFlag2) {
                        self.lockedCheck = true
                    } else {
                        self.lockedCheck = false
                    }
                }
                query.apiSteps = [{ id: data.id, locked: data.locked }]
            }
            ApiTempService.isExeOrLock(query).then(res => {
                if (res.code == 200) {
                    self.getApiTemp()
                }
            })

        }
        // 渲染表头
        renderTooltip(h, { column, $index }) {
            const self = this as any;
            if (column.label == '执行' || column.label == '锁定') {
                return h('div', { style: 'display: flex;align-items:center;justify-content:space-evenly;' }, [
                    h('el-checkbox', {
                        props: {
                            value: column.label == '执行' ? self.executeCheck : self.lockedCheck,
                        },
                        on: {
                            change: function (e) {
                                let query: any = {}
                                query.apiSteps = []
                                if (column.label == '执行') {
                                    self.executeCheck = !self.executeCheck
                                    self.tableData.map(el => {
                                        self.$set(el, 'executed', self.executeCheck)
                                        query.apiSteps.push({ id: el.id, executed: el.executed })
                                    })
                                } else if (column.label == '锁定') {
                                    self.lockedCheck = !self.lockedCheck
                                    self.tableData.map(el => {
                                        self.$set(el, 'locked', self.lockedCheck)
                                        query.apiSteps.push({ id: el.id, locked: el.locked })
                                    })
                                }
                                ApiTempService.isExeOrLock(query).then(res => {
                                    if (res.code == 200) {
                                        self.getApiTemp()
                                    }
                                })
                            }
                        }
                    }),

                    h('div', {
                        domProps: {
                            innerHTML: column.label
                        }
                    }),

                    h(
                        'el-tooltip',  //  标签的名称
                        {
                            props: {
                                content: (function () {
                                    if (column.label == '执行') {
                                        return '仅会执行勾选的步骤'
                                    } else {
                                        return '勾选锁定的步骤一定会按顺序执行,即使其他步骤出现异常'
                                    }

                                })(),
                                placement: 'top-end',
                                // effect: "light",  //  默认为黑色主题
                            },
                        },
                        [
                            h('div', {
                                style: {
                                    position: 'relative'
                                }
                            }, [
                                    h('img', {
                                        attrs: {
                                            src: self.tooltip1
                                        },
                                    }),
                                    h('img', {
                                        attrs: {
                                            src: self.tooltip2
                                        },
                                        style: {
                                            position: 'absolute',
                                            left: '6px',
                                            top: '6px',
                                            height: '8px',
                                            width: '3px'
                                        }
                                    }),
                                ])]
                    )
                ]);
            }
            return h('div', { style: 'display: flex;justify-content:center;' }, [
                h('div', {
                    domProps: {
                        innerHTML: column.label
                    }
                }),
            ]);

        }
        // 表格行添加 class
    tableRowClassName({row, rowIndex}){
        const self = this as any;
        if(row.stepType=='js'){
            return 'drag_table_disabled_drag_row';
        }
        return '';
    }
        // 行拖拽
        rowDrop() {
            const _this = this as any
            const table = _this.$refs.dragTable;
            const tbody = table.$el.querySelector('.el-table__body-wrapper tbody');
            Sortable.create(tbody, {
                handle: ".allowDrag",
                onEnd({ newIndex, oldIndex }) {
                    // 如果是模板类型,就不许交换
                    if(newIndex==oldIndex)return
                   if(_this.tableData[newIndex].stepType=='js') return
                    const currRow = _this.tableData.splice(oldIndex, 1)[0]
                    _this.tableData.splice(newIndex, 0, currRow)
                    // 拖拽结束调用排序接口
                    // id对应相应的顺序
                    const query = { orderMap: {} }
                    _this.tableData.map((el, index) => {
                        query.orderMap[el.id] = index
                        return el
                    })
                    ApiTempService.tempSort(query).then(res => {
                        if (res.code == 200) {
                            _this.getApiTemp()
                        }
                    })
                },
               // 拖拽移动的时候
            onMove: function (/**Event*/evt, /**Event*/originalEvent) {
                if(evt.related.className.indexOf('drag_table_disabled_drag_row') !== -1){
                    return false;
                }
                console.log('evt',evt)
            },
            })
        }
    }

</script>

<style scoped lang="scss">
    #mone_test_tmpl_detail {
        /*height: 100%;*/
        flex: 1;
        overflow: auto;
        .toolbars {
            display: flex;
            justify-content: space-between;
            align-items: center;
            ul {
                display: flex;
                li {
                    margin: 0 10px;
                    cursor: pointer;
                }
            }
            .enviroment {
                display: flex;
                overflow: hidden;
                &_l {
                    width: 50px;
                    border: 1px solid #d7d7d7;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                }
                &_r {
                    ::v-deep .el-input__inner {
                        border-radius: 0;
                        border-left: 0;
                        border-color: #d7d7d7;
                    }
                }
            }
        }
        .tab {
            &_t {
                display: flex;
                border-bottom: 1px solid #d7d7d7;
                padding-left: 20px;
                margin-top: 20px;
                li {
                    width: 66px;
                    display: inline-block;
                    float: left;
                    height: 30px;
                    /*border: 1px solid #d7d7d7;*/
                    /*border-bottom: 1px solid transparent;*/
                    margin-bottom: -1px;
                    background: #fff;
                    text-align: center;
                    margin-left: 12px;
                    padding-bottom: 10px;
                    line-height: 30px;
                }
                li:hover {
                    border: 1px solid #d7d7d7;
                    border-bottom: 1px solid transparent;
                    cursor: pointer;
                }
                li.active {
                    border: 1px solid #d7d7d7;
                    border-bottom: 1px solid transparent;
                }
            }
            &_b {
                .info {
                    border-bottom: 1px solid #ccc;
                    &_tag {
                        display: flex;
                        li {
                            padding: 2px;
                            height: 22px;
                            background-color: rgba(236, 245, 255, 1);
                            border-radius: 2px;
                            font-size: 12px;
                            margin-right: 5px;
                        }
                    }
                    &_t {
                        display: flex;
                        justify-content: space-between;
                        align-items: center;
                        h2 {
                            font-family: '微软雅黑 Bold', '微软雅黑 Regular', '微软雅黑';
                            font-weight: 700;
                            font-style: normal;
                            font-size: 15px;
                        }
                        .info_t_r {
                            display: flex;
                            align-items: center;
                            .tr_l {
                                margin-right: 10px;
                            }
                            .tr_r {}
                        }
                    }
                    &_detail {
                        display: flex;
                        p {
                            font-size: 12px;
                            color: #7F7F7F;
                            margin-right: 10px;
                        }
                    }
                }
                .temp-table {
                    margin-top: 5px;
                    &-top {
                        padding: 10px 0 10px 10px;
                        border: 1px solid #ccc;
                        .btn_new_group {
                            background: #0EAFC0;
                            border-color: #0EAFC0;
                            padding: 6px;
                            font-size: 12px;
                            border-radius: 0;
                            margin: 0;
                        }
                        .btn_new_group:hover {
                            background: #0adcf3;
                            border-color: #0adcf3;
                        }
                    }
                    &-bottom {
                        .data_table {
                            width: 100%;
                        }
                        .temp_count {
                            background-color: #F2F2F2;
                            p {
                                margin: 0;
                                height: 45px;
                                line-height: 45px;
                                padding-right: 10px;
                                font-family: 'Arial Normal', 'Arial';
                                font-weight: 400;
                                font-style: normal;
                                font-size: 13px;
                                letter-spacing: normal;
                                color: #333333;
                                text-align: let;
                            }
                        }
                        .tags {
                            display: flex;
                            justify-content: space-between;
                            .tag_api {
                                color: #348FE4;
                                border: 1px solid #348FE4;
                                padding: 0 10px;
                                font-size: 12px;
                            }
                            .tag_post {
                                background-color: #0eafc0;
                                padding: 0 10px;
                                color: #fff;
                                font-size: 12px;
                            }
                            .tag_js {
                                border: 1px solid #BB741A;
                                padding: 0 10px;
                                color: #BB741A;
                                font-size: 12px;
                            }
                            .tag_db {
                                border: 1px solid #333333;
                                padding: 0 10px;
                                color: #333333;
                                font-size: 12px;
                            }
                        }
                    }
                }
            }
        }
    }
    
    ::v-deep .el-dropdown-menu__item {
        padding: 8px 16px 8px 16px;
        font-family: 'Microsoft YaHei Regular', 'Microsoft YaHei';
        font-weight: 400;
        font-style: normal;
        font-size: 12px;
        color: rgba(85, 85, 85, 0.647058823529412);
        border-bottom: 1px dashed #ccc;
    }
    
    ::v-deep .el-dialog {
        width: 440px;
        .dialog-footer {
            display: flex;
            justify-content: flex-end;
            margin: 16px 5px 16px 0;
            .btn1,
            .btn2 {
                box-shadow: 5px 5px 5px rgba(0, 0, 0, .35);
                border-radius: 5px;
                font-family: '微软雅黑';
            }
            .btn1 {
                color: #AAA;
                background-color: #f2f2f2;
            }
            .btn2 {
                background-color: #0EAFC0;
            }
        }
        .el-dialog__header {
            background: #FCFCFC;
            border-bottom: 1px solid #d7d7d7;
            padding: 0;
            padding: 10px;
        }
        .el-dialog__body {
            padding: 0!important;
            padding-left: 70px!important;
            padding-top: 20px!important;
        }
    }
    
    .title {
        font-size: 15px;
        color: #333;
        font-weight: bold;
    }
</style>

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值