vue实现拖拽,增加等功能

一、直接上代码:样式如下
在这里插入图片描述

# 安装拖拽依赖vuedraggable
npm install vuedraggable

二、示例代码

<template>
  <div class="app-container">
    <!--条件搜索-->
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="所属部门" prop="deptId">
        <treeselect v-model="queryParams.deptId" :options="deptOptions" :show-count="true"
                    placeholder="所属部门" style="width: 240px"/>
      </el-form-item>
      <el-form-item label="考核类型" prop="judgeType">
        <el-select
          v-model="queryParams.judgeType"
          placeholder="考核类型"
          clearable
          style="width: 240px">
          <el-option
            v-for="dict in dict.type.judge_type"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"/>
        </el-select>
      </el-form-item>
      <el-form-item label="创建时间">
        <el-date-picker
          v-model="dateRange"
          style="width: 240px"
          value-format="yyyy-MM-dd HH:mm:ss"
          type="daterange"
          range-separator="-"
          start-placeholder="开始日期"
          end-placeholder="结束日期"
          :default-time="['00:00:00', '23:59:59']">
        </el-date-picker>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <!--按钮-->
    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="el-icon-plus"
          size="mini"
          @click="handleAdd"
          v-hasPermi="['evaluate:standard:add']">新增
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="warning"
          plain
          icon="el-icon-document-copy"
          size="mini"
          :disabled="multiple"
          @click="handleCopy"
          v-hasPermi="['evaluate:standard:copy']">复制
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          plain
          icon="el-icon-delete"
          size="mini"
          :disabled="multiple"
          @click="handleDelete"
          v-hasPermi="['evaluate:standard:remove']">批量删除
        </el-button>
      </el-col>
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>
    <!--列表-->
    <el-table ref="tables" v-loading="loading" :data="list" @selection-change="handleSelectionChange"
              :default-sort="defaultSort" @sort-change="handleSortChange"
              row-key="id"
              :tree-props="{children: 'copyData', hasChildren: 'hasChildren'}">
      <el-table-column type="selection" width="50" align="center" :selectable="isParentNode"/>
      <el-table-column label="编号" align="center" prop="id"/>
      <el-table-column label="所属部门" align="center" prop="deptId">
        <template slot-scope="scope">
          {{ deptNames[scope.row.deptId] || '未知部门' }}
        </template>
      </el-table-column>
      <el-table-column label="考核类型" align="center" prop="judgeType">
        <template slot-scope="scope">
          <dict-tag :options="dict.type.judge_type" :value="scope.row.judgeType"/>
        </template>
      </el-table-column>
      <el-table-column label="考核指标" align="center" prop="judgeIndex"/>
      <el-table-column label="对应加减分" align="center" prop="judgeSocre"/>
      <el-table-column label="创建人" align="center" prop="createBy"/>
      <el-table-column label="创建时间" align="center" prop="createTime" width="160" sortable="custom"
                       :sort-orders="['descending', 'ascending']"/>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <!-- 判断是否为父节点(parentId 为空)-->
          <template v-if="!scope.row.parentId">
            <!-- parentId 为空时,显示 详细、修改 和 删除 按钮 -->
            <el-button
              size="mini"
              type="text"
              icon="el-icon-view"
              @click="handleView(scope.row)"
              v-hasPermi="['evaluate:standard:query']"
            >详细
            </el-button>
            <el-button
              size="mini"
              type="text"
              icon="el-icon-edit"
              @click="handleUpdate(scope.row)"
              v-hasPermi="['evaluate:standard:edit']"
            >修改
            </el-button>
            <el-button
              size="mini"
              type="text"
              icon="el-icon-delete"
              @click="handleDelete(scope.row)"
              v-hasPermi="['evaluate:standard:remove']"
            >删除
            </el-button>
          </template>

          <!-- parentId 不为空时,只显示 删除 按钮 -->
          <template v-else>
            <el-button
              size="mini"
              type="text"
              icon="el-icon-delete"
              @click="handleDelete(scope.row)"
              v-hasPermi="['evaluate:standard:remove']"
            >删除
            </el-button>
          </template>
        </template>
      </el-table-column>
    </el-table>
    <!--分页组件-->
    <pagination
      v-show="total>0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getList"
    />
    <!--弹窗 -->
    <MyDialog ref="dialog" @refresh="getList"></MyDialog>
  </div>
