add_member.js 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. const app = getApp();
  2. Page({
  3. data: {
  4. formData: {
  5. name: '',
  6. simplified_name: '',
  7. sex: '1',
  8. birthday: '',
  9. family_rank: '',
  10. name_word_generation: '',
  11. is_pass_away: 0,
  12. marital_status: 0,
  13. relation_type: '',
  14. sub_relation_type: '',
  15. former_name: '',
  16. phone: '',
  17. notes: ''
  18. },
  19. selectedMemberName: '',
  20. selectedMemberId: '',
  21. showDuplicateModal: false,
  22. duplicateMembers: [],
  23. showMemberDetailModal: false,
  24. selectedMemberDetail: null,
  25. isPassAwayOptions: ['健在', '已故', '未知'],
  26. maritalStatusOptions: ['未知', '未婚', '已婚', '离异/丧偶'],
  27. relationTypeOptions: ['父子 (关联人为父)', '母子 (关联人为母)', '夫妻', '兄弟', '姐妹'],
  28. subRelationTypeOptions: ['亲生/正妻', '养父', '出继(亲生父母)', '入继(养父母)', '妾', '外室'],
  29. showMemberSearch: false,
  30. memberSearchKeyword: '',
  31. memberSearchResults: [],
  32. memberSearchLoading: false
  33. },
  34. onLoad: function () {
  35. // 不自动登录,在需要时登录
  36. },
  37. // 输入处理
  38. onNameInput: function (e) {
  39. this.setData({
  40. 'formData.name': e.detail.value
  41. });
  42. // 输入姓名后自动检查同名
  43. if (e.detail.value.length >= 2) {
  44. this.checkDuplicate(e.detail.value);
  45. }
  46. },
  47. onSimplifiedNameInput: function (e) {
  48. this.setData({
  49. 'formData.simplified_name': e.detail.value
  50. });
  51. },
  52. selectSex: function (e) {
  53. this.setData({
  54. 'formData.sex': e.currentTarget.dataset.value
  55. });
  56. },
  57. onBirthdayChange: function (e) {
  58. this.setData({
  59. 'formData.birthday': e.detail.value
  60. });
  61. },
  62. onFamilyRankInput: function (e) {
  63. this.setData({
  64. 'formData.family_rank': e.detail.value
  65. });
  66. },
  67. onGenerationInput: function (e) {
  68. this.setData({
  69. 'formData.name_word_generation': e.detail.value
  70. });
  71. },
  72. onIsPassAwayChange: function (e) {
  73. this.setData({
  74. 'formData.is_pass_away': parseInt(e.detail.value)
  75. });
  76. },
  77. onMaritalStatusChange: function (e) {
  78. this.setData({
  79. 'formData.marital_status': parseInt(e.detail.value)
  80. });
  81. },
  82. onRelationTypeChange: function (e) {
  83. this.setData({
  84. 'formData.relation_type': e.detail.value
  85. });
  86. },
  87. onSubRelationTypeChange: function (e) {
  88. this.setData({
  89. 'formData.sub_relation_type': e.detail.value
  90. });
  91. },
  92. onFormerNameInput: function (e) {
  93. this.setData({
  94. 'formData.former_name': e.detail.value
  95. });
  96. },
  97. onPhoneInput: function (e) {
  98. this.setData({
  99. 'formData.phone': e.detail.value
  100. });
  101. },
  102. onNotesInput: function (e) {
  103. this.setData({
  104. 'formData.notes': e.detail.value
  105. });
  106. },
  107. // 检查同名成员
  108. checkDuplicate: function (name) {
  109. wx.request({
  110. url: `${app.globalData.baseUrl}/api/members/check_duplicate`,
  111. method: 'GET',
  112. data: {
  113. name: name
  114. },
  115. success: (res) => {
  116. if (res.data.success && res.data.data.length > 0) {
  117. this.setData({
  118. duplicateMembers: res.data.data,
  119. showDuplicateModal: true
  120. });
  121. }
  122. },
  123. fail: () => {
  124. console.log('检查同名失败');
  125. }
  126. });
  127. },
  128. // 打开关联成员搜索弹层
  129. selectRelatedMember: function () {
  130. this.setData({
  131. showMemberSearch: true,
  132. memberSearchKeyword: '',
  133. memberSearchResults: []
  134. });
  135. },
  136. closeMemberSearch: function () {
  137. this.setData({ showMemberSearch: false });
  138. },
  139. onMemberSearchInput: function (e) {
  140. this.setData({ memberSearchKeyword: e.detail.value });
  141. },
  142. doMemberSearch: function () {
  143. const keyword = this.data.memberSearchKeyword.trim();
  144. if (!keyword) {
  145. wx.showToast({ title: '请输入姓名搜索', icon: 'none' });
  146. return;
  147. }
  148. this.setData({ memberSearchLoading: true, memberSearchResults: [] });
  149. wx.request({
  150. url: `${app.globalData.baseUrl}/api/members/search`,
  151. method: 'GET',
  152. header: { 'Authorization': `Bearer ${app.globalData.token}` },
  153. data: { keyword },
  154. success: (res) => {
  155. this.setData({ memberSearchLoading: false });
  156. if (res.data && res.data.success) {
  157. const results = res.data.data || [];
  158. if (results.length === 0) {
  159. wx.showToast({ title: '未找到匹配成员', icon: 'none' });
  160. }
  161. this.setData({ memberSearchResults: results });
  162. } else {
  163. wx.showToast({ title: '搜索失败', icon: 'none' });
  164. }
  165. },
  166. fail: () => {
  167. this.setData({ memberSearchLoading: false });
  168. wx.showToast({ title: '网络请求失败', icon: 'none' });
  169. }
  170. });
  171. },
  172. confirmSelectMember: function (e) {
  173. const member = e.currentTarget.dataset.member;
  174. this.setData({
  175. selectedMemberId: member.id,
  176. selectedMemberName: member.name + (member.simplified_name ? `(${member.simplified_name})` : ''),
  177. showMemberSearch: false
  178. });
  179. },
  180. clearSelectedMember: function () {
  181. this.setData({ selectedMemberId: '', selectedMemberName: '' });
  182. },
  183. // 关闭同名弹窗
  184. closeDuplicateModal: function () {
  185. this.setData({
  186. showDuplicateModal: false
  187. });
  188. },
  189. // 查看成员详情(可从搜索结果或同名列表进入)
  190. viewMemberDetail: function (e) {
  191. const member = e.currentTarget.dataset.member;
  192. wx.request({
  193. url: `${app.globalData.baseUrl}/api/members/${member.id}`,
  194. method: 'GET',
  195. header: { 'Authorization': `Bearer ${app.globalData.token}` },
  196. success: (res) => {
  197. if (res.data && res.data.success) {
  198. this.setData({
  199. selectedMemberDetail: res.data.data,
  200. // 记录是否从搜索弹层打开,用于"选择此人"回填
  201. _detailFromSearch: this.data.showMemberSearch,
  202. showMemberDetailModal: true,
  203. showDuplicateModal: false
  204. });
  205. } else {
  206. wx.showToast({ title: '获取详情失败', icon: 'none' });
  207. }
  208. },
  209. fail: () => {
  210. wx.showToast({ title: '网络请求失败', icon: 'none' });
  211. }
  212. });
  213. },
  214. // 在详情弹层中直接选择此人作为关联成员
  215. selectFromDetail: function () {
  216. const m = this.data.selectedMemberDetail;
  217. if (!m) return;
  218. this.setData({
  219. selectedMemberId: m.id,
  220. selectedMemberName: m.name + (m.simplified_name ? `(${m.simplified_name})` : ''),
  221. showMemberDetailModal: false,
  222. showMemberSearch: false
  223. });
  224. },
  225. // 关闭成员详情弹窗
  226. closeMemberDetailModal: function () {
  227. this.setData({
  228. showMemberDetailModal: false,
  229. selectedMemberDetail: null
  230. });
  231. },
  232. // 放弃录入
  233. abortEntry: function () {
  234. wx.navigateBack();
  235. },
  236. // 阻止事件冒泡
  237. stopPropagation: function () {},
  238. // 提交表单
  239. submitForm: function () {
  240. const { formData } = this.data;
  241. // 验证必填字段
  242. if (!formData.name.trim()) {
  243. wx.showToast({
  244. title: '请输入姓名(繁体)',
  245. icon: 'none'
  246. });
  247. return;
  248. }
  249. if (!formData.birthday) {
  250. wx.showToast({
  251. title: '请选择出生日期',
  252. icon: 'none'
  253. });
  254. return;
  255. }
  256. wx.showLoading({
  257. title: '提交中...'
  258. });
  259. wx.request({
  260. url: `${app.globalData.baseUrl}/api/members/add`,
  261. method: 'POST',
  262. header: {
  263. 'Content-Type': 'application/json',
  264. 'Authorization': `Bearer ${app.globalData.token}`
  265. },
  266. data: {
  267. name: formData.name,
  268. simplified_name: formData.simplified_name,
  269. sex: parseInt(formData.sex),
  270. birthday: formData.birthday,
  271. family_rank: formData.family_rank,
  272. name_word_generation: formData.name_word_generation,
  273. is_pass_away: formData.is_pass_away,
  274. marital_status: formData.marital_status,
  275. former_name: formData.former_name,
  276. phone: formData.phone,
  277. notes: formData.notes,
  278. relations: this.data.selectedMemberId ? [{
  279. parent_mid: this.data.selectedMemberId,
  280. relation_type: parseInt(formData.relation_type) || 1,
  281. sub_relation_type: parseInt(formData.sub_relation_type) || 0
  282. }] : []
  283. },
  284. success: (res) => {
  285. wx.hideLoading();
  286. if (res.data.success) {
  287. wx.showToast({
  288. title: '录入成功',
  289. icon: 'success'
  290. });
  291. setTimeout(() => {
  292. wx.navigateBack();
  293. }, 1500);
  294. } else {
  295. wx.showToast({
  296. title: res.data.message || '录入失败',
  297. icon: 'none'
  298. });
  299. }
  300. },
  301. fail: () => {
  302. wx.hideLoading();
  303. wx.showToast({
  304. title: '网络异常',
  305. icon: 'none'
  306. });
  307. }
  308. });
  309. }
  310. });