index.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. <template>
  2. <template-page ref="pageRef" :get-list="getList" :exportList="exportList" :table-attributes="tableAttributes"
  3. :table-events="tableEvents" :options-evens-group="optionsEvensGroup"
  4. :column-parsing="columnParsing" :operation="operation()" :operationColumnWidth="200">
  5. <div class="cartographer">
  6. <el-dialog :title="formData.id?'详情':'新增'" width="100%" :modal="false" :visible.sync="formDialog"
  7. :before-close="formCancel">
  8. <zj-form-container v-if="formDialog" ref="formRef" :form-data="formData" :styleSwitch="false">
  9. <zj-form-module title="活动信息" label-width="120px" :form-data="formData"
  10. :form-items="formItems">
  11. </zj-form-module>
  12. <zj-form-module title="活动填写内容" label-width="100px" :form-data="formData"
  13. :form-items="formItems2">
  14. </zj-form-module>
  15. </zj-form-container>
  16. <div slot="footer" class="dialog-footer">
  17. <el-button size="mini" @click="formCancel">取 消</el-button>
  18. <el-button v-if="!formData.id" size="mini" type="primary" @click="formConfirm">确 定</el-button>
  19. <el-button v-if="formData.id && !!~[0, 1].indexOf(formData.status)" size="mini" type="primary" @click="zhongzhi">终 止</el-button>
  20. </div>
  21. </el-dialog>
  22. </div>
  23. <answer v-if="showQuestion" :defaultData="questionData" @close="questionClose" @confirm="questionConfirm"/>
  24. </template-page>
  25. </template>
  26. <script>
  27. import TemplatePage from '@/components/template/template-page-1.vue'
  28. import import_mixin from '@/components/template/import_mixin.js'
  29. import operation_mixin from '@/components/template/operation_mixin.js'
  30. import {promotionQuestionnaireList,promotionQuestionnaireExport,promotionQuestionnaireAdd,promotionQuestionnaireStop,promotionQuestionnaireDetail} from "@/api/setActivity.js"
  31. import answer from "./answer.vue"
  32. import ImageUpload from '@/components/file-upload'
  33. import quillEditor from '@/components/v-quill-editor'
  34. import editTable from "@/components/template/editTable.js"
  35. import { required, mobileRequired, mobile, httpUrl, email } from '@/components/template/rules_verify.js'
  36. export default {
  37. components: { TemplatePage, answer, ImageUpload, quillEditor },
  38. mixins: [import_mixin, operation_mixin, editTable],
  39. data() {
  40. return {
  41. formDialog: false,
  42. showQuestion: false,
  43. questionData: {
  44. rowIndex: -1
  45. },
  46. formData: {
  47. "companyWechatId": "",
  48. "companyWechatName": JSON.parse(localStorage.getItem('greemall_user')).companyName,
  49. "startTime": "",
  50. "endTime": "",
  51. "name": "",
  52. "submitLimit": '',
  53. "submitLimitBool": 0,
  54. "qrcode": "",
  55. "title": "",
  56. "content": "",
  57. "banner": [],
  58. "detailImgs": [],
  59. "promotionQuestionnaireItems": [],
  60. "promotionQuestionnaireUsers": [],
  61. },
  62. // 表格属性
  63. tableAttributes: {
  64. // 启用勾选列
  65. selectColumn: false
  66. },
  67. // 表格事件
  68. tableEvents: {},
  69. }
  70. },
  71. computed:{
  72. // 事件组合
  73. optionsEvensGroup() {
  74. return [
  75. [
  76. [
  77. this.optionsEvensAuth('add', {
  78. click: this.addData
  79. })
  80. ]
  81. ]
  82. ]
  83. },
  84. formItems(){
  85. return [
  86. {
  87. name: 'el-input',
  88. md: 12,
  89. attributes: { disabled: true, placeholder: '请选择' },
  90. formItemAttributes: { label: '所属商户', prop: 'companyWechatName' }
  91. },
  92. {
  93. name: 'el-date-picker',
  94. md: 6,
  95. attributes: {
  96. disabled: !!this.formData.id,
  97. style: { width: '100%' },
  98. placeholder: '请选择',
  99. 'value-format': 'yyyy-MM-dd HH:mm:ss',
  100. },
  101. formItemAttributes: {
  102. label: '活动开始日期',
  103. prop: 'startTime',
  104. rules: [{ required: true, message: '请选择', trigger: 'blur' }]
  105. }
  106. },
  107. {
  108. name: 'el-date-picker',
  109. md: 6,
  110. attributes: {
  111. disabled: !!this.formData.id,
  112. style: { width: '100%' },
  113. placeholder: '请选择',
  114. 'value-format': 'yyyy-MM-dd HH:mm:ss',
  115. },
  116. formItemAttributes: {
  117. label: '活动结束日期',
  118. prop: 'endTime',
  119. rules: [{ required: true, message: '请选择', trigger: 'blur' }]
  120. }
  121. },
  122. {
  123. name: 'el-input',
  124. md: 12,
  125. attributes: { disabled: !!this.formData.id, placeholder: '请选择' },
  126. formItemAttributes: {
  127. label: '活动名称',
  128. prop: 'name',
  129. rules: [{ required: true, message: '请填写', trigger: 'blur' }]
  130. }
  131. },
  132. {
  133. name: 'el-input',
  134. md: 12,
  135. attributes: { disabled: !!this.formData.id, placeholder: '请选择' },
  136. formItemAttributes: {
  137. label: '二维码主题',
  138. prop: 'title',
  139. rules: [{ required: true, message: '请填写', trigger: 'blur' }]
  140. }
  141. },
  142. {
  143. md: 24,
  144. name: 'slot-component',
  145. attributes: { placeholder: '请输入' },
  146. formItemAttributes: {
  147. label: '提交次数',
  148. prop: 'submitLimitBool',
  149. rules: [{ required: true, message: '请选择', trigger: 'blur' }]
  150. },
  151. render: (h, { props, onInput }) => {
  152. var { value } = props
  153. console.log(value)
  154. return (
  155. <div class="redbordererr" style="">
  156. <el-form-item label="" label-width="0px" prop="submitLimit" rules={value ? [{ required: true, message: '请填写', trigger: 'blur' }] : []}>
  157. <el-radio-group disabled={!!this.formData.id} value={value} onInput={onInput}>
  158. <el-radio disabled={!!this.formData.id} label={0}>不限制</el-radio>
  159. <el-radio disabled={!!this.formData.id} label={1}>
  160. 限制{value?[<el-input disabled={!!this.formData.id} style="margin: 0 10px;width:100px;" value={this.formData.submitLimit} onInput={(val)=>{this.formData.submitLimit = val}} type="number" placeholder="请输入内容"></el-input>,<span>次</span>]:null}
  161. </el-radio>
  162. </el-radio-group>
  163. </el-form-item>
  164. </div>
  165. )
  166. }
  167. },
  168. {
  169. md: 24,
  170. name: 'slot-component',
  171. attributes: { placeholder: '请输入' },
  172. formItemAttributes: {
  173. label: '首页广告图',
  174. prop: 'banner',
  175. rules: [{ required: true, message: '请上传', trigger: 'blur' }]
  176. },
  177. render: (h, { props, onInput }) => {
  178. var { value } = props
  179. return (
  180. <ImageUpload isEdit={!this.formData.id} fileList={this.formData.banner} uid={`questionFiles_bananner`} limit={1} isUpdate={false} />
  181. )
  182. }
  183. },
  184. {
  185. md: 24,
  186. name: 'slot-component',
  187. attributes: { placeholder: '请输入' },
  188. formItemAttributes: {
  189. label: '活动详情图',
  190. prop: 'detailImgs',
  191. rules: [{ required: true, message: '请上传', trigger: 'blur' }]
  192. },
  193. render: (h, { props, onInput }) => {
  194. var { value } = props
  195. return (
  196. <ImageUpload isEdit={!this.formData.id} fileList={this.formData.detailImgs} uid={`questionFiles_detaidetailImgsdetailImgs`} limit={100} isUpdate={false} />
  197. )
  198. }
  199. },
  200. {
  201. md: 24,
  202. name: 'slot-component',
  203. attributes: { placeholder: '请输入' },
  204. formItemAttributes: {
  205. label: '活动说明',
  206. prop: 'content',
  207. rules: []
  208. },
  209. render: (h, { props, onInput }) => {
  210. var { value } = props
  211. return (
  212. <quillEditor disabled={!!this.formData.id} value={value} onInput={onInput}></quillEditor>
  213. )
  214. }
  215. },
  216. {
  217. name: 'slot-component',
  218. md: 24,
  219. formItemAttributes: {
  220. label: '提交记录',
  221. prop: 'promotionQuestionnaireUsers',
  222. rules: [{ required: true, message: '请设置', trigger: 'blur' }]
  223. },
  224. render: (h, { props, onInput }) => {
  225. var { value } = props
  226. return this.convertTableJson(value, [
  227. {
  228. columnAttributes: {
  229. label: '*姓名',
  230. prop: 'name',
  231. },
  232. editRender: (h, { row, column, index }) => {
  233. return (
  234. <div class="redbordererr">
  235. <el-form-item label="" label-width="0px" prop={`promotionQuestionnaireUsers.${index}.${column.columnAttributes.prop}`} rules={[{ required: true, message: '请填写', trigger: 'blur' }]}>
  236. <el-input value={row[column.columnAttributes.prop]} onInput={val => { row[column.columnAttributes.prop] = val }} placeholder="请输入内容"></el-input>
  237. </el-form-item>
  238. </div>
  239. )
  240. },
  241. viewRender: (h, { row, column, index }) => {
  242. return <div style="padding-left:10px">{row[column.columnAttributes.prop]}</div>
  243. }
  244. },
  245. {
  246. columnAttributes: {
  247. label: '*电话',
  248. prop: 'mobile',
  249. },
  250. editRender: (h, { row, column, index }) => {
  251. return (
  252. <div class="redbordererr">
  253. <el-form-item label="" label-width="0px" prop={`promotionQuestionnaireUsers.${index}.${column.columnAttributes.prop}`} rules={mobileRequired}>
  254. <el-input value={row[column.columnAttributes.prop]} onInput={val => { row[column.columnAttributes.prop] = val }} placeholder="请输入内容"></el-input>
  255. </el-form-item>
  256. </div>
  257. )
  258. },
  259. viewRender: (h, { row, column, index }) => {
  260. return <div style="padding-left:10px">{row[column.columnAttributes.prop]}</div>
  261. }
  262. },
  263. {
  264. columnAttributes: {
  265. label: '*时间(分钟)',
  266. prop: 'min',
  267. },
  268. editRender: (h, { row, column, index }) => {
  269. return (
  270. <div class="redbordererr">
  271. <el-form-item label="" label-width="0px" prop={`promotionQuestionnaireUsers.${index}.${column.columnAttributes.prop}`} rules={[{ required: true, message: '请填写', trigger: 'blur' }]}>
  272. <el-input type="number" value={row[column.columnAttributes.prop]} onInput={val => { row[column.columnAttributes.prop] = val }} placeholder="请输入内容"></el-input>
  273. </el-form-item>
  274. </div>
  275. )
  276. },
  277. viewRender: (h, { row, column, index }) => {
  278. return <div style="padding-left:10px">{row[column.columnAttributes.prop]}</div>
  279. }
  280. },
  281. {
  282. columnAttributes: {
  283. label: '*备注',
  284. prop: 'remark',
  285. },
  286. editRender: (h, { row, column, index }) => {
  287. return (
  288. <div class="redbordererr">
  289. <el-form-item label="" label-width="0px" prop={`promotionQuestionnaireUsers.${index}.${column.columnAttributes.prop}`} rules={[{ required: true, message: '请填写', trigger: 'blur' }]}>
  290. <el-input value={row[column.columnAttributes.prop]} onInput={val => { row[column.columnAttributes.prop] = val }} placeholder="请输入内容"></el-input>
  291. </el-form-item>
  292. </div>
  293. )
  294. },
  295. viewRender: (h, { row, column, index }) => {
  296. return <div style="padding-left:10px">{row[column.columnAttributes.prop]}</div>
  297. }
  298. },
  299. ], {
  300. isEdit: !this.formData.id,
  301. isAdd: !this.formData.id,
  302. isDel: !this.formData.id,
  303. }, {
  304. add: ()=>{
  305. this.formData.promotionQuestionnaireUsers.push({
  306. "min": '',
  307. "mobile": "",
  308. "name": "",
  309. "promotionQuestionnaireId": "",
  310. "remark": ""
  311. })
  312. this.isEditTableIndex = this.formData.promotionQuestionnaireUsers.length - 1
  313. },
  314. delete: ({ row, column, index }, cb) => {
  315. if (this.isEditTableIndex == index) {
  316. this.isEditTableIndex = -1
  317. } else if (this.isEditTableIndex > index) {
  318. this.isEditTableIndex--
  319. }
  320. cb && cb()
  321. },
  322. verify: ({ row, column, index }, isEditTableIndex) => {
  323. return new Promise(r => {
  324. if (isEditTableIndex > -1) {
  325. this.$refs.formRef.validateField([
  326. `promotionQuestionnaireUsers.${isEditTableIndex}.min`,
  327. `promotionQuestionnaireUsers.${isEditTableIndex}.mobile`,
  328. `promotionQuestionnaireUsers.${isEditTableIndex}.name`,
  329. `promotionQuestionnaireUsers.${isEditTableIndex}.remark`,
  330. ], (v) => {
  331. if (v) {
  332. r(true)
  333. } else {
  334. r(false)
  335. }
  336. })
  337. } else {
  338. r(true)
  339. }
  340. })
  341. },
  342. })
  343. }
  344. },
  345. ]
  346. },
  347. formItems2(){
  348. return [{
  349. md: 24,
  350. name: 'slot-component',
  351. attributes: { placeholder: '请输入' },
  352. formItemAttributes: {
  353. label: '',
  354. 'label-width': '0px',
  355. prop: 'promotionQuestionnaireItems',
  356. rules: [{ required: true, message: '请设置', trigger: 'blur' }]
  357. },
  358. render: (h, { props, onInput }) => {
  359. return (
  360. <div>
  361. <div>
  362. {!this.formData.id?<el-button type="primary" onClick={()=>{ this.showQuestion = true }}>新增</el-button>:null}
  363. </div>
  364. <div>
  365. <zj-table
  366. columns={[{
  367. columnAttributes: {
  368. label: '填写内容',
  369. prop: '',
  370. },
  371. render: (h, { row, column, index }) => {
  372. return (
  373. <div style="padding:6px;">
  374. <div style="font-weight:bold;">{row.isRequire?<span style="color:red">*</span> : null}{index+1}、{row.question}({['单选','多选','填写'][row.type-1]})</div>
  375. {[
  376. <div>
  377. {row.answer.map(item=><el-radio disabled label="">{item.option_value}</el-radio>)}
  378. </div>,
  379. <div>
  380. {row.answer.map(item=><el-checkbox disabled label="">{item.option_value}</el-checkbox>)}
  381. </div>,
  382. <div>
  383. <el-input disabled placeholder="请输入内容"></el-input>
  384. </div>
  385. ][row.type-1]}
  386. </div>
  387. )
  388. },
  389. },
  390. ...(()=>{
  391. if(!this.formData.id){
  392. return[{
  393. columnAttributes: {
  394. label: '操作',
  395. prop: '',
  396. width: '200px'
  397. },
  398. render: (h, { row, column, index }) => {
  399. return (
  400. <div style="padding-left:5px">
  401. <el-button size="mini" onClick={()=>{
  402. this.questionData = {
  403. ...JSON.parse(JSON.stringify(row)),
  404. rowIndex: index
  405. }
  406. this.$nextTick(()=>{
  407. this.showQuestion = true
  408. })
  409. }}>编辑</el-button>
  410. <el-button size="mini" onClick={()=>{
  411. this.formData.promotionQuestionnaireItems.push({...JSON.parse(JSON.stringify(row))})
  412. }}>复制</el-button>
  413. <el-button size="mini" onClick={()=>{
  414. this.formData.promotionQuestionnaireItems.splice(index, 1)
  415. }}>删除</el-button>
  416. </div>
  417. )
  418. },
  419. }]
  420. }
  421. return []
  422. })()]}
  423. table-data={this.formData.promotionQuestionnaireItems}
  424. />
  425. </div>
  426. </div>
  427. )
  428. }
  429. }]
  430. }
  431. },
  432. methods: {
  433. // 列表请求函数
  434. getList:promotionQuestionnaireList,
  435. // 列表导出函数
  436. exportList: promotionQuestionnaireExport,
  437. // 表格列解析渲染数据更改
  438. columnParsing(item, defaultData) {
  439. if (item.jname === 'qrcode') {
  440. defaultData.render = (h, { row, index, column }) => {
  441. return (
  442. <div style="padding:0 6px;cursor: pointer;">
  443. {row.qrcode ? row.qrcode.split(",").map(url => <el-image src={url} preview-src-list={[url]} fit="fit" style="width:80px;height:80px;" />) : null}
  444. </div>
  445. )
  446. }
  447. }
  448. if (item.jname == 'startTime') {
  449. defaultData.render = (h, { row, index, column }) => {
  450. return (
  451. <div style="padding:0 6px;cursor: pointer;">
  452. {row.startTime && row.startTime.split(" ")[0]}
  453. </div>
  454. )
  455. }
  456. }
  457. if (item.jname == 'endTime') {
  458. defaultData.render = (h, { row, index, column }) => {
  459. return (
  460. <div style="padding:0 6px;cursor: pointer;">
  461. {row.endTime && row.endTime.split(" ")[0]}
  462. </div>
  463. )
  464. }
  465. }
  466. return defaultData
  467. },
  468. // 操作按钮
  469. operation() {
  470. return this.operationBtn({
  471. detail: {
  472. click: ({ row, index, column }) => {
  473. promotionQuestionnaireDetail({
  474. id: row.id
  475. }).then(res=>{
  476. this.formData = {
  477. ...res.data,
  478. submitLimitBool: res.data.submitLimit == -1 ? 0 : 1,
  479. promotionQuestionnaireItems:res.data.promotionQuestionnaireItems.map(item=>{
  480. return {
  481. ...item,
  482. answer: JSON.parse(item?.answer||"[]")
  483. }
  484. }),
  485. banner:res.data?.banner?.split(",").map(url=>({url})),
  486. detailImgs:res.data?.detailImgs?.split(",").map(url=>({url}))
  487. }
  488. this.$nextTick(()=>{
  489. this.formDialog = true
  490. })
  491. })
  492. }
  493. },
  494. createActivity: {
  495. click: ({ row, index, column }) => {
  496. this.$router.push({
  497. name: "activityOrder",
  498. query: {
  499. type: "detail",
  500. id: row.id,
  501. },
  502. })
  503. }
  504. },
  505. viewActivity: {
  506. click: ({ row, index, column }) => {
  507. this.$router.push({
  508. name: "activityOrder",
  509. query: {
  510. type: "list",
  511. id: row.id,
  512. },
  513. })
  514. }
  515. },
  516. })
  517. },
  518. // 新增
  519. addData(){
  520. this.formDialog = true
  521. },
  522. // 关闭弹窗
  523. formCancel(){
  524. this.formDialog = false
  525. this.$data.formData = this.$options.data().formData
  526. },
  527. // 确定
  528. formConfirm() {
  529. this.$refs.formRef.validate((valid, invalidFields, errLabels) => {
  530. if (valid) {
  531. var data = {
  532. ...this.formData,
  533. endTime: this.formData.endTime ? `${this.formData.endTime.split(" ")[0]} 23:59:59` : '',
  534. banner:this.formData.banner.map(item=>item.url).join(","),
  535. detailImgs:this.formData.detailImgs.map(item=>item.url).join(","),
  536. promotionQuestionnaireItems:this.formData.promotionQuestionnaireItems.map(item=>{
  537. return {
  538. ...item,
  539. answer: JSON.stringify(item.answer)
  540. }
  541. }),
  542. submitLimit: !!this.formData.submitLimitBool ? this.formData.submitLimit : -1
  543. }
  544. promotionQuestionnaireAdd(data).then(res=>{
  545. this.$message({
  546. type: 'success',
  547. message: `添加成功!`,
  548. })
  549. this.$refs.pageRef.refreshList()
  550. this.formCancel()
  551. })
  552. }
  553. })
  554. },
  555. // 终止
  556. zhongzhi(){
  557. promotionQuestionnaireStop({
  558. id:this.formData.id
  559. }).then(res=>{
  560. this.$message({
  561. type: 'success',
  562. message: `终止成功!`,
  563. })
  564. this.$refs.pageRef.refreshList()
  565. this.formCancel()
  566. })
  567. },
  568. // 关闭题目编辑
  569. questionClose(){
  570. this.showQuestion = false
  571. this.questionData = {
  572. rowIndex: -1
  573. }
  574. },
  575. // 确定题目编辑
  576. questionConfirm(data){
  577. if(data.rowIndex==-1){
  578. this.formData.promotionQuestionnaireItems.push({...data})
  579. }else{
  580. this.formData.promotionQuestionnaireItems.splice(data.rowIndex, 1, {...data})
  581. }
  582. this.questionClose()
  583. }
  584. }
  585. }
  586. </script>
  587. <style lang="scss">
  588. </style>