</template>

<script>
import MyDialog from './myDialog.vue'
import {deptTreeSelect} from "@/api/system/user";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import {listJudge, getJudge, delJudge, copyJudge} from "@/api/coppms/judge";

export default {
  // 字典类型
  dicts: ['judge_type'],
  data() {
    return {
      // 遮罩层
      loading: true,
      // 选中数组
      ids: [],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // 表格数据
      list: [],
      // 是否显示弹出层
      open: false,
      // 日期范围
      dateRange: [],
      // 默认排序
      defaultSort: {prop: 'createTime', order: 'descending'},
      // 表单参数
      form: {},
      // 查询参数
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        deptId: undefined,
        judgeType: undefined
      },
      // 部门树选项
      deptOptions: [],
      // 用于存储部门名称的对象
      deptNames: {}
    };
  },
  created() {
    this.getDeptTree();
    this.getList();
  },
  components: {
    Treeselect,
    MyDialog
  },
  methods: {
    // 判断是否为父节点(parentId 为空)
    isParentNode(row) {
      return !row.parentId;
    },

    //  查询部门下拉树结构
    async getDeptTree() {
      const response = await deptTreeSelect();
      this.deptOptions = response.data;
      this.extractDeptNames(this.deptOptions);
    },
    // 获取部门信息
    extractDeptNames(departments) {
      const deptNames = {};

      // 递归处理部门信息并保存
      function traverse(depts) {
        depts.forEach(dept => {
          deptNames[dept.id] = dept.label;
          if (dept.children) {
            traverse(dept.children);
          }
        });
      }

      traverse(departments);
      this.deptNames = deptNames;
    },
    // 查询评判标准列表
    getList() {
      this.loading = true;
      listJudge(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
          this.list = response.rows;
          this.total = response.total;
          this.loading = false;
        }
      );
      this.loading = false;
    },
    // 搜索按钮操作
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    // 重置按钮操作
    resetQuery() {
      this.queryParams = {}
      this.dateRange = []
      this.getList()
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.id);
      this.single = selection.length != 1;
      this.multiple = !selection.length;
    },
    // 排序触发事件
    handleSortChange(column, prop, order) {
      this.queryParams.orderByColumn = column.prop;
      this.queryParams.isAsc = column.order;
      this.getList();
    },
    // 详细
    handleView(row) {
      getJudge(row.id).then(response => {
        let title = '查看';
        let formData = response.data;
        let isViewMode = true
        this.$refs.dialog.open(title, formData, isViewMode);
      });
    },
    // 新增
    handleAdd() {
      let title = '新增';
      let formData = {};
      let isViewMode = false
      this.$refs.dialog.open(title, formData, isViewMode);
    },
    // 修改
    handleUpdate(row) {
      const id = row.id;
      getJudge(id).then(response => {
        let title = '修改';
        let formData = response.data;
        let isViewMode = false
        this.$refs.dialog.open(title, formData, isViewMode);
      });
    },
    // 复制
    handleCopy() {
      const ids = this.ids;
      this.$modal.confirm('是否确认复制编号为"' + ids + '"的数据项?').then(function () {
        return copyJudge(ids);
      }).then(() => {
        this.getList();
        this.$modal.msgSuccess("复制成功");
      }).catch(() => {
      });
    },
    // 删除按钮操作
    handleDelete(row) {
      const ids = row.id || this.ids;
      this.$modal.confirm('是否确认删除编号为"' + ids + '"的数据项?').then(function () {
        return delJudge(ids);
      }).then(() => {
        this.getList();
        this.$modal.msgSuccess("删除成功");
      }).catch(() => {
      });
    },
  }
};
</script>


