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>{{ 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>{{ 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>{{ 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>{{ 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'" type="text" v-model="submitForm.AAA"></el-input>
<el-input v-if="item.fieldIdentify=='BBB'" type="text" v-model="submitForm.BBB"></el-input>
<el-input v-if="item.fieldIdentify=='CCC'" 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 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>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持本站。

发表回复