modelForm.vue 28 KB

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