当前位置 : 主页 > 网络编程 > JavaScript >

vue遍历中存在el-form之踩坑记录

来源:互联网 收集:自由互联 发布时间:2023-02-01
目录 vue遍历存在el-form之踩坑 初版 完善版 抽组件版 vue中el-form循环绑定 vue遍历存在el-form之踩坑 初版 template div class="message-templete-style" div class="title"短信通知模板 el-tooltip popper-class="t
目录
  • vue遍历存在el-form之踩坑
    • 初版
    • 完善版
    • 抽组件版
  • vue中el-form循环绑定

    vue遍历存在el-form之踩坑

    初版

    <template>
      <div class="message-templete-style">
        <div class="title">短信通知模板
          <el-tooltip popper-class="tooltip-style" content="请到阿里云短信平台申请短信权限" placement="bottom">
            <i class="h-icon-help" :offset="85"></i>
          </el-tooltip></div>
        <el-form :model="numberForm" ref="numberForm" :rules="numberFormRule" label-width="100px" class="number-form">
          <el-form-item label="测试手机号" prop="phoneNumber">
            <el-input v-model="numberForm.phoneNumber"></el-input>
          </el-form-item>
          <el-form-item class="btn">
            <el-button type="primary" @click="submitForm">保存</el-button>
          </el-form-item>
        </el-form>
        <el-tabs v-model="activeName" @tab-click="handleClick">
          <el-tab-pane v-for="item in tabList" :key="item.id" :label="item.name|templateTypeFilter " :name="item.name">
            
            <!-- <el-scrollbar wrap-class="scrollbar-wrap"> -->
            <el-row :gutter="12">
              <el-col v-for="(itemCard, index) in item.cardList" :key="itemCard.id" :xs="8" :sm="8" :md="8" :lg="8" :xl="6">
                <div class="card-wrap">
                  <div class="top-style">
                    <div class="card-title">{{ itemCard.templateName }}</div>
                    <el-button type="text" @click="sendMessage(itemCard.templateCode)" :disabled="itemCard.templateCode ? false: true">发送</el-button>
                  </div>
                  <div class="content-style">
                    <div><h4>通知对象</h4> {{ itemCard.notifyParty | notifyPartyFilter }}</div>
                    <div><h4>远程会议</h4> {{ itemCard.remoteMeeting | remoteMeetingFilter }}</div>
                    <div><h4>申请模板</h4> 模板名称/内容
                      <el-popover width="300" trigger="hover" popper-class="detail-pop-style">
                        <p>模板名称 <i class="h-icon-copy" @click="copyText(itemCard.templateName, '名称')"></i></p>
                        <div class="title">{{ itemCard.templateName }}</div>
                        <p>模板内容<i class="h-icon-copy" @click="copyText(itemCard.templateContent, '内容')"></i></p>
                        <!-- \n -->
                        <div style="white-space: pre-wrap;">{{ itemCard.templateContent }}</div>
                        <!-- 
     -->
                        <!-- <div v-html="itemCard.templateContent"></div> -->
                        <i slot="reference" class="h-icon-details"></i>
                      </el-popover>
                    </div>
                    <div class="code-style"><h4>模板code</h4><span class="code-width">{{ itemCard.templateCode || '' }}</span>
                      <el-popover v-model="itemCard.visible" popper-class="code-pop-style">
                        <el-form :model="item" ref="codeForm" label-position="top" class="code-form">
                          <el-form-item label="模板code" :prop="'cardList.' + index + '.templateCodeValue'">
                            <el-input v-model="itemCard.templateCodeValue"></el-input>
                          </el-form-item>
                          <div class="btn-style">
                            <el-button type="primary" @click.native="confirm(index, itemCard)">确定</el-button>
                            <el-button @click="itemCard.visible = false">取消</el-button>
                          </div>
                        </el-form>
                        <i slot="reference" class="h-icon-edit" @click="openInit(itemCard)"></i>
                      </el-popover>
                    </div>
                  </div>
                </div>
              </el-col>
            </el-row>
            <!-- </el-scrollbar> -->
          </el-tab-pane>
        </el-tabs>
      </div>
    </template>
    <script>
    import rules from '@/lib/rules';
    
    export default {
      filters: {
        templateTypeFilter: value => {
          switch (value) {
            case 'MEETING_BEFORE':
              return '会前通知';
            case 'MEETING_DURING':
              return '会中通知';
            case 'MEETING_AFTER':
              return '会后通知';
            case 'NOTICE_TIMING':
              return '定时提醒';
            case 'USER_MANAGEMENT':
              return '用户管理';
            default:
              return;
          }
        },
        remoteMeetingFilter: value => {
          switch (value) {
            case 'YES':
              return '有';
            case 'NO':
              return '无';
            default:
              return;
          }
        },
        notifyPartyFilter: value => {
          switch (value) {
            case 'CC':
              return '抄送人';
            case 'MEMBER':
              return '与会人';
            case 'MEMBER_CC':
              return '与会人和抄送人';
            case 'REGISTRANT':
              return '注册人';
            case 'CREATOR':
              return '发起人';
            default:
              return;
          }
        }
      },
      data() {
        return {
          activeName: 'NOTICE_TIMING', // 当前激活的tab
          successPhoneNumber: '', // 保存成功的测试手机号
          tabList: [
            // {
            //   id: 1,
            //   name: 'hqtz',
            //   cardList: [
            //     {
            //       id: 1,
            //       templateName: '预定会议通知1', // ,模板名称
            //       isSend: true, // 是否发送
            //       notifyParty: '发起人', // 通知对象
            //       remoteMeeting: true, // 是否支持远程会议
            //       templateContent: 'xx', // 模板内容
            //       templateCode: 'cc' // 模板code,
            //       visible: false, // 是否开启弹框
            //     }
            //   ]
            // }, {
            //   id: 2,
            //   name: 'hztz',
            //   cardList: []
            // }, {
            //   id: 3,
            //   name: 'hhtz',
            //   cardList: []
            // }, {
            //   id: 4,
            //   name: 'dstz',
            //   cardList: []
            // }, {
            //   id: 5,
            //   name: 'yhgl',
            //   cardList: []
            // }
          ],
          numberForm: { // 测试手机号
            phoneNumber: ''
          },
          numberFormRule: {
            phoneNumber: [rules.required('phoneNumber'), rules.phoneNumber()]
          }
          // codeFormRule: {
          //   templateCodeValue: [
          //     {
          //       required: true,
          //       message: '请输入模板code'
          //       // trigger: 'blur'
          //     }
          //   ]
          // }
        };
      },
      created() {
        this.getPhoneNumber();
        this.getData();
      },
      methods: {
        // 获取测试手机号
        async getPhoneNumber() {
          const res = await this.$get('meeting/aLiYunSmsSdk/v1/getALiYunSmsTestPhone');
          this.numberForm.phoneNumber = res || '';
          this.successPhoneNumber = res || '';
        },
        // 获取短信模板
        async getData() {
          const res = await this.$get('meeting/template/v1/getSmsTemplateInfo');
          let dataList = res || [];
          const newTabList = dataList.map((item, index) => {
            return {
              id: index + 1,
              name: item.noticePeriodName,
              cardList: item.noticePeriodData ? item.noticePeriodData.map(item_ => {
                return {
                  id: item_.id,
                  templateName: item_.templateName, // 模板名称
                  isSend: true, // 是否发送
                  notifyParty: item_.notifyObject, // 通知对象
                  remoteMeeting: item_.videoConference, // 是否支持远程会议
                  templateContent: item_.templateContent, // 模板内容
                  templateCode: item_.templateCode, // 模板code
                  templateCodeValue: item_.templateCode, // 输入的code
                  visible: false
                };
              }) : []
            };
          });
          console.log(newTabList);
          this.tabList = JSON.parse(JSON.stringify(newTabList));
        },
        // 保存测试手机号
        submitForm() {
          this.$refs.numberForm.validate(async valid => {
            if (valid) {
              const res = await this.$get(`meeting/aLiYunSmsSdk/v1/saveALiYunSmsTestPhone/${this.numberForm.phoneNumber}`);
              this.successPhoneNumber = res || '';
              this.$message({
                message: '手机号保存成功,可用于有code码的模板进行短信测试!',
                type: 'success'
              });
            }
          });
        },
        // 切换tab
        handleClick(tab, event) {
          console.log(tab, event);
        },
        // 发送
        async sendMessage(code) {
          if (!this.successPhoneNumber) {
            return this.$message({
              message: '测试手机号未保存!',
              type: 'warning'
            });
          }
          await this.$get(`meeting/sms/v1/sendSmsTest/${this.successPhoneNumber}/$[code]`);
        },
        // 复制
        copyText(text) {
          console.log(text);//获取input对象
          //创建input标签
          var input = document.createElement('textarea');
          //将input的值设置为需要复制的内容
          input.value = text;
          //添加input标签
          document.body.appendChild(input);
          //选中input标签
          input.select();
          //执行复制
          document.execCommand('copy');
          //成功提示信息
          this.$message({
            message: '已复制成功!',
            type: 'success'
          });
          //移除input标签
          document.body.removeChild(input);
        },
        // 开启code弹框
        openInit(item) {
          item.templateCodeValue = item.templateCode;
        },
        // 确认code
        async confirm(index, item) {
          console.log(index, Boolean(item.templateCodeValue));
          if (!item.templateCodeValue) {
            return this.$message({
              message: '模板code不能为空!',
              type: 'warning'
            });
          }
          if (item.templateCodeValue) {
            await this.$get(`meeting/template/v1/bindingSmsTemplateCode/${item.id}/${item.templateCodeValue}`);
            item.templateCode = item.templateCodeValue;
            item.visible = false;
          }
    
          this.$refs.codeForm[index].focusFirstField();
        }
        // this.$refs.codeForm[index].validate(async valid => {
        //   if (valid) {
        //     console.log(valid);
        //     console.log(item);
        //     await this.$get(`meeting/template/v1/bindingSmsTemplateCode/${item.id}/${item.templateCodeValue}`);
        //     item.templateCode = item.templateCodeValue;
        //     item.visible = false;
        //   }
        // });
        // }
        
      }
    };
    </script>
    
    <style lang="less">
    .message-templete-style {
      height: 100%;
      // background: rgb(253, 243, 243);
      overflow: hidden;
    
      .title{
        font-size: 16px;
        color:#000000;
        font-weight: 900;
        padding-bottom: 10px;
    
        .h-icon-help{
          position: absolute;
          font-size: 26px;
          cursor: pointer;
          padding-left:2px;
          margin-top:-3px;
        }
      }
    
      .number-form{
        height:64px;
        padding-top:12px;
        background: #F7F8F9;
        border-radius: 2px;
        display: flex;
        .el-form-item{
          margin-bottom: 20px;
        }
        .btn .el-form-item__content{
          margin-left: 10px !important;
        }
      }
    
      .el-tabs{
        height: calc(100% - 94px);
        // background: #2080F7;
        padding-top:12px;
    
    
        // .scrollbar-wrap{
        //   // max-height: 700px;
        // }
    
        .el-tabs__item{
          padding:0px 32px;
          span{
            opacity: 0.7;
            font-size: 14px;
          }
        }
        .el-tabs__item.is-active{
          color: #000000;
          font-weight: 900;
        }
        .el-tabs__item:hover{
          color: #000000;
          font-weight: 900;
        }
        .el-tabs__active-bar{
          background-color: #2080F7;
        }
    
        .el-tabs__header{
          padding-bottom: 10px;
        }
        .el-tabs__content{
          height:calc(100% - 51px);
          // background: #e8eef5;
          overflow: auto;
    
          // 重置滚动条位置
          &::-webkit-scrollbar {
            width: 4px;
            height: 3px;
            background: transparent;
          }
          &::-webkit-scrollbar-thumb {
            background: transparent;
            border-radius: 4px;
          }
          &:hover::-webkit-scrollbar-thumb {
            background: hsla(0, 0%, 53%, 0.5);
          }
          &:hover::-webkit-scrollbar-track {
            background: hsla(0, 0%, 53%, 0);
          }
    
          .el-col{
            margin-bottom: 12px;
          }
    
          .card-wrap{
            padding: 16px 20px;
            background: #F7F8F9;
            border-radius: 2px;
            .top-style{
              display: flex;
              justify-content: space-between;
              align-items: center;
              font-size: 14px;
              font-weight: 900;
              line-height: 14px;
              padding-bottom: 20px;
              .card-title{
                color: #000000;
              }
              .el-button {
                border: 0px;
                height:16px;
                margin-top:-4px;
                span{
                  line-height: 14px;
                  font-size: 14px;
                  color:#2080F7;
                }
              }
            }
            .content-style{
              div{
                position: relative;
                opacity: 0.9;
                font-size: 14px;
                color: #000000;
                line-height: 24px;
                h4{
                  display: inline-block;
                  opacity: 0.5;
                  font-size: 14px;
                  color: #000000;
                  line-height: 24px;
                  padding-right:16px;
                  font-weight: normal;
                }
    
                .h-icon-details, .h-icon-edit{
                  position: absolute;
                  font-size: 22px;
                  cursor: pointer;
                  padding-left:8px;
                }
    
                .h-icon-edit{
                  margin-top:-12px;
                }
              }
              .code-style{
                display: flex;
                align-items: center;
                .code-width{
                  max-width:calc(100% - 104px);
                  text-overflow: ellipsis;
                  overflow: hidden;
                  white-space: nowrap;
                  
                  line-height: 14px;
                  font-size: 14px;
                  font-weight: normal;
                }
              }
            }
          }
        }
      }
    }
    .detail-pop-style{
      background: #FFFFFF;
      box-shadow: 0 0 16px 0 rgba(0,0,0,0.20), 0 16px 32px 0 rgba(0,0,0,0.12);
      p{
        position: relative;
        font-weight: 900;
        font-size: 14px;
        line-height: 14px;
        color: #000000;
        padding-bottom: 8px;
    
        .h-icon-copy{
          color:#1C7FFF;
          position: absolute;
          font-size: 20px;
          cursor: pointer;
          padding-left:4px;
          margin-top:-3px;
        }
      }
      .title{
        padding-bottom:16px;
      }
      div{
        font-size: 14px;
        color: rgba(0,0,0,0.50);
        line-height: 24px;
      }
    }
    
    .code-pop-style{
      background: #FFFFFF;
      box-shadow: 0 0 16px 0 rgba(0,0,0,0.20), 0 16px 32px 0 rgba(0,0,0,0.12);
      .el-form-item__content{
        margin-left:0px;
      }
    
      .btn-style{
        float: right;
      }
    }
    .tooltip-style{
      background: #000000;
    }
    </style>

    完善版

    <template>
      <div class="message-templete-style">
        <div class="title">短信通知模板
          <el-tooltip popper-class="tooltip-style" content="请到阿里云短信平台申请短信权限" placement="bottom">
            <i class="h-icon-help" :offset="85"></i>
          </el-tooltip></div>
        <el-form :model="numberForm" ref="numberForm" :rules="numberFormRule" label-width="100px" class="number-form">
          <el-form-item label="测试手机号" prop="phoneNumber">
            <el-input v-model="numberForm.phoneNumber"></el-input>
          </el-form-item>
          <el-form-item class="btn">
            <el-button type="primary" @click="submitForm">保存</el-button>
          </el-form-item>
        </el-form>
        <el-tabs v-model="activeName" @tab-click="handleClick">
          <!-- tab头部 -->
          <el-tab-pane v-for="item in tabList" :key="item.key" :label="item.label|templateTypeFilter " :name="item.label"></el-tab-pane>
          <!-- tab内容 -->
          <el-row :gutter="12">
            <el-col v-for="(itemCard) in templateList" :key="itemCard.id" :xs="8" :sm="8" :md="8" :lg="8" :xl="6">
              <div class="card-wrap">
                <div class="top-style">
                  <div class="card-title">{{ itemCard.templateName }}</div>
                  <el-button type="text" @click="sendMessage(itemCard.templateCode)" :disabled="itemCard.templateCode ? false: true">发送</el-button>
                </div>
                <div class="content-style">
                  <div><h4>通知对象</h4> {{ itemCard.notifyParty | notifyPartyFilter }}</div>
                  <div><h4>远程会议</h4> {{ itemCard.remoteMeeting | remoteMeetingFilter }}</div>
                  <div><h4>申请模板</h4> 模板名称/内容
                    <el-popover width="300" trigger="hover" popper-class="detail-pop-style">
                      <p>模板名称 <i class="h-icon-copy" @click="copyText(itemCard.templateName, '名称')"></i></p>
                      <div class="title">{{ itemCard.templateName }}</div>
                      <p>模板内容<i class="h-icon-copy" @click="copyText(itemCard.templateContent, '内容')"></i></p>
                      <div style="white-space: pre-wrap;">{{ itemCard.templateContent }}</div>
                      <i slot="reference" class="h-icon-details"></i>
                    </el-popover>
                  </div>
                  <div class="code-style"><h4>模板code</h4><span class="code-width">{{ itemCard.templateCode || '' }}</span>
                    <el-popover v-model="itemCard.visible" popper-class="code-pop-style">
                      <el-form :model="itemCard" :ref="itemCard.id" label-position="top" class="code-form">
                        <el-form-item label="模板code" prop="templateCodeValue" :rules="codeFormRule.templateCodeValue">
                          <el-input v-model="itemCard.templateCodeValue"></el-input>
                        </el-form-item>
                        <div class="btn-style">
                          <el-button type="primary" @click="confirm(itemCard)">确定</el-button>
                          <el-button @click="itemCard.visible = false">取消</el-button>
                        </div>
                      </el-form>
                      <i slot="reference" class="h-icon-edit" @click="openInit(itemCard)"></i>
                    </el-popover>
                  </div>
                </div>
              </div>
            </el-col>
          </el-row>
        </el-tabs>
      </div>
    </template>
    
    <script>
    import rules from '@/lib/rules';
    
    export default {
      filters: {
        templateTypeFilter: value => {
          switch (value) {
            case 'MEETING_BEFORE':
              return '会前通知';
            case 'MEETING_DURING':
              return '会中通知';
            case 'MEETING_AFTER':
              return '会后通知';
            case 'NOTICE_TIMING':
              return '定时提醒';
            case 'USER_MANAGEMENT':
              return '用户管理';
            default:
              return;
          }
        },
        remoteMeetingFilter: value => {
          switch (value) {
            case 'YES':
              return '有';
            case 'NO':
              return '无';
            default:
              return;
          }
        },
        notifyPartyFilter: value => {
          switch (value) {
            case 'CC':
              return '抄送人';
            case 'MEMBER':
              return '与会人';
            case 'MEMBER_CC':
              return '与会人和抄送人';
            case 'REGISTRANT':
              return '注册人';
            case 'CREATOR':
              return '发起人';
            default:
              return;
          }
        }
      },
      data() {
        return {
          activeName: 'NOTICE_TIMING', // 当前激活的tab
          successPhoneNumber: '', // 保存成功的测试手机号
          tabList: [  // 获取的所有数据 重组数据结构如下:
            // {
            //   key: 1,
            //   label: 'MEETING_AFTER',
            //   contentList: []
            // },
            // {
            //   key: 2,
            //   label: 'MEETING_BEFORE',
            //   contentList: []
            // },
            // {
            //   key: 3,
            //   label: 'MEETING_DURING',
            //   contentList: []
            // },
            // {
            //   key: 4,
            //   label: 'NOTICE_TIMING',
            //   contentList: []
            // },
            // {
            //   key: 5,
            //   label: 'USER_MANAGEMENT',
            //   contentList: []
            // }
          ],
          templateList: [], // 要渲染的模板列表
    
          numberForm: {  // 测试手机号
            phoneNumber: ''
          },
          numberFormRule: { // 测试手机号校验
            phoneNumber: [rules.required('phoneNumber'), rules.phoneNumber()]
          },
          codeFormRule: { // 模板code校验
            templateCodeValue: [
              // rules.required('templateCodeValue')
              {
                required: true,
                message: '请输入模板code'
                // trigger: 'blur'
              }
            ]
          }
        };
      },
      created() {
        this.getPhoneNumber();
        this.getData();
      },
      methods: {
        // 获取测试手机号
        async getPhoneNumber() {
          const res = await this.$get('meeting/aLiYunSmsSdk/v1/getALiYunSmsTestPhone');
          this.numberForm.phoneNumber = res || '';
          this.successPhoneNumber = res || '';
        },
        // 获取短信模板
        async getData() {
          const res = await this.$get('meeting/template/v1/getSmsTemplateInfo');
          let dataList = res || [];
          const newTabList = dataList.map((item, index) => {
            return {
              key: index + 1,
              label: item.noticePeriodName,
              contentList: item.noticePeriodData ? item.noticePeriodData.map(item_ => {
                return {
                  id: item_.id,
                  templateName: item_.templateName, // 模板名称
                  isSend: true, // 是否发送
                  notifyParty: item_.notifyObject, // 通知对象
                  remoteMeeting: item_.videoConference, // 是否支持远程会议
                  templateContent: item_.templateContent, // 模板内容
                  templateCode: item_.templateCode, // 模板code
                  templateCodeValue: item_.templateCode, // 双向绑定的code
                  visible: false
                };
              }) : []
            };
          });
    
          this.tabList = JSON.parse(JSON.stringify(newTabList));
          this.templateList = newTabList[0] ? JSON.parse(JSON.stringify(newTabList))[0].contentList : [];
        },
        // 保存测试手机号
        submitForm() {
          this.$refs.numberForm.validate(async valid => {
            if (valid) {
              const res = await this.$get(`meeting/aLiYunSmsSdk/v1/saveALiYunSmsTestPhone/${this.numberForm.phoneNumber}`);
              this.successPhoneNumber = res || '';
              this.$message({
                message: '手机号保存成功,可用于有code码的模板进行短信测试!',
                type: 'success'
              });
            }
          });
        },
        // 切换tab (按理此处可以通过接口获取,因为数据少,所以后端一次性返回,前端自行处理)
        handleClick(tab) {
          const newArr = JSON.parse(JSON.stringify(this.tabList));
          let newTemplateList = JSON.parse(JSON.stringify(this.templateList));
    
          for (let i = 0; i < newArr.length; i++) {
            if (newArr[i].label === tab.name) {
              newTemplateList = newArr[i].contentList;
            }
          }
    
          this.templateList = newTemplateList;
        },
        // 发送
        async sendMessage(code) {
          if (!this.successPhoneNumber) {
            return this.$message({
              message: '测试手机号未保存!',
              type: 'warning'
            });
          }
          await this.$get(`meeting/sms/v1/sendSmsTest/${this.successPhoneNumber}/$[code]`);
        },
        // 复制
        copyText(text) {
          console.log(text);//获取input对象
          //创建input标签
          var input = document.createElement('textarea');
          //将input的值设置为需要复制的内容
          input.value = text;
          //添加input标签
          document.body.appendChild(input);
          //选中input标签
          input.select();
          //执行复制
          document.execCommand('copy');
          //成功提示信息
          this.$message({
            message: '已复制成功!',
            type: 'success'
          });
          //移除input标签
          document.body.removeChild(input);
        },
        // 开启code弹框
        openInit(item) {
          item.templateCodeValue = item.templateCode;
        },
        // 确认code
        async confirm(item) {
          this.$refs[item.id][0].validate(async valid => {
            if (valid) {
              await this.$get(`meeting/template/v1/bindingSmsTemplateCode/${item.id}/${item.templateCodeValue}`);
              item.templateCode = item.templateCodeValue;
              item.visible = false;
            }
          });
        }
      }
    };
    </script>
    <style lang="less">
    .message-templete-style {
      height: 100%;
      // background: rgb(253, 243, 243);
      overflow: hidden;
    
      .title{
        font-size: 16px;
        color:#000000;
        font-weight: 900;
        padding-bottom: 10px;
    
        .h-icon-help{
          position: absolute;
          font-size: 26px;
          cursor: pointer;
          padding-left:2px;
          margin-top:-3px;
        }
      }
    
      .number-form{
        height:64px;
        padding-top:12px;
        background: #F7F8F9;
        border-radius: 2px;
        display: flex;
        .el-form-item{
          margin-bottom: 20px;
        }
        .btn .el-form-item__content{
          margin-left: 10px !important;
        }
      }
    
      .el-tabs{
        height: calc(100% - 94px);
        // background: #2080F7;
        padding-top:12px;
    
        .el-tabs__item{
          padding:0px 32px;
          span{
            opacity: 0.7;
            font-size: 14px;
          }
        }
        .el-tabs__item.is-active{
          color: #000000;
          font-weight: 900;
        }
        .el-tabs__item:hover{
          color: #000000;
          font-weight: 900;
        }
        .el-tabs__active-bar{
          background-color: #2080F7;
        }
    
        .el-tabs__header{
          padding-bottom: 10px;
        }
        .el-tabs__content{
          height:calc(100% - 51px);
          // background: #e8eef5;
          overflow: auto;
    
          // 重置滚动条位置
          &::-webkit-scrollbar {
            width: 4px;
            height: 3px;
            background: transparent;
          }
          &::-webkit-scrollbar-thumb {
            background: transparent;
            border-radius: 4px;
          }
          &:hover::-webkit-scrollbar-thumb {
            background: hsla(0, 0%, 53%, 0.5);
          }
          &:hover::-webkit-scrollbar-track {
            background: hsla(0, 0%, 53%, 0);
          }
    
          .el-col{
            margin-bottom: 12px;
          }
    
          .card-wrap{
            padding: 16px 20px;
            background: #F7F8F9;
            border-radius: 2px;
            .top-style{
              display: flex;
              justify-content: space-between;
              align-items: center;
              font-size: 14px;
              font-weight: 900;
              line-height: 14px;
              padding-bottom: 20px;
              .card-title{
                color: #000000;
              }
              .el-button {
                border: 0px;
                height:16px;
                margin-top:-4px;
                span{
                  line-height: 14px;
                  font-size: 14px;
                  color:#2080F7;
                }
              }
            }
            .content-style{
              div{
                position: relative;
                opacity: 0.9;
                font-size: 14px;
                color: #000000;
                line-height: 24px;
                h4{
                  display: inline-block;
                  opacity: 0.5;
                  font-size: 14px;
                  color: #000000;
                  line-height: 24px;
                  padding-right:16px;
                  font-weight: normal;
                }
    
                .h-icon-details, .h-icon-edit{
                  position: absolute;
                  font-size: 22px;
                  cursor: pointer;
                  padding-left:8px;
                }
    
                .h-icon-edit{
                  margin-top:-12px;
                }
              }
              .code-style{
                display: flex;
                align-items: center;
                .code-width{
                  max-width:calc(100% - 104px);
                  text-overflow: ellipsis;
                  overflow: hidden;
                  white-space: nowrap;
                  
                  line-height: 14px;
                  font-size: 14px;
                  font-weight: normal;
                }
              }
            }
          }
        }
      }
    }
    .detail-pop-style{
      background: #FFFFFF;
      box-shadow: 0 0 16px 0 rgba(0,0,0,0.20), 0 16px 32px 0 rgba(0,0,0,0.12);
      p{
        position: relative;
        font-weight: 900;
        font-size: 14px;
        line-height: 14px;
        color: #000000;
        padding-bottom: 8px;
    
        .h-icon-copy{
          color:#1C7FFF;
          position: absolute;
          font-size: 20px;
          cursor: pointer;
          padding-left:4px;
          margin-top:-3px;
        }
      }
      .title{
        padding-bottom:16px;
      }
      div{
        font-size: 14px;
        color: rgba(0,0,0,0.50);
        line-height: 24px;
      }
    }
    
    .code-pop-style{
      background: #FFFFFF;
      box-shadow: 0 0 16px 0 rgba(0,0,0,0.20), 0 16px 32px 0 rgba(0,0,0,0.12);
      .el-form-item__content{
        margin-left:0px;
      }
    
      .btn-style{
        float: right;
      }
    }
    .tooltip-style{
      background: #000000;
    }
    </style>

    抽组件版

    父组件:
    <template>
      <div class="message-templete-style">
        <div class="title">短信通知模板
          <el-tooltip popper-class="tooltip-style" content="请到阿里云短信平台申请短信权限" placement="bottom">
            <i class="h-icon-help" :offset="85"></i>
          </el-tooltip></div>
        <el-form :model="numberForm" ref="numberForm" :rules="numberFormRule" label-width="100px" class="number-form">
          <el-form-item label="测试手机号" prop="phoneNumber">
            <el-input v-model="numberForm.phoneNumber"></el-input>
          </el-form-item>
          <el-form-item class="btn">
            <el-button type="primary" @click="submitForm">保存</el-button>
          </el-form-item>
        </el-form>
        <el-tabs v-model="activeName" @tab-click="handleClick">
          <!-- tab头部 -->
          <el-tab-pane v-for="item in tabList" :key="item.key" :label="item.label|templateTypeFilter " :name="item.label"></el-tab-pane>
          <!-- tab内容 -->
          <el-row :gutter="12">
            <el-col v-for="(itemCard) in templateList" :key="itemCard.id" :xs="8" :sm="8" :md="8" :lg="8" :xl="6">
              <template-card :success-phone-number="successPhoneNumber" :item-card="itemCard"></template-card>
              <!-- <div class="card-wrap">
                <div class="top-style">
                  <div class="card-title">{{ itemCard.templateName }}</div>
                  <el-button type="text" @click="sendMessage(itemCard.templateCode)" :disabled="itemCard.templateCode ? false: true">发送</el-button>
                </div>
                <div class="content-style">
                  <div><h4>通知对象</h4> {{ itemCard.notifyParty | notifyPartyFilter }}</div>
                  <div><h4>远程会议</h4> {{ itemCard.remoteMeeting | remoteMeetingFilter }}</div>
                  <div><h4>申请模板</h4> 模板名称/内容
                    <el-popover width="300" trigger="hover" popper-class="detail-pop-style">
                      <p>模板名称 <i class="h-icon-copy" @click="copyText(itemCard.templateName, '名称')"></i></p>
                      <div class="title">{{ itemCard.templateName }}</div>
                      <p>模板内容<i class="h-icon-copy" @click="copyText(itemCard.templateContent, '内容')"></i></p>
                      <div style="white-space: pre-wrap;">{{ itemCard.templateContent }}</div>
                      <i slot="reference" class="h-icon-details"></i>
                    </el-popover>
                  </div>
                  <div class="code-style"><h4>模板code</h4><span class="code-width">{{ itemCard.templateCode || '' }}</span>
                    <el-popover v-model="itemCard.visible" popper-class="code-pop-style">
                      <el-form :model="itemCard" :ref="itemCard.id" label-position="top" class="code-form">
                        <el-form-item label="模板code" prop="templateCodeValue" :rules="codeFormRule.templateCodeValue">
                          <el-input v-model="itemCard.templateCodeValue"></el-input>
                        </el-form-item>
                        <div class="btn-style">
                          <el-button type="primary" @click="confirm(itemCard)">确定</el-button>
                          <el-button @click="itemCard.visible = false">取消</el-button>
                        </div>
                      </el-form>
                      <i slot="reference" class="h-icon-edit" @click="openInit(itemCard)"></i>
                    </el-popover>
                  </div>
                </div>
              </div> -->
            </el-col>
          </el-row>
        </el-tabs>
      </div>
    </template>
    <script>
    import rules from '@/lib/rules';
    import templateCard from '@/components/view/SettingManage/templateCard.vue';
    export default {
      components: {
        templateCard
      },
      filters: {
        templateTypeFilter: value => {
          switch (value) {
            case 'MEETING_BEFORE':
              return '会前通知';
            case 'MEETING_DURING':
              return '会中通知';
            case 'MEETING_AFTER':
              return '会后通知';
            case 'NOTICE_TIMING':
              return '定时提醒';
            case 'USER_MANAGEMENT':
              return '用户管理';
            default:
              return;
          }
        }
      },
      data() {
        return {
          activeName: 'NOTICE_TIMING', // 当前激活的tab
          successPhoneNumber: '', // 保存成功的测试手机号
          tabList: [  // 获取的所有数据 重组数据结构如下:
            // {
            //   key: 1,
            //   label: 'MEETING_AFTER',
            //   contentList: []
            // },
            // {
            //   key: 2,
            //   label: 'MEETING_BEFORE',
            //   contentList: []
            // },
            // {
            //   key: 3,
            //   label: 'MEETING_DURING',
            //   contentList: []
            // },
            // {
            //   key: 4,
            //   label: 'NOTICE_TIMING',
            //   contentList: []
            // },
            // {
            //   key: 5,
            //   label: 'USER_MANAGEMENT',
            //   contentList: []
            // }
          ],
          templateList: [], // 要渲染的模板列表
    
          numberForm: {  // 测试手机号
            phoneNumber: ''
          },
          numberFormRule: { // 测试手机号校验
            phoneNumber: [rules.required('phoneNumber'), rules.phoneNumber()]
          },
          codeFormRule: { // 模板code校验
            templateCodeValue: [
              // rules.required('templateCodeValue')
              {
                required: true,
                message: '请输入模板code'
                // trigger: 'blur'
              }
            ]
          }
        };
      },
      created() {
        this.getPhoneNumber();
        this.getData();
      },
      methods: {
        // 获取测试手机号
        async getPhoneNumber() {
          const res = await this.$get('meeting/aLiYunSmsSdk/v1/getALiYunSmsTestPhone');
          this.numberForm.phoneNumber = res || '';
          this.successPhoneNumber = res || '';
        },
        // 获取短信模板
        async getData() {
          const res = await this.$get('meeting/template/v1/getSmsTemplateInfo');
          let dataList = res || [];
          const newTabList = dataList.map((item, index) => {
            return {
              key: index + 1,
              label: item.noticePeriodName,
              contentList: item.noticePeriodData ? item.noticePeriodData.map(item_ => {
                return {
                  id: item_.id,
                  templateName: item_.templateName, // 模板名称
                  isSend: true, // 是否发送
                  notifyParty: item_.notifyObject, // 通知对象
                  remoteMeeting: item_.videoConference, // 是否支持远程会议
                  templateContent: item_.templateContent, // 模板内容
                  templateCode: item_.templateCode, // 模板code
                  templateCodeValue: item_.templateCode, // 双向绑定的code
                  visible: false
                };
              }) : []
            };
          });
    
          this.tabList = JSON.parse(JSON.stringify(newTabList));
          this.templateList = newTabList[0] ? JSON.parse(JSON.stringify(newTabList))[0].contentList : [];
        },
        // 保存测试手机号
        submitForm() {
          this.$refs.numberForm.validate(async valid => {
            if (valid) {
              const res = await this.$get(`meeting/aLiYunSmsSdk/v1/saveALiYunSmsTestPhone/${this.numberForm.phoneNumber}`);
              this.successPhoneNumber = res || '';
              this.$message({
                message: '手机号保存成功,可用于有code码的模板进行短信测试!',
                type: 'success'
              });
            }
          });
        },
        // 切换tab (按理此处可以通过接口获取,因为数据少,所以后端一次性返回,前端自行处理)
        handleClick(tab) {
          const newArr = JSON.parse(JSON.stringify(this.tabList));
          let newTemplateList = JSON.parse(JSON.stringify(this.templateList));
    
          for (let i = 0; i < newArr.length; i++) {
            if (newArr[i].label === tab.name) {
              newTemplateList = newArr[i].contentList;
            }
          }
    
          this.templateList = newTemplateList;
        }
      }
    };
    </script>
    <style lang="less" scoped>
    .message-templete-style {
      height: 100%;
      // background: rgb(253, 243, 243);
      overflow: hidden;
    
      .title{
        font-size: 16px;
        color:#000000;
        font-weight: 900;
        padding-bottom: 10px;
    
        .h-icon-help{
          position: absolute;
          font-size: 26px;
          cursor: pointer;
          padding-left:2px;
          margin-top:-3px;
        }
      }
    
      .number-form{
        height:64px;
        padding-top:12px;
        background: #F7F8F9;
        border-radius: 2px;
        display: flex;
        .el-form-item{
          margin-bottom: 20px;
        }
        .btn .el-form-item__content{
          margin-left: 10px !important;
        }
      }
    
      .el-tabs{
        height: calc(100% - 94px);
        // background: #2080F7;
        padding-top:12px;
    
        .el-tabs__item{
          padding:0px 32px;
          span{
            opacity: 0.7;
            font-size: 14px;
          }
        }
        .el-tabs__item.is-active{
          color: #000000;
          font-weight: 900;
        }
        .el-tabs__item:hover{
          color: #000000;
          font-weight: 900;
        }
        .el-tabs__active-bar{
          background-color: #2080F7;
        }
    
        .el-tabs__header{
          padding-bottom: 10px;
        }
        .el-tabs__content{
          height:calc(100% - 51px);
          // background: #e8eef5;
          overflow: auto;
    
          // 重置滚动条位置
          &::-webkit-scrollbar {
            width: 4px;
            height: 3px;
            background: transparent;
          }
          &::-webkit-scrollbar-thumb {
            background: transparent;
            border-radius: 4px;
          }
          &:hover::-webkit-scrollbar-thumb {
            background: hsla(0, 0%, 53%, 0.5);
          }
          &:hover::-webkit-scrollbar-track {
            background: hsla(0, 0%, 53%, 0);
          }
    
          .el-col{
            margin-bottom: 12px;
          }
        }
      }
    }
    .tooltip-style{
      background: #000000;
    }
    </style>
    ```javascript
    子组件:
    <template>
      <div class="card-wrap">
        <div class="top-style">
          <div class="card-title">{{ itemCard.templateName }}</div>
          <el-button type="text" @click="sendMessage(itemCard.templateCode)" :disabled="itemCard.templateCode ? false: true">发送</el-button>
        </div>
        <div class="content-style">
          <div><h4>通知对象</h4> {{ itemCard.notifyParty | notifyPartyFilter }}</div>
          <div><h4>远程会议</h4> {{ itemCard.remoteMeeting | remoteMeetingFilter }}</div>
          <div><h4>申请模板</h4> 模板名称/内容
            <el-popover width="300" trigger="hover" popper-class="detail-pop-style">
              <p>模板名称 <i class="h-icon-copy" @click="copyText(itemCard.templateName, '名称')"></i></p>
              <div class="title">{{ itemCard.templateName }}</div>
              <p>模板内容<i class="h-icon-copy" @click="copyText(itemCard.templateContent, '内容')"></i></p>
              <div style="white-space: pre-wrap;">{{ itemCard.templateContent }}</div>
              <i slot="reference" class="h-icon-details"></i>
            </el-popover>
          </div>
          <div class="code-style"><h4>模板code</h4><span class="code-width">{{ itemCard.templateCode || '' }}</span>
            <el-popover v-model="itemCard.visible" popper-class="code-pop-style">
              <el-form :model="itemCard" :ref="itemCard.id" label-position="top" class="code-form">
                <el-form-item label="模板code" prop="templateCodeValue" :rules="codeFormRule.templateCodeValue">
                  <el-input v-model="itemCard.templateCodeValue"></el-input>
                </el-form-item>
                <div class="btn-style">
                  <el-button type="primary" @click="confirm(itemCard)">确定</el-button>
                  <el-button @click="itemCard.visible = false">取消</el-button>
                </div>
              </el-form>
              <i slot="reference" class="h-icon-edit" @click="openInit(itemCard)"></i>
            </el-popover>
          </div>
        </div>
      </div>
    </template>
    <script>
    export default {
      filters: {
        remoteMeetingFilter: value => {
          switch (value) {
            case 'YES':
              return '有';
            case 'NO':
              return '无';
            default:
              return;
          }
        },
        notifyPartyFilter: value => {
          switch (value) {
            case 'CC':
              return '抄送人';
            case 'MEMBER':
              return '与会人';
            case 'MEMBER_CC':
              return '与会人和抄送人';
            case 'REGISTRANT':
              return '注册人';
            case 'CREATOR':
              return '发起人';
            default:
              return;
          }
        }
      },
      props: {
        successPhoneNumber: {
          type: String,
          default: ''
        },
        itemCard: {
          type: Object,
          default: () => ({})
        }
      },
      data() {
        return {
          codeFormRule: { // 模板code校验
            templateCodeValue: [
              // rules.required('templateCodeValue')
              {
                required: true,
                message: '请输入模板code'
                // trigger: 'blur'
              }
            ]
          }
        };
      },
      methods: {
      // 发送
        async sendMessage(code) {
          if (!this.successPhoneNumber) {
            return this.$message({
              message: '测试手机号未保存!',
              type: 'warning'
            });
          }
          await this.$get(`meeting/sms/v1/sendSmsTest/${this.successPhoneNumber}/$[code]`);
        },
        // 复制
        copyText(text) {
          console.log(text);//获取input对象
          //创建input标签
          var input = document.createElement('textarea');
          //将input的值设置为需要复制的内容
          input.value = text;
          //添加input标签
          document.body.appendChild(input);
          //选中input标签
          input.select();
          //执行复制
          document.execCommand('copy');
          //成功提示信息
          this.$message({
            message: '已复制成功!',
            type: 'success'
          });
          //移除input标签
          document.body.removeChild(input);
        },
        // 开启code弹框
        openInit(item) {
          item.templateCodeValue = item.templateCode;
        },
        // 确认code
        confirm(item) {
          this.$refs[item.id].validate(async valid => {
            if (valid) {
              await this.$get(`meeting/template/v1/bindingSmsTemplateCode/${item.id}/${item.templateCodeValue}`);
              item.templateCode = item.templateCodeValue;
              item.visible = false;
            }
          });
        }
      }
    };
    </script>
    <style lang='less' scoped>
    .card-wrap{
      padding: 16px 20px;
      background: #F7F8F9;
      border-radius: 2px;
      .top-style{
        display: flex;
        justify-content: space-between;
        align-items: center;
        font-size: 14px;
        font-weight: 900;
        line-height: 14px;
        padding-bottom: 20px;
        .card-title{
          color: #000000;
        }
        /deep/.el-button {
          border: 0px;
          height:16px;
          margin-top:-4px;
          span{
            line-height: 14px;
            font-size: 14px;
            color:#2080F7;
          }
        }
      }
      .content-style{
        div{
          position: relative;
          opacity: 0.9;
          font-size: 14px;
          color: #000000;
          line-height: 24px;
          h4{
            display: inline-block;
            opacity: 0.5;
            font-size: 14px;
            color: #000000;
            line-height: 24px;
            padding-right:16px;
            font-weight: normal;
          }
    
          .h-icon-details, .h-icon-edit{
            position: absolute;
            font-size: 22px;
            cursor: pointer;
            padding-left:8px;
          }
    
          .h-icon-edit{
            margin-top:-12px;
          }
        }
        .code-style{
          display: flex;
          align-items: center;
          .code-width{
            max-width:calc(100% - 104px);
            text-overflow: ellipsis;
            overflow: hidden;
            white-space: nowrap;
            
            line-height: 14px;
            font-size: 14px;
            font-weight: normal;
          }
        }
      }
    }
    
    .detail-pop-style{
      background: #FFFFFF;
      box-shadow: 0 0 16px 0 rgba(0,0,0,0.20), 0 16px 32px 0 rgba(0,0,0,0.12);
      p{
        position: relative;
        font-weight: 900;
        font-size: 14px;
        line-height: 14px;
        color: #000000;
        padding-bottom: 8px;
    
        .h-icon-copy{
          color:#1C7FFF;
          position: absolute;
          font-size: 20px;
          cursor: pointer;
          padding-left:4px;
          margin-top:-3px;
        }
      }
      .title{
        padding-bottom:16px;
      }
      div{
        font-size: 14px;
        color: rgba(0,0,0,0.50);
        line-height: 24px;
      }
    }
    
    .code-pop-style{
      background: #FFFFFF;
      box-shadow: 0 0 16px 0 rgba(0,0,0,0.20), 0 16px 32px 0 rgba(0,0,0,0.12);
      .code-form{
        /deep/ .el-form-item__content{
          margin-left:0px;
        }
        .btn-style{
          float: right;
        }
      }
    
    }
    </style>

    vue中el-form循环绑定

    在我们开发过程中,有时会遇到el-form循环绑定校验,并且后台返回的是动态表单list的形式,并且动态绑定是否必填

    <el-form
    	ref="addForm"
    	:model="submitForm"   //绑定的表单对象
    	label-width="125px"
        :rules="rules"		  //绑定的校验规则
    
    >
    	<el-form-item v-for="(item,index) in formArr" :key="index" :label="item.fieldName + ' : ' " :required="item.isRequired==1?true:false" :prop="item.fieldIdentify">
    		<el-input v-if="item.fieldIdentify=='AAA'" style="width:100%;color:#DBDBDD;" type="text" v-model="submitForm.AAA"></el-input>
    		<el-input v-if="item.fieldIdentify=='BBB'" style="width:100%;color:#DBDBDD;" type="text" v-model="submitForm.BBB"></el-input>
    		<el-input v-if="item.fieldIdentify=='CCC'" style="width:100%;color:#DBDBDD;" type="text" v-model="submitForm.CCC"></el-input>
    		<el-form-item  class="textarea form_textarea" v-if="item.fieldIdentify=='DDD'" :prop="item.fieldIdentify">
    			<el-input style="width:650px;" type="textarea" v-model="submitForm.DDD"></el-input>
            </el-form-item>
    	</el-form-item>
    
    </el-form>
    <script>
    	export default {
    		data(){
    			return{
    				submitForm:{
    					AAA:'',
    					BBB:'',
    					CCC:'',
    					DDD:''
    				},
    				//formArr数据类似
    				formArr:[
    					{
    						fieldIdentify: "xxx",
    						fieldName: "xxx",
    						fieldValue: "xxx",
    						isRequired: 1
    					},
    					{
    						fieldIdentify: "xxx",
    						fieldName: "xxx",
    						fieldValue: "xxx",
    						isRequired: 1
    					},
    					{
    						fieldIdentify: "xxx",
    						fieldName: "xxx",
    						fieldValue: "xxx",
    						isRequired: 1
    					}
    				],
    				//注意在el-form-item的:prop值要和rules里面的值相同
    				rules:{
    					AAA:[{
    						required: true, message: "AAA不能为空", trigger: ["blur","change"]
    					}],
    					BBB:[{
    						required: true, message: "BBB不能为空", trigger: ["blur","change"]
    					}],
    					CCC:[{
    						required: true, message: "CCC不能为空", trigger: ["blur","change"]
    					}],
    					DDD:[{
    						required: true, message: "CCC不能为空", trigger: ["blur","change"]
    					}]
    				}
    			}
    		}
    	}
    </script>
    

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持自由互联。

    上一篇:vue利用openlayers实现动态轨迹
    下一篇:没有了
    网友评论