modelForm.vue 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  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. title:this.$route.query.title,
  388. edit:0,
  389. form:{name:'',page:1,page_size:20},
  390. total:1,
  391. list:[{name:'2333'}],
  392. loading:false,
  393. checkList:[],
  394. input:'',
  395. dialogVisible:false,
  396. defaultProps:{},
  397. data: [{
  398. id: 1,
  399. label: '一级 1'
  400. }, {
  401. id: 2,
  402. label: '一级 2',
  403. children: [{
  404. id: 5,
  405. label: '二级 2-1'
  406. }, {
  407. id: 6,
  408. label: '二级 2-2'
  409. }]
  410. }],
  411. stdWidgetList:[
  412. {type:"input",label:"请输入标题",placeholder:"请输入",edit:true},
  413. {type:"textarea",label:"请输入标题",placeholder:"请输入",edit:true},
  414. {type:"radio",label:"请输入标题",placeholder:"请输入",edit:true,
  415. items:[{label:"选项",value:"选项值"},{label:"选项1",value:"选项值"}]
  416. },
  417. {type:"checkbox",label:"请输入标题",placeholder:"请输入",edit:true,
  418. items:[{label:"选项",value:"选项值"},{label:"选项1",value:"选项值"}]
  419. },
  420. {type:"image",label:"请输入标题",placeholder:"请输入",edit:true},
  421. {type:"file",label:"请输入标题",placeholder:"请输入",edit:true}
  422. ],
  423. widgetList:[],
  424. }
  425. },
  426. methods:{
  427. unique(arr){
  428. var x = new Set(arr);
  429. return [...x];
  430. },
  431. save(){
  432. let id = this.$route.query.id;
  433. let copyid = this.$route.query.copyid
  434. let widgets = Array.from(this.widgetList);
  435. let flag = 0;
  436. let labels = []
  437. widgets.forEach((item,index)=>{
  438. labels.push(item.label)
  439. })
  440. if(labels.length!=this.unique(labels).length){
  441. flag = 1
  442. this.$alert("题干不能相同请仔细检查数据!","数据错误",{
  443. confirmButtonText:"确定",
  444. type:"error"
  445. })
  446. return false
  447. }
  448. widgets.forEach((item,index)=>{
  449. if(item.label==""){
  450. flag = 2
  451. }
  452. if(item.type=="radio"||item.type=="checkbox"){
  453. let item_labels = []
  454. item.items.forEach((obj,index)=>{
  455. item_labels.push(obj.label)
  456. })
  457. if(item_labels.length!=this.unique(item_labels).length){
  458. flag = 3
  459. }
  460. }
  461. })
  462. if(flag==2){
  463. this.$alert("题干不能为空请仔细检查数据!","数据错误",{
  464. confirmButtonText:"确定",
  465. type:"error"
  466. })
  467. return false
  468. }
  469. if(flag==3){
  470. this.$alert("选择题选项不能相同请仔细检查数据!","数据错误",{
  471. confirmButtonText:"确定",
  472. type:"error"
  473. })
  474. return false
  475. }
  476. let params = {
  477. name:this.title,
  478. widget:JSON.stringify(widgets)
  479. }
  480. console.log(widgets,22222222222)
  481. if(id && !copyid){
  482. params.id = id;
  483. this.$api.editTemplate(params).then(res=>{
  484. if(res.data.code==0){
  485. this.$message({
  486. type:"success",
  487. message:"成功!"
  488. })
  489. }else{
  490. this.$message.error("失败!")
  491. }
  492. this.$router.push('/message/template')
  493. })
  494. }else{
  495. this.$api.addTemplate(params).then(res=>{
  496. if(res.data.code==0){
  497. this.$message({
  498. type:"success",
  499. message:"成功!"
  500. })
  501. }else{
  502. this.$message.error("失败!")
  503. }
  504. this.$router.push('/message/template')
  505. })
  506. }
  507. },
  508. addWidget(i){
  509. console.log(i)
  510. this.widgetList.push(JSON.parse(JSON.stringify(this.stdWidgetList[i])))
  511. console.log(this.widgetList)
  512. },
  513. minusOption(options,index){
  514. if(options.length<=1){
  515. this.$message.error("选项不能少于1个!")
  516. }else{
  517. options.splice(index,1)
  518. }
  519. },
  520. plusOption(options,index){
  521. if(options.length>=10){
  522. this.$message.error("选项不能超过10个!")
  523. }else{
  524. options.splice(index+1,0,{label:"选项"+(index+1),value:"选项值"})
  525. }
  526. },
  527. gopage(size){
  528. if(size){
  529. this.form.page_size=size
  530. }
  531. this.form.page=this.$refs.pageButton.page
  532. this.getData()
  533. },
  534. handleSelectionChange(val) {
  535. this.multipleSelection = val;
  536. },
  537. gopage1(size){
  538. if(size){
  539. this.form1.page_size=size
  540. }
  541. this.form1.page=this.$refs.pageButton1.page
  542. this.getJl()
  543. },
  544. open(data) {
  545. this.dialogFormVisible=true;
  546. this.message={...data}
  547. },
  548. download(){
  549. let array=this.multipleSelection,ids=[];
  550. for(let i=0;i<array.length;i++){
  551. ids.push(array[i].id)
  552. }
  553. ids=ids.join(',')
  554. this.$api.downloadMon({ids:ids}).then(res=>{
  555. var elink = document.createElement('a');
  556. let blob=new Blob([res.data], {type: 'application/vnd.ms-excel'});
  557. let objUrl=URL.createObjectURL(blob);
  558. console.log(res.headers['content-disposition'])
  559. let file_name=res.headers['content-disposition'].split('=')[1];
  560. elink.download = file_name;
  561. elink.style.display = 'none';
  562. elink.href = objUrl;
  563. document.body.appendChild(elink);
  564. elink.click();
  565. document.body.removeChild(elink);
  566. })
  567. },
  568. prview(id){
  569. this.form1.enterprise_id=id;
  570. this.getJl();
  571. this.dialogFormVisible1=true
  572. },
  573. getJl(){
  574. var parm=this.form1;
  575. this.$api.getMonitjobList(parm).then(res=>{
  576. this.data=res.data.data.list
  577. this.total1=res.data.data.total
  578. })
  579. },
  580. detail(id){
  581. this.$router.push({ path: '/company/detail', query: { id: id,page:this.form.page,page_size:this.form.page_size } });
  582. },
  583. getData(){
  584. let id = this.$route.query.id;
  585. if(id){
  586. this.$api.getTemplate({id:id}).then(res=>{
  587. if(res.data.code==0){
  588. this.widgetList = res.data.data.widget;
  589. }
  590. })
  591. }
  592. },
  593. del(id){
  594. this.$confirm('确定删除吗?', '提示', {
  595. type: 'warning'
  596. }).then(() => {
  597. this.$api.deleteEnterprise({id:id}).then((res)=>{
  598. this.$message({
  599. message: '删除成功',
  600. type: 'success'
  601. })
  602. this.getData()
  603. })
  604. })
  605. },
  606. permission(name){
  607. let permissions=this.info.permissions||[];
  608. let list=[];
  609. for(let i=0;i<permissions.length;i++){
  610. list.push(permissions[i].name)
  611. }
  612. if(list.indexOf(name)<0){
  613. return false;
  614. }else{
  615. return true;
  616. }
  617. },
  618. },
  619. created(){
  620. this.getData();
  621. }
  622. }
  623. </script>