<template>
  <div>
    <el-dialog custom-class="dialog-title" :visible.sync="isVisible" :title="dialogTitle+'评判标准'"
               :close-on-click-modal="false"
               @close="close"
               width="80%">
      <el-form ref="elForm" :model="formData" :rules="rules" size="medium" label-width="170px">
        <el-form-item label="评判标准所属部门" prop="deptId">
          <treeselect v-model="formData.deptId" :options="deptOptions" :show-count="true"
                      placeholder="请选择评判标准所属部门" :style="{width: '50%'}" :disabled="isViewMode"/>
        </el-form-item>
        <el-form-item label="考核类型" prop="judgeType">
          <el-select v-model="formData.judgeType" placeholder="请选择考核类型" clearable :style="{width: '50%'}"
                     :disabled="isViewMode">
            <el-option
              v-for="dict in dict.type.judge_type"
              :key="dict.value"
              :label="dict.label"
              :value="dict.value"/>
          </el-select>
        </el-form-item>
        <el-form-item label="评判标准对应考核指标" prop="judgeIndex">
          <el-input v-model="formData.judgeIndex" placeholder="请输入评判标准对应考核指标" clearable
                    :style="{width: '100%'}" :readonly="isViewMode"></el-input>
        </el-form-item>
        <el-form-item label="评判标准对应加减分值" prop="judgeSocre">
          <el-input v-model="formData.judgeSocre"
                    placeholder="说明:分值必须为 X~X 格式,或者单独一个 ~ 字符,其中 X 可以为数字(正数、负数、小数,正数不能以 0 开头);后面的值必须大于前面的值"
                    clearable
                    :style="{width: '100%'}" :readonly="isViewMode"></el-input>
        </el-form-item>
        <el-form-item label="评判标准描述">
          <el-input v-model="formData.judgeDesc" type="textarea" placeholder="请输入评判标准描述"
                    :autosize="{minRows: 4, maxRows: 4}" :style="{width: '100%'}" :readonly="isViewMode"></el-input>
        </el-form-item>
        <!--具体选项----------------------------------------------------------------------------------------->
        <el-form-item label="具体选项">
          <el-button type="primary" icon="el-icon-plus" size="mini" @click="addOptions" plain :disabled="isViewMode">
            添加
          </el-button>
        </el-form-item>

        <!-- 增加一个固定高度的容器用于滚动 -->
        <!--选项-->
        <div class="options-container">
          <draggable v-model="options" handle=".drag-handle" @end="updateOrder">
            <transition-group>
              <el-form-item v-for="(option, index) in options" :key="option.optionKey">
                <!-- 父选项头部 -->
                <el-form-item>
                  <label>选项 {{ index + 1 }}:</label>
                  <el-button class="remove-button" type="danger" icon="el-icon-delete" size="mini"
                             @click="removeOption(index)" plain :disabled="isViewMode">删除
                  </el-button>
                  <el-tag class="drag-handle" style="cursor: move;margin-left: 20px;" type="info">点击此处拖动排序
                  </el-tag>
                </el-form-item>
                <div class="option-block">
                  <el-form-item label="是否有下级选项">
                    <el-radio-group v-model="option.optionIsHaveChild" :disabled="isViewMode">
                      <el-radio :label=1></el-radio>
                      <el-radio :label=0></el-radio>
                    </el-radio-group>
                    <el-button v-if="option.optionIsHaveChild === 1" class="add-button" type="primary"
                               icon="el-icon-plus"
                               size="mini" @click="addSubOption(index)"
                               plain :disabled="isViewMode">添加
                    </el-button>
                  </el-form-item>

                  <!--父选项内容-->
                  <el-form-item label="选项介绍" class="form-item-with-spacing">
                    <el-input v-model="option.optionIntroduce" type="textarea" placeholder="请输入选项介绍"
                              :readonly="isViewMode"></el-input>
                  </el-form-item>
                  <el-form-item v-if="option.optionIsHaveChild === 0" label="选项分值" class="form-item-with-spacing">
                    <el-input-number v-model="option.optionScore" placeholder="请输入选项分值"
                                     :style="{width: '25%'}" :disabled="isViewMode"
                                     :precision="2" :step="0.1" :max="99"></el-input-number>
                  </el-form-item>

                  <!--子选项-->
                  <draggable v-if="option.optionIsHaveChild===1" v-model="option.subOptions" handle=".drag-handle"
                             @end="updateSubOrder(index)">
                    <transition-group>
                      <div class="sub-option-block" v-for="(subOption, subIndex) in option.subOptions"
                           :key="subOption.optionKey">
                        <!--子选项头部-->
                        <el-form-item>
                          <label>子选项 {{ subIndex + 1 }}:</label>
                          <el-button class="remove-button" type="danger" icon="el-icon-delete" size="mini"
                                     @click="removeSubOption(index, subIndex)" plain :disabled="isViewMode">删除
                          </el-button>
                          <el-tag class="drag-handle" style="cursor: move;margin-left: 20px;" type="info">点击此处拖动排序
                          </el-tag>
                        </el-form-item>
                        <!--子选项内容-->
                        <el-form-item label="选项介绍" class="form-item-with-spacing">
                          <el-input v-model="subOption.optionIntroduce" type="textarea" placeholder="请输入选项介绍"
                                    :readonly="isViewMode"></el-input>
                        </el-form-item>
                        <el-form-item label="选项分值" class="form-item-with-spacing">
                          <el-input-number v-model="subOption.optionScore" placeholder="请输入选项分值"
                                           :style="{width: '25%'}" :disabled="isViewMode"
                                           :precision="2" :step="0.1" :max="99"></el-input-number>
                        </el-form-item>
                      </div>
                    </transition-group>
                  </draggable>
                </div>
              </el-form-item>
            </transition-group>
          </draggable>
        </div>
        <!--以上是具体选项内容---------------------------------------------------------------------------------->
        <el-form-item label="特殊评分" prop="specialSocre">
          <el-radio-group v-model="formData.specialSocre" size="medium" :disabled="isViewMode">
            <el-radio v-for="(item, index) in specialSocreOptions" :key="index" :label="item.value">{{ item.label }}
            </el-radio>
          </el-radio-group>
          <span class="green"
                style="margin-left: 100px;color: red;font-size: 14px;">解释:特殊评分过程请根据评分标准手动输入分值</span>
        </el-form-item>
        <el-form-item label="评判标准解释">
          <el-input v-model="formData.judgeExplain" type="textarea" placeholder="请输入评判标准解释"
                    :autosize="{minRows: 4, maxRows: 4}" :style="{width: '100%'}" :readonly="isViewMode"></el-input>
        </el-form-item>
        <el-form-item label="指标完成情况" prop="completionStatus">
          <el-input v-model="formData.completionStatus" type="textarea" placeholder="请输入指标完成情况"
                    :autosize="{minRows: 4, maxRows: 4}" :style="{width: '100%'}" :readonly="isViewMode"></el-input>
        </el-form-item>
        <el-form-item label="部门自评" prop="deptComment">
          <el-input v-model="formData.deptComment" type="textarea" placeholder="请输入部门自评"
                    :autosize="{minRows: 4, maxRows: 4}" :style="{width: '100%'}" :readonly="isViewMode"></el-input>
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="formData.remark" type="textarea" placeholder="请输入备注"
                    :autosize="{minRows: 4, maxRows: 4}" :style="{width: '100%'}" :readonly="isViewMode"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer">
        <el-button v-if="dialogTitle === '新增'" type="primary" @click="save" :disabled="isViewMode">保存</el-button>
        <el-button v-if="dialogTitle === '修改'" type="primary" @click="update" :disabled="isViewMode">修改</el-button>
        <el-button @click="close">取消</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import {addJudge, updateJudge} from "@/api/coppms/judge";
