modelForm.vue 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. <style lang="scss" scoped>
  2. .content{
  3. display:flex;
  4. padding:0;
  5. .content-item{
  6. flex:1;
  7. padding:20px;
  8. &.middle{
  9. border-left:2px solid #D8D8D8;
  10. border-right:2px solid #D8D8D8;
  11. }
  12. &.right,&.middle{
  13. flex:2;
  14. }
  15. .item-title{
  16. font-size: 14px;
  17. font-weight: bold;
  18. color: #666666;
  19. margin-bottom:20px;
  20. }
  21. .el-row{
  22. margin-top:20px;
  23. }
  24. .model{
  25. width:80px;
  26. height:80px;
  27. display:flex;
  28. flex-direction: column;
  29. align-items: center;
  30. justify-content: space-evenly;
  31. &:hover{
  32. cursor: pointer;
  33. background:#F5FAFF;
  34. }
  35. img{
  36. height:28px;
  37. width:28px;
  38. }
  39. span{
  40. font-size:14px;
  41. color:#666666;
  42. // margin-top:19px;
  43. }
  44. }
  45. .el-form{
  46. margin-bottom:20px;
  47. .el-form-item{
  48. background:#F5FAFF;
  49. padding:10px 20px;
  50. margin-bottom:5px;
  51. /deep/.el-form-item__label{
  52. font-size:16px;
  53. color:#666666;
  54. }
  55. /deep/.el-form-item__content{
  56. margin-right:160px;
  57. position:relative;
  58. font,.drag{
  59. position:absolute;
  60. right:-145px;
  61. }
  62. font{
  63. top:0px;
  64. color:#3895FE;
  65. font-size: 12px;
  66. span{
  67. margin-left: 5px;
  68. cursor: pointer;
  69. }
  70. }
  71. .drag{
  72. right:-160px;
  73. bottom:-3px;
  74. }
  75. div{
  76. font-size:16px;
  77. color:#333333;
  78. }
  79. .el-radio,.el-checkbox{
  80. margin-right: 32px;
  81. height: 32px;
  82. line-height: 32px;
  83. }
  84. .el-radio-group,.el-checkbox-group{
  85. display:flex;
  86. flex-direction: column;
  87. }
  88. }
  89. /deep/.el-form-item__label{
  90. float: none;
  91. font-weight: bold;
  92. }
  93. &.text{
  94. /deep/.el-form-item__content{
  95. // margin-left:60px;
  96. }
  97. }
  98. }
  99. }
  100. // 右边
  101. .phone{
  102. width: 350px;
  103. height: 713px;
  104. background: url("../../assets/survey_bg.png") no-repeat;
  105. background-size:100% auto;
  106. margin: auto;
  107. }
  108. .item-main{
  109. height: 541px;
  110. width: 315px;
  111. background: #FFFFFF;
  112. border: 1px solid #ddd;
  113. overflow: auto;
  114. position: relative;
  115. top: 85px;
  116. left: 21px;
  117. // display: none;
  118. // border: 1px solid #DDDDDD;
  119. // box-shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.13);
  120. border-radius: 5px;
  121. overflow: auto;
  122. .el-form.over_y{
  123. border: none;
  124. overflow: visible;
  125. }
  126. }
  127. // label样式
  128. .edit_label {
  129. /deep/.el-input__inner{
  130. background:#F5FAFF;
  131. border:0px;
  132. padding:0px;
  133. }
  134. }
  135. /deep/.opicon{
  136. font-weight: bold;
  137. padding:5px;
  138. color:#3895FE;
  139. }
  140. .tpl_title{
  141. font-size: 18px;
  142. margin-bottom:20px;
  143. }
  144. .tpl_form{
  145. margin:20px;
  146. border:1px solid #ccc;
  147. border-radius: 20px;
  148. /deep/.el-form-item{
  149. background:none;
  150. }
  151. /deep/.el-form-item__content{
  152. width:100%;
  153. }
  154. }
  155. .survey_logo{
  156. width:145px;
  157. position: relative;
  158. // top:15px;
  159. left: 20px;
  160. }
  161. .item_require{
  162. position: absolute;
  163. top:0px;
  164. right:35px!important;
  165. /deep/.el-checkbox__label{
  166. padding-left:5px;
  167. // color:red;
  168. }
  169. }
  170. .require::before{
  171. content: "*";
  172. color: #f56c6c;
  173. margin-right: 4px;
  174. position:absolute;
  175. left:-10px;
  176. }
  177. }
  178. }
  179. </style>
  180. <template>
  181. <section>
  182. <p><span>信息管理></span>新增模板</p>
  183. <div class="content">
  184. <div class="content-item">
  185. <div class='item-title'>模板组件</div>
  186. <el-row>
  187. <el-col :span='12'>
  188. <div class='model' @click="addWidget(0)">
  189. <img src="../../assets/slt_small.png" alt="">
  190. <span>单行文本</span>
  191. </div>
  192. </el-col>
  193. <el-col :span='12'>
  194. <div class='model' @click="addWidget(1)">
  195. <img src="../../assets/mlt_small.png" alt="">
  196. <span>多行文本</span>
  197. </div>
  198. </el-col>
  199. </el-row>
  200. <el-row>
  201. <el-col :span='12'>
  202. <div class='model' @click="addWidget(2)">
  203. <img src="../../assets/radio_small.png" alt="">
  204. <span>单选统计</span>
  205. </div>
  206. </el-col>
  207. <el-col :span='12'>
  208. <div class='model' @click="addWidget(3)">
  209. <img src="../../assets/checked_small.png" alt="">
  210. <span>多选统计</span>
  211. </div>
  212. </el-col>
  213. </el-row>
  214. <!-- <el-row>
  215. <el-col :span='12'>
  216. <div class='model' @click="addWidget(4)">
  217. <img src="../../assets/upload_small.png" alt="">
  218. <span>图片上传</span>
  219. </div>
  220. </el-col>
  221. <el-col :span='12'>
  222. <div class='model' @click="addWidget(5)">
  223. <img src="../../assets/file_small.png" alt="">
  224. <span>文件上传</span>
  225. </div>
  226. </el-col>
  227. </el-row> -->
  228. </div>
  229. <div class="content-item middle">
  230. <div class='item-title'>编辑模板-{{title}}</div>
  231. <el-form size="small" label-width="" label-position="top" class='over_y'>
  232. <!-- handle=".dargBtn" 触发拖拽事件的按钮类名 filter=".undraggable" 不可拖拽的元素的类名 -->
  233. <vuedraggable class="wrapper" v-model="widgetList" handle=".dargBtn">
  234. <transition-group>
  235. <el-form-item v-for="(item,index) in widgetList" :key="index" :prop="item.label">
  236. <section v-if="item.type=='input'">
  237. <el-input :readonly="item.edit" v-model="item.label" :class="[item.edit?'edit_label':'',item.require?'require':'']"></el-input>
  238. <el-input placeholder='请输入' v-model="item.placeholder"></el-input>
  239. <font>
  240. <el-checkbox class="item_require" v-model="item.require">必填</el-checkbox>
  241. <span @click="item.edit=!item.edit">{{item.edit?'编辑':'保存'}}</span>
  242. <span @click="widgetList.splice(index,1)">删除</span>
  243. </font>
  244. <el-button type='primary' class='dargBtn drag'>拖拽移动顺序</el-button>
  245. </section>
  246. <section v-if="item.type=='textarea'">
  247. <el-input :readonly="item.edit" v-model="item.label" :class="[item.edit?'edit_label':'',item.require?'require':'']"></el-input>
  248. <el-input type="textarea" placeholder='请输入' v-model="item.placeholder"></el-input>
  249. <font>
  250. <el-checkbox class="item_require" v-model="item.require">必填</el-checkbox>
  251. <span @click="item.edit=!item.edit">{{item.edit?'编辑':'保存'}}</span>
  252. <span @click="widgetList.splice(index,1)">删除</span>
  253. </font>
  254. <el-button type='primary' class='dargBtn drag'>拖拽移动顺序</el-button>
  255. </section>
  256. <section v-if="item.type=='radio'">
  257. <el-input :readonly="item.edit" v-model="item.label" :class="[item.edit?'edit_label':'',item.require?'require':'']"></el-input>
  258. <el-radio-group>
  259. <el-radio :label="iitem.label" v-for="(iitem,index) in item.items" :key="index">
  260. <el-input :readonly="item.edit" v-model="iitem.label" :class="item.edit?'edit_label':''"></el-input>
  261. <template v-if="!item.edit">
  262. <i class="el-icon-minus opicon" @click="minusOption(item.items,index)"></i><i class="el-icon-plus opicon" @click="plusOption(item.items,index)"></i>
  263. </template>
  264. </el-radio>
  265. </el-radio-group>
  266. <font>
  267. <el-checkbox class="item_require" v-model="item.require">必填</el-checkbox>
  268. <span @click="item.edit=!item.edit">{{item.edit?'编辑':'保存'}}</span>
  269. <span @click="widgetList.splice(index,1)">删除</span>
  270. </font>
  271. <el-button type='primary' class='dargBtn drag'>拖拽移动顺序</el-button>
  272. </section>
  273. <section v-if="item.type=='checkbox'">
  274. <el-input :readonly="item.edit" v-model="item.label" :class="[item.edit?'edit_label':'',item.require?'require':'']"></el-input>
  275. <el-radio-group>
  276. <el-checkbox :label="iitem.label" v-for="(iitem,index) in item.items" :key="index">
  277. <el-input :readonly="item.edit" v-model="iitem.label" :class="item.edit?'edit_label':''"></el-input>
  278. <template v-if="!item.edit">
  279. <i class="el-icon-minus opicon" @click="minusOption(item.items,index)"></i><i class="el-icon-plus opicon" @click="plusOption(item.items,index)"></i>
  280. </template>
  281. </el-checkbox>
  282. </el-radio-group>
  283. <font>
  284. <el-checkbox class="item_require" v-model="item.require">必填</el-checkbox>
  285. <span @click="item.edit=!item.edit">{{item.edit?'编辑':'保存'}}</span>
  286. <span @click="widgetList.splice(index,1)">删除</span>
  287. </font>
  288. <el-button type='primary' class='dargBtn drag'>拖拽移动顺序</el-button>
  289. </section>
  290. <section v-if="item.type=='image'">
  291. <el-input :readonly="item.edit" v-model="item.label" :class="item.edit?'edit_label':''"></el-input>
  292. <el-upload
  293. action="https://jsonplaceholder.typicode.com/posts/"
  294. list-type="picture-card"
  295. :on-preview="handlePictureCardPreview"
  296. :on-remove="handleRemove">
  297. <i class="el-icon-plus"></i>
  298. </el-upload>
  299. <font>
  300. <span @click="item.edit=!item.edit">{{item.edit?'编辑':'保存'}}</span>
  301. <span @click="widgetList.splice(index,1)">删除</span>
  302. </font>
  303. <el-button type='primary' class='dargBtn drag'>拖拽移动顺序</el-button>
  304. </section>
  305. <section v-if="item.type=='file'">
  306. <el-input :readonly="item.edit" v-model="item.label" :class="item.edit?'edit_label':''"></el-input>
  307. <el-upload
  308. class="upload-demo"
  309. ref="upload"
  310. action="https://jsonplaceholder.typicode.com/posts/"
  311. :on-preview="handlePreview"
  312. :on-remove="handleRemove"
  313. :file-list="fileList"
  314. :auto-upload="false">
  315. <!-- <el-button slot="trigger" size="small" type="primary">选取文件</el-button> -->
  316. <el-button style="margin-left: 10px;" size="small" type="primary" plain @click="submitUpload">添加文件</el-button>
  317. <!-- <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div> -->
  318. </el-upload>
  319. <font>
  320. <span @click="item.edit=!item.edit">{{item.edit?'编辑':'保存'}}</span>
  321. <span @click="widgetList.splice(index,1)">删除</span>
  322. </font>
  323. <el-button type='primary' class='dargBtn drag'>拖拽移动顺序</el-button>
  324. </section>
  325. </el-form-item>
  326. </transition-group>
  327. </vuedraggable>
  328. <div v-if="this.widgetList.length">
  329. <el-button size="medium" type="primary" @click="save">保存</el-button>
  330. </div>
  331. </el-form>
  332. </div>
  333. <div class="content-item right">
  334. <div class='item-title'>效果预览</div>
  335. <div class="phone">
  336. <div class='item-main'>
  337. <img src="../../assets/survey_logo.png" alt="" class="survey_logo">
  338. <h5 align='center' class="tpl_title">{{title}}</h5>
  339. <el-form ref="form" :model="form" class="tpl_form over_y">
  340. <el-form-item v-for="(item,index) in widgetList" :key="index" :label="item.label">
  341. <el-input :class="item.require?'require':''" v-if="item.type=='input'" v-model="form.label" :placeholder="item.placeholder"></el-input>
  342. <el-input :class="item.require?'require':''" v-if="item.type=='textarea'" type="textarea" v-model="form.label" :placeholder="item.placeholder"></el-input>
  343. <el-radio-group v-if="item.type=='radio'" :class="item.require?'require':''">
  344. <el-radio :label="iitem.label" v-for="(iitem,index) in item.items" :key="index">{{iitem.label}}</el-radio>
  345. </el-radio-group>
  346. <el-radio-group v-if="item.type=='checkbox'" :class="item.require?'require':''">
  347. <el-checkbox :label="iitem.label+'22'" v-for="(iitem,index) in item.items" :key="index">{{iitem.label}}</el-checkbox>
  348. </el-radio-group>
  349. <el-upload
  350. v-if="item.type=='image'"
  351. action="https://jsonplaceholder.typicode.com/posts/"
  352. list-type="picture-card"
  353. :on-preview="handlePictureCardPreview"
  354. :on-remove="handleRemove">
  355. <i class="el-icon-plus"></i>
  356. </el-upload>
  357. <el-upload
  358. v-if="item.type=='file'"
  359. class="upload-demo"
  360. ref="upload"
  361. action="https://jsonplaceholder.typicode.com/posts/"
  362. :on-preview="handlePreview"
  363. :on-remove="handleRemove"
  364. :file-list="fileList"
  365. :auto-upload="false">
  366. <!-- <el-button slot="trigger" size="small" type="primary">选取文件</el-button> -->
  367. <el-button style="margin-left: 10px;" size="small" type="primary" plain @click="submitUpload">添加文件</el-button>
  368. <!-- <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div> -->
  369. </el-upload>
  370. </el-form-item>
  371. <el-form-item v-if="this.widgetList.length">
  372. <el-button size="medium" type="primary" @click="dialogVisible = false" style="width:100%;margin-top:20px;">提交</el-button>
  373. </el-form-item>
  374. </el-form>
  375. </div>
  376. </div>
  377. </div>
  378. </div>
  379. </section>
  380. </template>
  381. <script>
  382. import vuedraggable from 'vuedraggable';
  383. export default {
  384. components: {vuedraggable},
  385. data(){
  386. return{
  387. rules: {
  388. "姓名": [{ required: true, message: "请输入标题", trigger: "blur" }],
  389. },
  390. title:this.$route.query.title,
  391. edit:0,
  392. form:{name:'',page:1,page_size:20},
  393. total:1,
  394. list:[{name:'2333'}],
  395. loading:false,
  396. checkList:[],
  397. input:'',
  398. dialogVisible:false,
  399. defaultProps:{},
  400. data: [{
  401. id: 1,
  402. label: '一级 1'
  403. }, {
  404. id: 2,
  405. label: '一级 2',
  406. children: [{
  407. id: 5,
  408. label: '二级 2-1'
  409. }, {
  410. id: 6,
  411. label: '二级 2-2'
  412. }]
  413. }],
  414. stdWidgetList:[
  415. {type:"input",label:"请输入标题",placeholder:"请输入",edit:true},
  416. {type:"textarea",label:"请输入标题",placeholder:"请输入",edit:true},
  417. {type:"radio",label:"请输入标题",placeholder:"请输入",edit:true,
  418. items:[{label:"选项",value:"选项值"},{label:"选项1",value:"选项值"}]
  419. },
  420. {type:"checkbox",label:"请输入标题",placeholder:"请输入",edit:true,
  421. items:[{label:"选项",value:"选项值"},{label:"选项1",value:"选项值"}]
  422. },
  423. {type:"image",label:"请输入标题",placeholder:"请输入",edit:true},
  424. {type:"file",label:"请输入标题",placeholder:"请输入",edit:true}
  425. ],
  426. widgetList:[],
  427. }
  428. },
  429. methods:{
  430. unique(arr){
  431. var x = new Set(arr);
  432. return [...x];
  433. },
  434. save(){
  435. let id = this.$route.query.id;
  436. let copyid = this.$route.query.copyid
  437. let widgets = Array.from(this.widgetList);
  438. let flag = 0;
  439. let labels = []
  440. widgets.forEach((item,index)=>{
  441. labels.push(item.label)
  442. })
  443. if(labels.length!=this.unique(labels).length){
  444. flag = 1
  445. this.$alert("题干不能相同请仔细检查数据!","数据错误",{
  446. confirmButtonText:"确定",
  447. type:"error"
  448. })
  449. return false
  450. }
  451. widgets.forEach((item,index)=>{
  452. if(item.label==""){
  453. flag = 2
  454. }
  455. if(item.type=="radio"||item.type=="checkbox"){
  456. let item_labels = []
  457. item.items.forEach((obj,index)=>{
  458. item_labels.push(obj.label)
  459. })
  460. if(item_labels.length!=this.unique(item_labels).length){
  461. flag = 3
  462. }
  463. }
  464. })
  465. if(flag==2){
  466. this.$alert("题干不能为空请仔细检查数据!","数据错误",{
  467. confirmButtonText:"确定",
  468. type:"error"
  469. })
  470. return false
  471. }
  472. if(flag==3){
  473. this.$alert("选择题选项不能相同请仔细检查数据!","数据错误",{
  474. confirmButtonText:"确定",
  475. type:"error"
  476. })
  477. return false
  478. }
  479. let params = {
  480. name:this.title,
  481. widget:JSON.stringify(widgets)
  482. }
  483. console.log(widgets,22222222222)
  484. if(id && !copyid){
  485. params.id = id;
  486. this.$api.editTemplate(params).then(res=>{
  487. if(res.data.code==0){
  488. this.$message({
  489. type:"success",
  490. message:"成功!"
  491. })
  492. }else{
  493. this.$message.error("失败!")
  494. }
  495. this.$router.push('/message/template')
  496. })
  497. }else{
  498. this.$api.addTemplate(params).then(res=>{
  499. if(res.data.code==0){
  500. this.$message({
  501. type:"success",
  502. message:"成功!"
  503. })
  504. }else{
  505. this.$message.error("失败!")
  506. }
  507. this.$router.push('/message/template')
  508. })
  509. }
  510. },
  511. addWidget(i){
  512. console.log(i)
  513. this.widgetList.push(JSON.parse(JSON.stringify(this.stdWidgetList[i])))
  514. console.log(this.widgetList)
  515. },
  516. minusOption(options,index){
  517. if(options.length<=1){
  518. this.$message.error("选项不能少于1个!")
  519. }else{
  520. options.splice(index,1)
  521. }
  522. },
  523. plusOption(options,index){
  524. if(options.length>=10){
  525. this.$message.error("选项不能超过10个!")
  526. }else{
  527. options.splice(index+1,0,{label:"选项"+(index+1),value:"选项值"})
  528. }
  529. },
  530. gopage(size){
  531. if(size){
  532. this.form.page_size=size
  533. }
  534. this.form.page=this.$refs.pageButton.page
  535. this.getData()
  536. },
  537. handleSelectionChange(val) {
  538. this.multipleSelection = val;
  539. },
  540. gopage1(size){
  541. if(size){
  542. this.form1.page_size=size
  543. }
  544. this.form1.page=this.$refs.pageButton1.page
  545. this.getJl()
  546. },
  547. open(data) {
  548. this.dialogFormVisible=true;
  549. this.message={...data}
  550. },
  551. download(){
  552. let array=this.multipleSelection,ids=[];
  553. for(let i=0;i<array.length;i++){
  554. ids.push(array[i].id)
  555. }
  556. ids=ids.join(',')
  557. this.$api.downloadMon({ids:ids}).then(res=>{
  558. var elink = document.createElement('a');
  559. let blob=new Blob([res.data], {type: 'application/vnd.ms-excel'});
  560. let objUrl=URL.createObjectURL(blob);
  561. console.log(res.headers['content-disposition'])
  562. let file_name=res.headers['content-disposition'].split('=')[1];
  563. elink.download = file_name;
  564. elink.style.display = 'none';
  565. elink.href = objUrl;
  566. document.body.appendChild(elink);
  567. elink.click();
  568. document.body.removeChild(elink);
  569. })
  570. },
  571. prview(id){
  572. this.form1.enterprise_id=id;
  573. this.getJl();
  574. this.dialogFormVisible1=true
  575. },
  576. getJl(){
  577. var parm=this.form1;
  578. this.$api.getMonitjobList(parm).then(res=>{
  579. this.data=res.data.data.list
  580. this.total1=res.data.data.total
  581. })
  582. },
  583. detail(id){
  584. this.$router.push({ path: '/company/detail', query: { id: id,page:this.form.page,page_size:this.form.page_size } });
  585. },
  586. getData(){
  587. let id = this.$route.query.id;
  588. if(id){
  589. this.$api.getTemplate({id:id}).then(res=>{
  590. if(res.data.code==0){
  591. this.widgetList = res.data.data.widget;
  592. }
  593. })
  594. }
  595. },
  596. del(id){
  597. this.$confirm('确定删除吗?', '提示', {
  598. type: 'warning'
  599. }).then(() => {
  600. this.$api.deleteEnterprise({id:id}).then((res)=>{
  601. this.$message({
  602. message: '删除成功',
  603. type: 'success'
  604. })
  605. this.getData()
  606. })
  607. })
  608. },
  609. permission(name){
  610. let permissions=this.info.permissions||[];
  611. let list=[];
  612. for(let i=0;i<permissions.length;i++){
  613. list.push(permissions[i].name)
  614. }
  615. if(list.indexOf(name)<0){
  616. return false;
  617. }else{
  618. return true;
  619. }
  620. },
  621. },
  622. created(){
  623. this.getData();
  624. }
  625. }
  626. </script>