index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. <template>
  2. <view class="container main">
  3. <view class="one">
  4. <view class="register" v-if="!user.id">
  5. <uni-forms ref="baseForm" :rules="rules" :modelValue="form" label-width="80px">
  6. <uni-forms-item label="账号" required name="account">
  7. <uni-easyinput v-model="form.account" placeholder="请输入账号" />
  8. </uni-forms-item>
  9. <uni-forms-item label="密码" required name="password">
  10. <uni-easyinput type="password" v-model="form.password" placeholder="请输入密码" />
  11. </uni-forms-item>
  12. <uni-forms-item label="确认密码" required name="ispassword">
  13. <uni-easyinput type="password" v-model="form.ispassword" placeholder="请输入确认密码" />
  14. </uni-forms-item>
  15. <uni-forms-item label="手机号" required name="phone">
  16. <uni-easyinput v-model="form.phone" placeholder="请输入手机号" />
  17. </uni-forms-item>
  18. <uni-forms-item label="电子邮箱">
  19. <uni-easyinput v-model="form.email" placeholder="请输入电子邮箱" />
  20. </uni-forms-item>
  21. </uni-forms>
  22. </view>
  23. <view class="list" v-for="(item, index) in investigate" :key="index">
  24. <div class="problem">
  25. <text v-if="item.is_must=='0'" class="t-icon t-icon-xinghao"></text>
  26. <span v-if="item.is_must=='0'">{{item.problem}}</span>
  27. <span style="margin: 0 0 0 2vw;" v-else>{{item.problem}}</span>
  28. </div>
  29. <div class="type" v-if="item.type =='0'">
  30. <div class="remark" v-if="item.remark">{{item.remark}}</div>
  31. <uni-data-checkbox v-model="item.reply" :localdata="item.answer"
  32. :map="{text:'text',value:'text'}" />
  33. <div v-if="errors[item.problem]" class="error-message">{{ errors[item.problem] }}</div>
  34. </div>
  35. <div class="type" v-if="item.type =='1'">
  36. <div class="remark" v-if="item.remark">{{item.remark}}</div>
  37. <uni-data-checkbox v-model="item.reply" multiple :localdata="item.answer"
  38. :map="{text:'text',value:'text'}" />
  39. <div v-if="errors[item.problem]" class="error-message">{{ errors[item.problem] }}</div>
  40. </div>
  41. <div class="type" v-if="item.type =='2'">
  42. <div class="remark" v-if="item.remark">{{item.remark}}</div>
  43. <uni-data-select v-model="item.reply" :localdata="item.answer"></uni-data-select>
  44. <div v-if="errors[item.problem]" class="error-message">{{ errors[item.problem] }}</div>
  45. </div>
  46. <div class="type" v-if="item.type =='3'">
  47. <div class="remark" v-if="item.remark">{{item.remark}}</div>
  48. <uni-easyinput v-model="item.reply" type="number"
  49. :placeholder="getField(item.problem)"></uni-easyinput>
  50. <div v-if="errors[item.problem]" class="error-message">{{ errors[item.problem] }}</div>
  51. </div>
  52. <div class="type" v-if="item.type =='4'">
  53. <div class="remark" v-if="item.remark">{{item.remark}}</div>
  54. <uni-easyinput v-model="item.reply" :placeholder="getField(item.problem)"></uni-easyinput>
  55. <div v-if="errors[item.problem]" class="error-message">{{ errors[item.problem] }}</div>
  56. </div>
  57. <div class="type" v-if="item.type =='5'">
  58. <div class="remark" v-if="item.remark">{{item.remark}}</div>
  59. <uni-easyinput type="textarea" v-model="item.reply"
  60. :placeholder="getField(item.problem)"></uni-easyinput>
  61. <div v-if="errors[item.problem]" class="error-message">{{ errors[item.problem] }}</div>
  62. </div>
  63. <div class="type" v-if="item.type =='6'">
  64. <div class="remark" v-if="item.remark">{{item.remark}}</div>
  65. <upload class='upload' :list="item.reply" name="reply" :count="1" @uplSuc="uplSuc($event,item)"
  66. @uplDel="uplDel($event,item)">
  67. </upload>
  68. <div v-if="errors[item.problem]" class="error-message">{{ errors[item.problem] }}</div>
  69. </div>
  70. <div class="type" v-if="item.type =='7'">
  71. <div class="list">
  72. <div v-for="(aa, ina) in item.answer" :key="ina" class="name">{{aa.text}}</div>
  73. </div>
  74. <div class="list" v-for="(gg, inx) in item.reply" :key="inx">
  75. <div v-for="(aa, ina) in item.answer" :key="ina" class="input">
  76. <uni-easyinput v-model="gg[aa.text]" :clearable="false"
  77. :placeholder="getField(aa.text)"></uni-easyinput>
  78. </div>
  79. <uni-icons @tap="toDel(item,gg.sid)" class="icon" type="closeempty" size="20"></uni-icons>
  80. </div>
  81. <div class="add" @tap="toAdd(item)">+新增一行</div>
  82. <div v-if="errors[item.problem]" class="error-message">{{ errors[item.problem] }}</div>
  83. </div>
  84. <div class="type" v-if="item.type =='8'">
  85. <image class="image" v-if="item.answer&&item.answer.length>0" v-for="(as, img) in item.answer"
  86. :key="img" :src="getUrl(as.url)"></image>
  87. <div class="remark" v-if="item.remark">{{item.remark}}</div>
  88. </div>
  89. </view>
  90. <view class="button">
  91. <button type="warn" @tap="toSave">保存</button>
  92. </view>
  93. </view>
  94. </view>
  95. </template>
  96. <script>
  97. import upload from '../../components/upload/index.vue';
  98. import moment from 'moment';
  99. export default {
  100. components: {
  101. upload
  102. },
  103. data() {
  104. return {
  105. openid: "",
  106. id: '',
  107. user: {},
  108. info: {},
  109. investigate: [],
  110. form: {
  111. gender: '0',
  112. account: '',
  113. password: '',
  114. ispassword: '',
  115. email: '',
  116. role: ['User']
  117. },
  118. // 校验规则
  119. rules: {
  120. account: {
  121. rules: [{
  122. required: true,
  123. errorMessage: '账号不能为空'
  124. }]
  125. },
  126. password: {
  127. rules: [{
  128. required: true,
  129. errorMessage: '密码不能为空'
  130. }, {
  131. validateFunction: function(rule, value, data, callback) {
  132. const reg =
  133. /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[._~!@#$^&*])[A-Za-z0-9._~!@#$^&*]{8,16}$/g
  134. if (!reg.test(value)) {
  135. callback('请输入包含英文字母大小写、数字和特殊符号的 8-16 位组合')
  136. }
  137. return true
  138. }
  139. }]
  140. },
  141. ispassword: {
  142. rules: [{
  143. required: true,
  144. errorMessage: '确认密码不能为空'
  145. },
  146. {
  147. validateFunction: function(rule, value, data, callback) {
  148. if (value != data.password) {
  149. callback('两次输入的密码必须相同')
  150. }
  151. return true
  152. }
  153. }
  154. ]
  155. },
  156. phone: {
  157. rules: [{
  158. required: true,
  159. errorMessage: '手机号不能为空'
  160. }, {
  161. validateFunction: function(rule, value, data, callback) {
  162. const reg = /^1[3-9]\d{9}$/
  163. if (!reg.test(value)) {
  164. callback('请输入正确的手机号')
  165. }
  166. return true
  167. }
  168. }]
  169. },
  170. },
  171. errors: {}
  172. }
  173. },
  174. onLoad: async function(e) {
  175. const that = this;
  176. that.$set(that, `id`, e && e.id || '');
  177. await that.searchOpenids();
  178. await that.searchToken();
  179. await that.search();
  180. },
  181. onReady() {
  182. // 需要在onReady中设置规则
  183. this.$refs.baseForm.setRules(this.rules)
  184. },
  185. methods: {
  186. async searchOpenids() {
  187. const that = this;
  188. uni.getStorage({
  189. key: 'openid',
  190. success: function(res) {
  191. that.$set(that, `openid`, res.data);
  192. },
  193. fail: function(err) {
  194. uni.login({
  195. success: async function(res) {
  196. if (res.code) {
  197. const aee = await that.$app('/wechat/api/login/app',
  198. 'GET', {
  199. js_code: res.code,
  200. config: that.$config.wx_projectkey
  201. })
  202. if (aee.errcode == '0') {
  203. uni.setStorage({
  204. key: "openid",
  205. data: aee.data.openid
  206. })
  207. that.$set(that, `openid`, aee.data.openid);
  208. } else {
  209. uni.showToast({
  210. title: aee.errmsg,
  211. icon: 'none'
  212. })
  213. }
  214. } else {
  215. uni.showToast({
  216. title: res.errMsg,
  217. icon: 'none'
  218. })
  219. }
  220. }
  221. });
  222. }
  223. })
  224. },
  225. // 用户信息
  226. searchToken() {
  227. const that = this;
  228. try {
  229. const res = uni.getStorageSync('token');
  230. if (res) {
  231. const user = that.$jwt(res);
  232. that.$set(that, `user`, user);
  233. }
  234. } catch (e) {}
  235. },
  236. // 查询
  237. async search() {
  238. const that = this;
  239. if (that.id) {
  240. let res;
  241. res = await that.$api(`/match/${that.id}`, 'GET', {})
  242. if (res.errcode == '0') {
  243. that.$set(that, `info`, res.data)
  244. if (res.data.ext_info && res.data.ext_info.length > 0) {
  245. for (let val of res.data.ext_info) {
  246. if (val.type == '2') {
  247. for (let s of val.answer) {
  248. s.value = s.text
  249. }
  250. }
  251. }
  252. that.$set(that, `investigate`, res.data.ext_info)
  253. }
  254. } else {
  255. uni.showToast({
  256. title: res.errmsg,
  257. icon: 'none'
  258. });
  259. }
  260. }
  261. },
  262. getField(data) {
  263. let res = "请输入内容"
  264. if (data) res = `请输入${data}`
  265. return res
  266. },
  267. // 图片处理
  268. getUrl(e) {
  269. const that = this;
  270. if (e) return that.$config.serverFile + e
  271. },
  272. // 图片上传
  273. uplSuc(e, item) {
  274. const that = this;
  275. for (let val of that.investigate) {
  276. if (val.sid == item.sid) val.reply = [e.data]
  277. }
  278. },
  279. // 图片删除
  280. uplDel(e, item) {
  281. const that = this;
  282. for (let val of that.investigate) {
  283. if (val.sid == item.sid) val.reply = []
  284. }
  285. },
  286. // 新增一行
  287. toAdd(item) {
  288. const that = this;
  289. for (let val of that.investigate) {
  290. if (val.sid == item.sid) {
  291. let answer = []
  292. let obj = {
  293. sid: moment().valueOf(),
  294. }
  295. for (let s of val.answer) {
  296. obj[s.text] = '';
  297. }
  298. answer.push(obj)
  299. if (val.reply) val.reply = [...val.reply, ...answer, ]
  300. else val.reply = answer
  301. }
  302. }
  303. },
  304. // 删除一行
  305. toDel(item, sid) {
  306. const that = this;
  307. if (item && item.reply && item.reply.length > 0) {
  308. let answer = item.reply.filter((i) => i.sid != sid)
  309. for (let val of that.investigate) {
  310. if (val.sid == item.sid) {
  311. val.reply = answer
  312. }
  313. }
  314. }
  315. },
  316. // 自定义的验证函数
  317. validateObject(arr) {
  318. const errors = {};
  319. for (const obj of arr) {
  320. if (obj.is_must == '0') {
  321. if (!obj.reply || obj.reply.length == 0) {
  322. if (obj.type == '0' || obj.type == '1' || obj.type == '1') errors[obj.problem] =
  323. `请选择${obj.problem}`
  324. else if (obj.type == '6') errors[obj.problem] = `请上传${obj.problem}`
  325. else errors[obj.problem] = `请填写${obj.problem}`
  326. }
  327. }
  328. }
  329. // 如果有错误,返回错误对象
  330. if (Object.keys(errors).length > 0) {
  331. return errors
  332. }
  333. // 如果没有错误,返回null或undefined
  334. return null
  335. },
  336. async toSave() {
  337. const that = this;
  338. const errorsInfo = await that.validateObject(that.investigate)
  339. // 检查是否有错误
  340. if (errorsInfo) {
  341. that.$set(that, `errors`, errorsInfo)
  342. // 遍历错误对象并显示错误信息
  343. for (const key in errorsInfo) {
  344. if (errorsInfo.hasOwnProperty(key)) {
  345. console.error(`${key} 错误: ${errorsInfo[key]}`);
  346. }
  347. }
  348. } else {
  349. that.$set(that, `errors`, {})
  350. let data = {
  351. match_id: that.info.id,
  352. info: that.investigate
  353. }
  354. if (that.user.id) {
  355. data.user_id = that.user.id
  356. const res = await that.$api(`/matchReg`, 'POST', data)
  357. if (res.errcode == '0') {
  358. uni.showModal({
  359. content: "调查问卷填写成功!",
  360. showCancel: false
  361. });
  362. uni.navigateBack({
  363. delta: 1
  364. })
  365. } else {
  366. uni.showToast({
  367. title: res.errmsg,
  368. icon: 'none'
  369. });
  370. }
  371. } else {
  372. that.$refs.baseForm.validate().then(async ass => {
  373. if (ass.password == ass.ispassword) {
  374. ass.openid = that.openid
  375. data.user = {
  376. nick_name: ass.account,
  377. ...that.form,
  378. ...ass
  379. }
  380. const res = await that.$api(`/matchReg`, 'POST', data)
  381. if (res.errcode == '0') {
  382. uni.showModal({
  383. content: "调查问卷填写成功!",
  384. showCancel: false
  385. });
  386. uni.navigateBack({
  387. delta: 1
  388. })
  389. } else {
  390. uni.showToast({
  391. title: res.errmsg,
  392. icon: 'none'
  393. });
  394. }
  395. } else {
  396. uni.showToast({
  397. title: `密码不一致`,
  398. icon: 'error'
  399. });
  400. return;
  401. }
  402. }).catch(err => {
  403. console.log('err', err);
  404. return;
  405. })
  406. }
  407. }
  408. },
  409. }
  410. }
  411. </script>
  412. <style lang="scss" scoped>
  413. .main {
  414. .one {
  415. padding: 2vw;
  416. .list {
  417. .problem {
  418. display: flex;
  419. align-items: center;
  420. .t-icon {
  421. width: 30px !important;
  422. height: 30px !important;
  423. }
  424. }
  425. .type {
  426. padding: 2vw 0 2vw 2vw;
  427. .list {
  428. display: flex;
  429. align-items: center;
  430. justify-content: center;
  431. margin: 2vw 0;
  432. .name {
  433. width: 50%;
  434. text-align: center;
  435. }
  436. .input {
  437. margin: 0 1vw 0 0;
  438. .name {
  439. width: 50%;
  440. text-align: center;
  441. margin: 0 0 2vw 0;
  442. }
  443. }
  444. .icon {
  445. display: none;
  446. margin: 1vw 0 0 0;
  447. }
  448. }
  449. .list:hover {
  450. .icon {
  451. display: block;
  452. }
  453. }
  454. .add {
  455. border: 1px solid #e5e5e5;
  456. border-radius: 5px;
  457. text-align: center;
  458. padding: 2vw;
  459. }
  460. .image {
  461. width: 96%;
  462. }
  463. .error-message {
  464. text-align: left;
  465. margin: 5px 0 0 8px;
  466. color: var(--fF0Color);
  467. font-size: var(--font12Size);
  468. }
  469. .remark {
  470. margin: 2vw;
  471. font-size: 12px;
  472. color: red;
  473. }
  474. }
  475. }
  476. .button {
  477. margin: 2vw 0 0 0;
  478. padding: 2vw;
  479. text-align: center;
  480. button {
  481. background-color: var(--f3CColor);
  482. font-size: var(--font14Size);
  483. border-radius: 2vw;
  484. }
  485. }
  486. }
  487. }
  488. </style>