import {deptTreeSelect} from "@/api/system/user";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import draggable from 'vuedraggable';

export default {
  // 字典类型
  dicts: ['judge_type'],
  inheritAttrs: false,
  components: {Treeselect, draggable},
  props: [],
  data() {
    return {
      // 是否允许修改,默认不是查看模式
      isViewMode: false,
      // 弹窗显示
      isVisible: false,
      // 弹窗标题
      dialogTitle: '',
      // 选项数组
      options: [],
      // 数据对象
      formData: {
        id: '',
        deptId: '',
        judgeType: '',
        judgeIndex: '',
        judgeSocre: '',
        judgeDesc: '',
        specialSocre: 0,
        judgeExplain: '',
        completionStatus: '',
        deptComment: '',
        remark: '',
        children: []
      },
      // 部门树选项
      deptOptions: undefined,
      rules: {
        deptId: [{
          required: true,
          message: '请选择评判标准所属部门',
          trigger: 'change'
        }],
        judgeType: [{
          required: true,
          message: '请选择考核类型',
          trigger: 'change'
        }],
        judgeIndex: [{
          required: true,
          message: '请输入评判标准对应考核指标',
          trigger: 'blur'
        }],
        judgeSocre: [{
          required: true,
          message: '请输入评判标准对应加减分值',
          trigger: 'blur'
        }, {
          validator: (rule, value, callback) => {
            // 正则表达式:匹配负数、正数、小数;正数的两位数不能以 0 开头
            const regex = /^(-?(\d|[1-9]\d*)(\.\d+)?~(-?(\d|[1-9]\d*)(\.\d+)?)|~)$/;

            if (!regex.test(value)) {
              callback(new Error('分值必须为 X~X 格式,或者单独一个 ~ 字符。X 可以是数字(正数、负数、小数),且正数不能以 0 开头'));
            } else if (value !== '~') {
              // 如果不是单独的 '~',继续检查数值关系
              const [firstX, secondX] = value.split('~').map(Number);

              if (firstX >= secondX) {
                callback(new Error('后面的值必须大于前面的值'));
              } else {
                callback();
              }
            } else {
              callback();
            }
          },
          trigger: 'blur'
        }],
        specialSocre: [{
          required: true,
          message: '特殊评分不能为空',
          trigger: 'change'
        }]
      },
      specialSocreOptions: [{
        "label": "是",
        "value": 1
      }, {
        "label": "否",
        "value": 0
      }],
    }
  },
  computed: {},
  watch: {},
  created() {
  },
  mounted() {
    // 获取组织树
    this.getDeptTree();
  },
  methods: {
    // 查询部门下拉树结构
    getDeptTree() {
      deptTreeSelect().then(response => {
        this.deptOptions = response.data;
      });
    },
    // 添加选项
    addOptions() {
      this.options.push({
        optionKey: this.randomUUID(),
        optionIsHaveChild: 0,
        optionIntroduce: '',
        optionScore: '',
        subOptions: [],
        optionOrder: this.options.length + 1
      });
    },
    // 移除选项
    removeOption(index) {
      this.options.splice(index, 1);
      this.updateOrder();
    },
    // 添加子选项
    addSubOption(index) {
      this.options[index].subOptions.push({
        optionKey: this.randomUUID(),
        optionIntroduce: '',
        optionScore: '',
        optionOrder: this.options[index].subOptions.length + 1
      });
    },
    randomUUID() {
      const hexDigits = '0123456789abcdef';
      let uuid = '';

      for (let i = 0; i < 36; i++) {
        if (i === 8 || i === 13 || i === 18 || i === 23) {
          uuid += '-';
        } else if (i === 14) {
          uuid += '4';
        } else if (i === 19) {
          uuid += hexDigits[(Math.floor(Math.random() * 4) + 8)];
        } else {
          uuid += hexDigits[Math.floor(Math.random() * 16)];
        }
      }
      return uuid;
    },
    // 移除子选项
    removeSubOption(index, subIndex) {
      this.options[index].subOptions.splice(subIndex, 1);
      this.updateSubOrder(index);
    },
    // 打开
    open(title, formData, isViewMode) {
      this.dialogTitle = title;
      this.isViewMode = isViewMode;
      this.formData = {
        ...formData,
        judgeType: String(formData.judgeType || ''),// 转换为字符串
        specialSocre: formData.specialSocre || 0
      };
      // 具体选项赋值
      this.options = Array.isArray(formData.children) ? formData.children : [];
      this.isVisible = true;
      // 获取组织树
      this.getDeptTree();
    },
    // 关闭
    close() {
      this.formData = {}
      this.options = []
      this.deptOptions = []
      this.$refs.elForm.resetFields()
      this.isVisible = false;
      // 刷新表格
      this.$emit('refresh');
    },
    // 提交
    save() {
      // 手动校验嵌套选项
      if (!this.validateNestedOptions()) {
        return;
      }

      this.$refs['elForm'].validate(valid => {
        if (valid) {
          let judgeExplain = this.formData.judgeExplain
          let judgeDesc = this.formData.judgeDesc
          // 判断两个值是否至少有一个不为空
          if (!judgeExplain && !judgeDesc) {
            this.$modal.msgError("评判标准描述和评判标准解释必须有一个不为空!");
            return;
          }

          // 不是特殊评分的时候才有具体选项
          let specialSocre = this.formData.specialSocre;
          // 特殊评分时必须有具体选项
          this.formData.children = this.options
          let children = this.formData.children
          if (specialSocre === 0 && (children === undefined || children.length === 0)) {
            this.$modal.msgError("不是特殊评分,必须有具体选项!");
            return;
          }
          // 不是特殊评分赋值
          if (specialSocre === 1) {
            this.formData.children = []
          }
          addJudge(this.formData).then(response => {
            this.$modal.msgSuccess("新增成功");
            this.close()
          });
        }
      })
    },
    // 修改
    update() {
      // 手动校验嵌套选项
      if (!this.validateNestedOptions()) {
        return;
      }

      this.$refs['elForm'].validate(valid => {
        if (valid) {
          let judgeExplain = this.formData.judgeExplain
          let judgeDesc = this.formData.judgeDesc
          // 判断两个值是否至少有一个不为空
          if (!judgeExplain && !judgeDesc) {
            this.$modal.msgError("评判标准描述和评判标准解释必须有一个不为空!");
            return;
          }

          // 不是特殊评分的时候才有具体选项
          let specialSocre = this.formData.specialSocre;
          // 特殊评分时必须有具体选项
          this.formData.children = this.options
          let children = this.formData.children
          if (specialSocre === 0 && (children === undefined || children.length === 0)) {
            this.$modal.msgError("不是特殊评分,必须有具体选项!");
            return;
          }
          // 不是特殊评分赋值
          if (specialSocre === 1) {
            this.formData.children = []
          }
          updateJudge(this.formData).then(response => {
            this.$modal.msgSuccess("修改成功");
            this.close()
          });
        }
      })
    },
    // 更新选择项顺序
    updateOrder() {
      this.options.forEach((option, index) => {
        option.optionOrder = index + 1;
      });
    },
    // 更新子选择项顺序
    updateSubOrder(index) {
      this.options[index].subOptions.forEach((subOption, subIndex) => {
        subOption.optionOrder = subIndex + 1;
      });
    },
    // 校验选项介绍是否为空
    validateNestedOptions() {
      for (let option of this.options) {
        if (!option.optionIntroduce) {
          this.$modal.msgError("选项介绍不能为空");
          return false;
        }

        if (option.optionIsHaveChild === 1) {
          for (let subOption of option.subOptions) {
            if (!subOption.optionIntroduce) {
              this.$modal.msgError("子选项介绍不能为空");
              return false;
            }
          }
        }
      }
      return true;
    }
  }
}

</script>
<style>
.option-block {
  border: 1px solid #dcdfe6;
  padding: 15px;
  margin-bottom: 10px;
  border-radius: 4px;
}

.sub-option-block {
  border: 1px dashed #dcdfe6;
  padding: 15px;
  margin: 10px 0;
  border-radius: 4px;
}

.input-with-button {
  display: flex;
  align-items: center;
}

.input-with-button .el-input {
  width: 80%;
  margin-right: 10px;
}

.add-button, .remove-button {
  margin-left: 20px;
}

.form-item-with-spacing {
  margin-bottom: 20px !important;
}

.options-container {
  max-height: 650px; /* 根据你的需要调整高度 */
  overflow-y: auto;
  border: 0px solid #dcdfe6; /* 可选:给滚动区域添加边框 */
  padding: 10px; /* 可选:调整内边距 */
}
</style>



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王之蔑视.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值