user-edit.ts 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import tickleBehavior, {
  2. getTickleContext,
  3. } from "../../../../core/behavior/tickle.behavior";
  4. import DictionariesBehavior from "../../../../core/behavior/dictionaries.behavior";
  5. import PageContainerBehavior from "../../../../core/behavior/page-container.behavior";
  6. import { PageLoadBehavior } from "../../../../core/behavior/page-loading.behavior";
  7. import { getUserInfoMethod, updateUserInfoMethod } from "../../request";
  8. // module/user/pages/user-edit/user-edit.ts
  9. Component({
  10. behaviors: [
  11. PageContainerBehavior,
  12. PageLoadBehavior<App.Patient.Model>(getUserInfoMethod),
  13. DictionariesBehavior,
  14. tickleBehavior,
  15. ],
  16. lifetimes: {
  17. attached() {},
  18. },
  19. properties: {},
  20. data: {
  21. model: null as App.Patient.Model | null,
  22. dirty: false,
  23. idCardValid: false,
  24. },
  25. observers: {
  26. 'model.cardno'(value: string) {
  27. const that = this as any;
  28. const v = (value || '').trim();
  29. if (!v) return that.setData({ idCardValid: false });
  30. if (/^\d{17}[\dXx]$/.test(v)) {
  31. const { valid } = (that as any).validateIdCard18(v);
  32. that.setData({ idCardValid: !!valid });
  33. } else {
  34. that.setData({ idCardValid: false });
  35. }
  36. },
  37. },
  38. methods: {
  39. validateIdCard18(cardno: string): { valid: boolean; message?: string } {
  40. const code = (cardno || '').toUpperCase();
  41. if (!/^\d{17}[\dX]$/.test(code)) return { valid: false, message: '身份证号格式不正确' };
  42. const year = parseInt(code.substring(6, 10));
  43. const month = parseInt(code.substring(10, 12));
  44. const day = parseInt(code.substring(12, 14));
  45. const birth = new Date(year, month - 1, day);
  46. if (
  47. birth.getFullYear() !== year ||
  48. birth.getMonth() + 1 !== month ||
  49. birth.getDate() !== day
  50. ) return { valid: false, message: '出生日期无效' };
  51. const Wi = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
  52. const Vi = ['1','0','X','9','8','7','6','5','4','3','2'];
  53. let sum = 0;
  54. for (let i = 0; i < 17; i++) sum += parseInt(code[i]) * Wi[i];
  55. const check = Vi[sum % 11];
  56. if (check !== code[17]) return { valid: false, message: '校验位错误' };
  57. return { valid: true };
  58. },
  59. onFormInput(event: WechatMiniprogram.Input) {
  60. const that = this as any;
  61. const field = (event.currentTarget?.dataset as any)?.field || (event.target?.dataset as any)?.field;
  62. if (!field) return;
  63. const value = (event.detail as any)?.value;
  64. if (field === 'cardno') {
  65. that.updateByCardno(value);
  66. } else if (field === 'age') {
  67. that.setData({ ['model.age']: value });
  68. }
  69. },
  70. onFormChange(event: WechatMiniprogram.CustomEvent) {
  71. const that = this as any;
  72. const { name, value } = (event.detail as any) || {};
  73. if (!name) return;
  74. that.setData({ [`model.${name}`]: value });
  75. },
  76. onSexChange(event: WechatMiniprogram.CustomEvent) {
  77. const that = this as any;
  78. const value = (event as any)?.detail; // field-radio 直接传递选中值
  79. that.setData({ ['model.sex']: value });
  80. },
  81. updateByCardno(cardno?: string) {
  82. const that = this as any;
  83. const normalized = (cardno || '').trim();
  84. that.setData({ ['model.cardno']: normalized });
  85. if (!normalized) {
  86. // 清空身份证:同步清空年龄与性别
  87. return that.setData({ ['model.age']: '', ['model.sex']: '', idCardValid: false });
  88. }
  89. // 仅支持18位身份证解析
  90. if (/^\d{17}[\dXx]$/.test(normalized)) {
  91. const { valid, message } = (this as any).validateIdCard18(normalized);
  92. if (!valid) {
  93. that.setData({ ['model.age']: '', ['model.sex']: '', idCardValid: false });
  94. return getTickleContext.call(that).showWarnMessage(message || '身份证号不合法');
  95. }
  96. const year = parseInt(normalized.substring(6, 10));
  97. const month = parseInt(normalized.substring(10, 12));
  98. const day = parseInt(normalized.substring(12, 14));
  99. const birth = new Date(year, month - 1, day);
  100. const now = new Date();
  101. let age = now.getFullYear() - birth.getFullYear();
  102. const m = now.getMonth() - birth.getMonth();
  103. if (m < 0 || (m === 0 && now.getDate() < birth.getDate())) age--;
  104. const sexCode = parseInt(normalized.substring(16, 17));
  105. // 字典通常 0=男 1=女 或 1=女? 需与现有校验一致:文件中 womenSpecialPeriod 用 sex==='1' 判断为女性
  106. const sex = sexCode % 2 === 0 ? '1' : '0';
  107. that.setData({ ['model.age']: age, ['model.sex']: sex, idCardValid: true });
  108. } else {
  109. // 未满18位时,实时清空由身份证推导的年龄/性别,保持可编辑
  110. that.setData({ ['model.age']: '', ['model.sex']: '', idCardValid: false });
  111. }
  112. },
  113. async onSubmit(event: WechatMiniprogram.FormSubmit) {
  114. const that = this as any;
  115. const submitBtn = that.selectComponent("#submitBtn");
  116. that.setData({ dirty: true });
  117. const data = { ...(that.data.model || {}), ...event.detail.value } as any;
  118. // 如填写了身份证,进行18位身份证合法性校验
  119. if (data.cardno) {
  120. const { valid, message } = (this as any).validateIdCard18((data.cardno || '').toString());
  121. if (!valid) {
  122. if (submitBtn) submitBtn.resetState();
  123. return getTickleContext.call(that).showWarnMessage(message || '身份证号不合法');
  124. }
  125. }
  126. // 必填:年龄、性别
  127. if (!data.age) {
  128. if (submitBtn) submitBtn.resetState();
  129. return getTickleContext.call(that).showWarnMessage("请填写年龄");
  130. }
  131. if (data.sex === undefined || data.sex === null || data.sex === '') {
  132. if (submitBtn) submitBtn.resetState();
  133. return getTickleContext.call(that).showWarnMessage("请选择性别");
  134. }
  135. if (!data.patientId) data.patientId = wx.getStorageSync("patientId");
  136. // 表单验证
  137. if (data.sex.toString() === "1" && !data.womenSpecialPeriod) {
  138. if (submitBtn) submitBtn.resetState();
  139. return getTickleContext
  140. .call(that)
  141. .showWarnMessage("请至少选择一项女性特殊期");
  142. }
  143. if (!data.height) {
  144. if (submitBtn) submitBtn.resetState();
  145. return getTickleContext.call(that).showWarnMessage("请填写身高");
  146. }
  147. if (!data.weight) {
  148. if (submitBtn) submitBtn.resetState();
  149. return getTickleContext.call(that).showWarnMessage("请填写体重");
  150. }
  151. try {
  152. await updateUserInfoMethod(<any>data)
  153. .then(() => wx.navigateBack())
  154. .then(() => {
  155. that.getOpenerEventChannel().emit("update2", event.detail.value);
  156. })
  157. .catch((error) => {
  158. if (submitBtn) {
  159. submitBtn.resetState();
  160. }
  161. const msg = (error as any)?.errMsg || '更新失败';
  162. getTickleContext.call(that).showWarnMessage(msg);
  163. });
  164. } catch (error) {
  165. if (submitBtn) submitBtn.resetState();
  166. const msg = (error as any)?.errMsg || '更新失败';
  167. getTickleContext.call(that).showWarnMessage(msg);
  168. }
  169. },
  170. },
  171. });