collection.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. <template>
  2. <div class="app-container">
  3. <el-form validate-on-rule-change :rules="rules" ref="form" :model="form" label-width="140px">
  4. <el-form-item label="信息模板" prop="questionId">
  5. <el-select @change="selectQuestion" v-model="form.questionId" placeholder="请选择问答">
  6. <el-option v-for="dict in questionOptions" :key="dict.dictValue" :label="dict.dictLabel"
  7. :value="parseInt(dict.dictValue)" />
  8. </el-select>
  9. </el-form-item>
  10. <!-- 动态渲染问题区域 -->
  11. <div v-if="form.answers && form.answers.length > 0">
  12. <div style="margin-bottom: 20px;margin-top: 20px;" v-for="(answer, index) in form.answers" :key="index">
  13. <div style="margin-bottom: 20px;margin-top: 20px;">
  14. <span style="font-size: 15px;font-weight: bold; margin-left: 31px">{{ answer.title }}</span>
  15. </div>
  16. <div style="margin-left: 31px;">
  17. <el-checkbox-group v-model="answer.value" size="mini">
  18. <el-checkbox v-for="option in answer.options" :key="option.value" :label="option.value">
  19. {{ option.name }}
  20. </el-checkbox>
  21. </el-checkbox-group>
  22. </div>
  23. </div>
  24. </div>
  25. <el-form-item label="用户姓名" prop="userName">
  26. <el-input v-model="form.userName" placeholder="请输入用户姓名"></el-input>
  27. </el-form-item>
  28. <el-form-item label="用户手机号后四位" prop="userPhoneFour">
  29. <el-input v-model="form.userPhoneFour" placeholder="请输入手机号后四位"></el-input>
  30. </el-form-item>
  31. <el-form-item label="用户性别" prop="sex">
  32. <el-select v-model="form.sex" placeholder="请选择用户性别">
  33. <el-option label="男" :value="1" />
  34. <el-option label="女" :value="0" />
  35. </el-select>
  36. </el-form-item>
  37. <el-form-item label="过敏情况" prop="allergy">
  38. <el-input type="textarea" :rows="2" placeholder="请输入过敏情况" v-model="form.allergy">
  39. </el-input>
  40. </el-form-item>
  41. <el-form-item label="备注" prop="remark">
  42. <el-input type="textarea" :rows="2" placeholder="请输入备注" v-model="form.remark">
  43. </el-input>
  44. </el-form-item>
  45. <el-form-item v-if="form.questionId" label="是否关联产品疗法" prop="isPackage">
  46. <el-radio-group v-model="form.isPackage" @change="handleIsPackageChange">
  47. <el-radio :label="0">否</el-radio>
  48. <el-radio :label="1">是</el-radio>
  49. </el-radio-group>
  50. </el-form-item>
  51. <el-form-item v-if="form.isPackage == 1" label="产品疗法" prop="packageId">
  52. <el-select filterable v-model="form.packageId" placeholder="请选择产品疗法">
  53. <el-option v-for="dict in privatePackageOptions" :key="dict.dictValue" :label="dict.dictLabel"
  54. :value="parseInt(dict.dictValue)" />
  55. </el-select>
  56. </el-form-item>
  57. <el-form-item v-if="form.packageId && form.isPackage && form.isPackage == 1" label="支付类型" prop="payType">
  58. <el-radio-group v-model="form.payType">
  59. <el-radio :label="1">全款</el-radio>
  60. <el-radio :label="2">物流代收</el-radio>
  61. </el-radio-group>
  62. </el-form-item>
  63. <el-form-item v-if="form.packageId && form.payType == 2 && form.isPackage && form.isPackage == 1"
  64. label="预付金额" prop="amount">
  65. <el-input v-model="form.amount" placeholder="请输入物流代收金额" type="number" />
  66. </el-form-item>
  67. </el-form>
  68. <div slot="footer" class="dialog-footer">
  69. <el-button type="primary" @click="submitForm">确 定</el-button>
  70. </div>
  71. <el-dialog :title="collectionForm.title" v-if="collectionForm.open" :visible.sync="collectionForm.open"
  72. width="450px" append-to-body>
  73. <div style="padding-bottom:15px;">
  74. <img :src="codeImage" width="400px">
  75. </div>
  76. <div slot="footer" class="dialog-footer">
  77. <el-button @click="downloadImage(codeImage, collectionForm.name + '.png')">下载二维码</el-button>
  78. </div>
  79. </el-dialog>
  80. </div>
  81. </template>
  82. <script>
  83. import { questionOptions, getAnswer } from "@/api/hisStore/answer";
  84. import { allPrivatePackage } from "@/api/store/package";
  85. import { getInfo, addCollection, updateCollection, getWxaCodeCollectionUnLimit } from "@/api/hisStore/collection";
  86. export default {
  87. name: "collection",
  88. components: {},
  89. data() {
  90. // 自定义姓名校验规则
  91. const validateName = (rule, value, callback) => {
  92. if (!value) {
  93. return callback(new Error('请输入用户姓名'));
  94. }
  95. if (value.length < 1 || value.length > 20) {
  96. return callback(new Error('姓名长度在 1 到 20 个字符'));
  97. }
  98. // 校验不能包含数字
  99. const numberRegex = /[0-9]/;
  100. if (numberRegex.test(value)) {
  101. return callback(new Error('姓名不能包含数字'));
  102. }
  103. // 可选:校验只能包含中文、英文和空格
  104. const nameRegex = /^[\u4e00-\u9fa5a-zA-Z\s]+$/;
  105. if (!nameRegex.test(value)) {
  106. return callback(new Error('姓名只能包含中文、英文和空格'));
  107. }
  108. callback();
  109. };
  110. return {
  111. form: {
  112. id: null,
  113. questionId: null,
  114. packageId: null,
  115. payType: null,
  116. amount: null,
  117. isPackage: null,
  118. answers: [],
  119. userName: '',
  120. userPhoneFour: '',
  121. sex: null,
  122. allergy: '',
  123. remark: ''
  124. },
  125. userId: null,
  126. questionOptions: [],
  127. privatePackageOptions: [],
  128. collectionForm: {
  129. open: false,
  130. title: "用户信息采集分享",
  131. name: null,
  132. },
  133. codeImage: null,
  134. rules: {
  135. questionId: [
  136. { required: true, message: '请选择信息模板', trigger: 'change' }
  137. ],
  138. packageId: [
  139. { required: true, message: '请选择套餐包', trigger: 'change' }
  140. ],
  141. isPackage: [
  142. { required: true, message: '请选择是否关联套餐包', trigger: 'change' }
  143. ],
  144. payType: [
  145. { required: true, message: '请选择支付类型', trigger: 'change' }
  146. ],
  147. amount: [
  148. { required: true, message: '请填写物流代收金额', trigger: 'blur' }
  149. ],
  150. userName: [
  151. { required: true, validator: validateName, trigger: 'blur' }
  152. ],
  153. userPhoneFour: [
  154. { required: true, message: '请输入手机号后四位', trigger: 'blur' },
  155. { pattern: /^\d{4}$/, message: '请输入正确的4位数字', trigger: 'blur' }
  156. ],
  157. sex: [
  158. { required: true, message: '请选择用户性别', trigger: 'change' },
  159. {
  160. validator: (rule, value, callback) => {
  161. if (value !== 0 && value !== 1) {
  162. callback(new Error('性别只能为男(1)或女(0)'));
  163. } else {
  164. callback();
  165. }
  166. },
  167. trigger: 'change'
  168. }
  169. ]
  170. }
  171. };
  172. },
  173. created() {
  174. this.getQuestionOptions();
  175. this.getAllPrivatePackge();
  176. },
  177. methods: {
  178. handleIsPackageChange(value) {
  179. if (value === 0) {
  180. this.form.packageId = null;
  181. this.form.payType = null;
  182. this.form.amount = null;
  183. this.$nextTick(() => {
  184. this.$refs.form.clearValidate(['packageId', 'payType', 'amount']);
  185. });
  186. }
  187. },
  188. downloadImage(imageSrc, fileName) {
  189. const link = document.createElement('a');
  190. link.href = imageSrc;
  191. link.download = fileName || '付款二维码.png';
  192. document.body.appendChild(link);
  193. link.click();
  194. document.body.removeChild(link);
  195. },
  196. handleShare(id) {
  197. let loadingRock = this.$loading({
  198. lock: true,
  199. text: '生成二维码中~~请不要刷新页面!!',
  200. spinner: 'el-icon-loading',
  201. background: 'rgba(0, 0, 0, 0.7)'
  202. });
  203. getWxaCodeCollectionUnLimit(id).then(response => {
  204. this.codeImage = response.url
  205. this.collectionForm.open = true;
  206. this.collectionForm.name = id;
  207. loadingRock.close();
  208. }).finally(res => {
  209. loadingRock.close();
  210. })
  211. },
  212. getQuestionOptions() {
  213. questionOptions().then(response => {
  214. this.questionOptions = response.rows;
  215. })
  216. },
  217. getAllPrivatePackge() {
  218. allPrivatePackage().then(res => {
  219. this.privatePackageOptions = res.rows;
  220. })
  221. },
  222. getCollectionInfo(userId) {
  223. this.userId = userId;
  224. getInfo({ userId }).then(res => {
  225. console.log('获取用户采集信息:', res.data); // 调试日志
  226. if (res.data) {
  227. this.processFormData(res.data);
  228. } else {
  229. this.resetFormData();
  230. }
  231. }).catch(error => {
  232. console.error('获取用户采集信息失败:', error);
  233. this.resetFormData();
  234. });
  235. },
  236. processFormData(data) {
  237. // 处理 answers 数据,确保 value 是数组格式
  238. let processedAnswers = [];
  239. if (data.answers && Array.isArray(data.answers)) {
  240. processedAnswers = data.answers.map(answer => ({
  241. ...answer,
  242. value: Array.isArray(answer.value) ? answer.value : []
  243. }));
  244. }
  245. this.form = {
  246. ...this.form,
  247. id: data.id || null,
  248. questionId: data.questionId || null,
  249. packageId: data.packageId || null,
  250. payType: data.payType || null,
  251. amount: data.amount || null,
  252. isPackage: data.isPackage ?? null,
  253. answers: processedAnswers,
  254. userName: data.userName || '',
  255. userPhoneFour: data.userPhoneFour || '',
  256. sex: data.sex ?? null,
  257. allergy: data.allergy || '',
  258. remark: data.remark || ''
  259. };
  260. console.log('处理后的表单数据:', this.form); // 调试日志
  261. },
  262. resetFormData() {
  263. this.form = {
  264. ...this.form,
  265. id: null,
  266. questionId: null,
  267. packageId: null,
  268. payType: null,
  269. amount: null,
  270. isPackage: null,
  271. answers: [],
  272. userName: '',
  273. userPhoneFour: '',
  274. sex: null,
  275. allergy: '',
  276. remark: ''
  277. };
  278. },
  279. //选择问答模板
  280. selectQuestion(val) {
  281. console.log('选择模板:', val); // 调试日志
  282. // 保留用户已填写的基础信息
  283. const preservedFields = {
  284. userName: this.form.userName,
  285. userPhoneFour: this.form.userPhoneFour,
  286. sex: this.form.sex,
  287. allergy: this.form.allergy,
  288. remark: this.form.remark,
  289. };
  290. // 先重置表单
  291. this.form = {
  292. ...preservedFields,
  293. questionId: val,
  294. answers: [],
  295. isPackage: null,
  296. packageId: null,
  297. payType: null,
  298. amount: null,
  299. id: null
  300. };
  301. // 查询该用户+该模板下是否有历史采集记录
  302. if (this.userId && val) {
  303. getInfo({ userId: this.userId, questionId: val }).then(res => {
  304. console.log('查询历史记录:', res.data); // 调试日志
  305. if (res.data) {
  306. this.processFormData(res.data);
  307. }
  308. }).catch(error => {
  309. console.error('查询历史记录失败:', error);
  310. });
  311. }
  312. },
  313. submitForm() {
  314. console.log('提交表单数据:', this.form); // 调试日志
  315. this.form.userId = this.userId;
  316. this.$refs["form"].validate(valid => {
  317. if (valid) {
  318. if (this.form.id != null) {
  319. updateCollection(this.form).then(res => {
  320. this.msgSuccess("修改成功");
  321. this.open = false;
  322. this.$parent.$parent.closeCollection();
  323. this.$refs['form'].resetFields();
  324. this.handleShare(res.data);
  325. })
  326. } else {
  327. addCollection(this.form).then(res => {
  328. this.msgSuccess("添加成功");
  329. this.open = false;
  330. this.$parent.$parent.closeCollection();
  331. this.$refs['form'].resetFields();
  332. this.handleShare(res.data);
  333. })
  334. }
  335. }
  336. });
  337. },
  338. cancel() {
  339. // 取消逻辑
  340. },
  341. },
  342. };
  343. </script>