index.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. import * as api from '@/api'
  2. import Custom from '../js/custom'
  3. import Layout1 from '../Layout1'
  4. import Layout2 from '../Layout2'
  5. import Layoutileads1 from '../Layoutileads1'
  6. import Storage from '@/utils/storage'
  7. const lStorage = new Storage('localStorage')
  8. require('@/utils/jweixin-1.3.2.js')
  9. function getTrim (val) {
  10. return val.replace(/(^\s+)|(\s+$)/g, '')
  11. }
  12. export default {
  13. props: {
  14. edata: {
  15. type: Object
  16. },
  17. edataItem: {
  18. type: Object
  19. },
  20. isEdit: {
  21. type: Boolean
  22. }
  23. },
  24. components: {
  25. Layout1,
  26. Layout2,
  27. Layoutileads1,
  28. },
  29. data() {
  30. return {
  31. TITLE: '问卷调查',
  32. data: {
  33. result: [],
  34. topic: {}
  35. },
  36. layoutType: {
  37. '1': 'Layout1',
  38. '2': 'Layout2',
  39. '3': 'Layoutileads1'
  40. },
  41. configType: {
  42. 'radio': '单选',
  43. 'checkbox': '多选'
  44. },
  45. loading: {
  46. data: false,
  47. empty: false,
  48. submit: false
  49. },
  50. show: {
  51. submit: false
  52. },
  53. codeMess: {
  54. num: 3,
  55. message: '自动跳转',
  56. disabled: false,
  57. t: null
  58. }
  59. };
  60. },
  61. computed: {
  62. putLayoutCurrent() {
  63. let layout_type = this.data ? this.data.topic.layout_type : ''
  64. return this.layoutType[layout_type] || 'van-empty'
  65. }
  66. },
  67. watch: {
  68. edata() {
  69. this.inData()
  70. }
  71. },
  72. destroyed() {
  73. clearInterval(this.codeMess.t)
  74. },
  75. created() {
  76. let objData = lStorage.getItem('AHR') || {}
  77. let data = Object.keys(objData).map(k => objData[k])
  78. let d1 = new Date().toString('yyyyMMdd')
  79. data = data.filter(item => {
  80. if (item.timer) {
  81. return new Date(item.timer).toString('yyyyMMdd') === d1
  82. }
  83. })
  84. if (data.length && !this.$route.query.jump && !this.isEdit) {
  85. this.$router.replace({ name: 'FormResult', query: this.$route.query })
  86. } else {
  87. this.vueWatchRoute()
  88. }
  89. },
  90. methods: {
  91. vueWatchRoute (a, b) {
  92. this.inQuery()
  93. if (!b || a.name !== b.name) {
  94. clearInterval(this.codeMess.t)
  95. this.inData()
  96. }
  97. },
  98. // 秒倒计时
  99. async loopCode(num, callback) {
  100. let msg = '自动跳转'
  101. clearInterval(this.codeMess.t)
  102. function loopNum() {
  103. if (num < 1) {
  104. this.codeMess['message'] = msg
  105. this.codeMess['disabled'] = false
  106. clearInterval(this.codeMess.t)
  107. callback && callback()
  108. return
  109. }
  110. this.codeMess['disabled'] = true
  111. this.codeMess['message'] = `${num}s ${msg}`
  112. num = num - 1
  113. console.log(this.codeMess['message'])
  114. }
  115. loopNum.call(this)
  116. this.codeMess.t = setInterval(() => loopNum.call(this), 1000)
  117. },
  118. inQuery() {
  119. let { title } = this.$route.query
  120. if (title) {
  121. this.TITLE = title
  122. }
  123. },
  124. isForm(result, callback) {
  125. return new Promise((resolve, reject) => {
  126. let state = result.some(item => {
  127. if (!item.required) {
  128. return false
  129. }
  130. let b = item.val instanceof Array ? !!item.val.length : !!item.val
  131. !b && callback && callback(item)
  132. return !b
  133. })
  134. state ? reject() : resolve()
  135. })
  136. },
  137. async inData() {
  138. this.loading.data = true
  139. this.loading.empty = false
  140. try {
  141. let data = null
  142. if (this.isEdit) {
  143. data = this.edata
  144. } else {
  145. let { result_id } = this.$route.query
  146. let pm = result_id
  147. ? api.apiGetVolumeResult({ result_id })
  148. : api.apiGetVolumeInfo(this.$route.query)
  149. let res = await pm
  150. data = res.data
  151. }
  152. this.inTopicComponent(data, Custom)
  153. this.$set(this, 'data', data)
  154. this.inTITLE()
  155. } catch (error) {
  156. this.loading.empty = true
  157. console.log(error)
  158. }
  159. this.loading.data = false
  160. },
  161. inTITLE () {
  162. if (this.data) {
  163. this.TITLE = this.data.topic.name
  164. }
  165. },
  166. // 问卷组件初始化
  167. inTopicComponent(data, callback) {
  168. data = data || this.data
  169. data.result.forEach(item => {
  170. typeof callback === 'function' && callback(item)
  171. let { patient_mobile } = this.$route.query
  172. if (new RegExp('手机号码').test(item.title) && patient_mobile) {
  173. item.val = patient_mobile
  174. // item.disabled = true
  175. }
  176. if (item.type === 'certificate') {
  177. item.certificate = '身份证'
  178. }
  179. if (item.type === 'area') {
  180. item.area = ''
  181. item.val1 = ''
  182. item.val2 = ''
  183. }
  184. })
  185. },
  186. btnOpenSuccess(callback) {
  187. this.show.submit = true
  188. this.loopCode(this.codeMess.num, async () => {
  189. this.show.submit = false
  190. await this.$nextTick()
  191. callback && callback()
  192. })
  193. },
  194. async btnSubmit(datas, callbackSuccess, callbackError) {
  195. let pm
  196. let ld = null
  197. let edatas = datas || [this.data]
  198. this.loading.submit = true
  199. try {
  200. // await Promise.all(edatas.map(data => {
  201. // return this.isForm(data.result, item => {
  202. // this.$dialog.alert({
  203. // title: '必填项',
  204. // message: `${item.title}`,
  205. // })
  206. // })
  207. // }))
  208. let ruleData = {}
  209. let rule = {}
  210. function validatorArea (item, reg) {
  211. let obj = {}
  212. let cerFn = () => item.required && !item.area
  213. if (cerFn()) {
  214. obj = {
  215. validator: () => !!item.area,
  216. message: '请选择居住地址'
  217. }
  218. } else {
  219. obj = {
  220. validator: () => {
  221. return !!item.val1 && !!item.val2
  222. },
  223. message: '请填写详细地址'
  224. }
  225. }
  226. return obj
  227. }
  228. function validatorCertificate(item, reg) {
  229. let obj = {}
  230. let cerFn = () => item.required && !item.certificate
  231. if (cerFn()) {
  232. obj = {
  233. validator: () => !!item.certificate,
  234. message: '请选择证件类型'
  235. }
  236. } else if (item.certificate === '身份证') {
  237. obj = {
  238. validator: /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/,
  239. message: '身份证格式错误'
  240. }
  241. }
  242. return obj
  243. }
  244. function validatorDefault (item, reg) {
  245. return {
  246. validator: item.val instanceof Array
  247. ? (value, rule) => !!value.length
  248. : reg,
  249. message: item.regexp_message
  250. }
  251. }
  252. edatas.forEach(({ result }, rIndex) => result.forEach((item, index) => {
  253. let k = `${rIndex}_${index}_val`
  254. ruleData[k] = typeof item.val !== 'string'
  255. ? item.val
  256. : item.val.replace(/(^\s+)|(\s+$)/g, '')
  257. let reg = item.reg ? new RegExp(item.reg) : null
  258. rule[k] = [{
  259. required: !!item.required,
  260. message: `必填项\n${item.title}`
  261. }]
  262. if (item.type === 'area') {
  263. rule[k].push(validatorArea(item, reg))
  264. }
  265. else if (item.type === 'certificate') {
  266. rule[k].push(validatorCertificate(item, reg))
  267. }
  268. else if (item.reg) {
  269. rule[k].push(validatorDefault(item, reg))
  270. }
  271. }))
  272. await this.$blRule(ruleData, rule, message => {
  273. this.$toast(message)
  274. })
  275. await this.$dialog.confirm({
  276. title: '提示',
  277. message: '请确认无误提交?',
  278. })
  279. ld = this.$toast.loading({ message: '提交中...', duration: 0 })
  280. if (this.isEdit) {
  281. await new Promise(r => setTimeout(r, 2500))
  282. this.btnOpenSuccess()
  283. throw new Error('模拟提交')
  284. }
  285. let arrData = edatas.map(d => {
  286. let data = JSON.parse(JSON.stringify(d))
  287. data.result.forEach(item => {
  288. let sp = '<#>'
  289. if (item.type === 'area') {
  290. item.val = [item.area, item.val1, item.val2, item.val].map(v => getTrim(v)).join(sp)
  291. }
  292. if (item.type === 'certificate') {
  293. item.val = [item.certificate, item.val].map(v => getTrim(v)).join(sp)
  294. }
  295. })
  296. return data
  297. })
  298. let pms = arrData.map(data => this.btnSubmitItem(data.result, data.query))
  299. let arrRes = await Promise.all(pms)
  300. if (pms.length === 1 && this.$route.query.topic_id == 1) {
  301. let res = arrRes[0]
  302. let { result_id } = res.data
  303. let dt = arrData[0]
  304. callbackSuccess && callbackSuccess(dt)
  305. this.$router.replace({ name: 'FormResult', query: { ...this.$route.query, result_id, jump: undefined, history: undefined } })
  306. } else {
  307. this.btnOpenSuccess(() => this.btnLinkBack())
  308. }
  309. pm = Promise.resolve(arrRes.length > 1 ? arrRes : arrRes[0])
  310. } catch (error) {
  311. pm = Promise.reject()
  312. callbackError && callbackError(error)
  313. }
  314. ld && ld.clear()
  315. this.loading.submit = false
  316. return pm
  317. },
  318. async btnSubmitItem(dataResult, option) {
  319. let pm
  320. dataResult = dataResult || this.data.result
  321. try {
  322. let result = dataResult.map(item => {
  323. return {
  324. detail_id: item.detail_id,
  325. val: item.val
  326. }
  327. })
  328. // 表单类型为 iLeads活动 - 2,时,额外爬取参数 -----------
  329. let patient = {}
  330. if (this.data.topic.flag === 2) {
  331. let config = {
  332. patient_name: new RegExp('姓名'),
  333. patient_mobile: new RegExp('手机号码'),
  334. age: new RegExp('年龄'),
  335. sex: new RegExp('性别'),
  336. birthday: new RegExp('出生日期'),
  337. sight_memo: new RegExp('视力')
  338. }
  339. let keys = Object.keys(config)
  340. let objs = dataResult.map(item => {
  341. let rst = { key: '', val: '' }
  342. keys.some(k => {
  343. let reg = config[k]
  344. if (reg.test(item.title)) {
  345. rst.key = k
  346. rst.val = item.val
  347. return true
  348. }
  349. })
  350. return rst
  351. }).filter(it => it)
  352. objs.forEach(({ key, val }) => {
  353. if (!patient[key]) {
  354. patient[key] = val
  355. }
  356. })
  357. }
  358. // ---------------------------------
  359. let query = {
  360. ...this.$route.query,
  361. ...option,
  362. ...patient,
  363. flag: this.data.topic.flag,
  364. data: JSON.stringify(result)
  365. }
  366. delete query.replace
  367. delete query.to
  368. delete query.go
  369. delete query.ids
  370. delete query.combos
  371. let res = await api.apiPostVolumeInfo(query)
  372. pm = Promise.resolve(res)
  373. } catch (error) {
  374. console.log(error)
  375. pm = Promise.reject(error)
  376. }
  377. return pm
  378. },
  379. btnLinkBack() {
  380. clearInterval(this.codeMess.t)
  381. var ua = navigator.userAgent.toLowerCase();
  382. let { go, replace, to } = this.$route.query
  383. if (replace) {
  384. location.replace(decodeURIComponent(replace))
  385. } else if (to) {
  386. location.href = decodeURIComponent(to)
  387. } else if (go) {
  388. this.$router.go(go)
  389. }
  390. else if (ua.match(/MicroMessenger/i) == "micromessenger") {
  391. this.btnLinkWeChat()
  392. } else {
  393. this.$router.go(-1)
  394. }
  395. },
  396. btnLinkWeChat () {
  397. try {
  398. if (ua.match(/MicroMessenger/i) == "micromessenger") {
  399. //ios的ua中无miniProgram,但都有MicroMessenger(表示是微信浏览器)
  400. wx.miniProgram.getEnv((res) => {
  401. if (res.miniprogram) {
  402. // 在小程序里
  403. console.log('miniprogram')
  404. wx.miniProgram.switchTab({ url: '/pages/index/index' })
  405. }
  406. })
  407. }
  408. } catch (err) {
  409. }
  410. }
  411. }
  412. }