message-select.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. // module/chats/components/message-select/message-select.ts
  2. interface Option {
  3. id: string;
  4. name: string;
  5. checked?: boolean;
  6. options: Option[] | null;
  7. }
  8. interface HandleEvent {
  9. mark: {
  10. type: "sub" | "options";
  11. index: number;
  12. item: Option;
  13. };
  14. }
  15. Component({
  16. properties: {
  17. payload: {
  18. type: Object,
  19. value: { title: "", multiple: false, options: [] },
  20. result: "",
  21. belongNew: null,
  22. },
  23. active: { type: Boolean, value: false },
  24. },
  25. data: {
  26. options: [] as Option[],
  27. subOptions: [] as Option[],
  28. subMultiple: false,
  29. itemHeight: 48,
  30. result: "",
  31. hasSelected: false,
  32. leftTitle: "都没有",
  33. rightTitle: "提交",
  34. },
  35. lifetimes: {
  36. attached() {
  37. console.log("attached", this.data.payload.belongNew,this.data.payload);
  38. if (this.data.payload.belongNew) {
  39. this.setData({
  40. leftTitle: "都没有",
  41. rightTitle: "提交",
  42. });
  43. } else {
  44. this.setData({
  45. leftTitle: "无变化",
  46. rightTitle: "完成",
  47. });
  48. }
  49. },
  50. },
  51. observers: {
  52. "payload.options"(options) {
  53. this.setData({ options });
  54. },
  55. options(options: AnyArray) {
  56. this.setData({
  57. hasSelected: options
  58. .filter((option) => !option.hide)
  59. .some((option) => option.checked),
  60. });
  61. },
  62. },
  63. methods: {
  64. handleTop(event: HandleEvent) {
  65. const {
  66. mark: { item },
  67. } = event;
  68. console.log("handleTop", item, this.data.active);
  69. if (!item || !this.data.active) return;
  70. console.log("handleTop", this.data.subOptions);
  71. const index = this.data.options.findIndex(
  72. (option) => option.id === item.id
  73. );
  74. // 如果当前项已选中且已有已选中的子项,则直接弹出子项程度选择弹窗以便修改
  75. const itemInState: any = this.data.options[index];
  76. const hasSubOptions = itemInState?.options?.filter(
  77. (o: any) => !o?.hide
  78. ).length;
  79. const hasAnySubChecked = itemInState?.options?.some(
  80. (o: any) => o?.checked
  81. );
  82. if (itemInState?.checked && hasSubOptions && hasAnySubChecked) {
  83. this.setData({
  84. subTitle: itemInState.name,
  85. subOptions: itemInState.options,
  86. subMultiple: itemInState.css === "checkbox",
  87. });
  88. this.onCancel = () => {
  89. this.setData({ subOptions: [] });
  90. };
  91. this.onConfirm = () => {
  92. if (!this.data.subOptions.some((option) => option.checked)) {
  93. wx.showToast({ title: "请至少选择一项", icon: "error" });
  94. } else {
  95. const options = this.data.options;
  96. options[index].options = this.data.subOptions;
  97. this.setData({ subOptions: [], options });
  98. // 单选场景:选择/修改子程度后直接提交
  99. if (!this.data.payload.multiple) {
  100. this.onSubmit();
  101. }
  102. }
  103. };
  104. return;
  105. }
  106. const multiple = this.data.payload.multiple;
  107. const checked = !item.checked;
  108. const options = this._handle(this.data.options, item, index, multiple);
  109. this.setData({ options });
  110. // 注释掉自动提交的逻辑,让用户可以继续选择症状程度
  111. if (checked && !multiple) {
  112. this.onSubmit();
  113. }
  114. },
  115. handleSub(event: HandleEvent) {
  116. const {
  117. mark: { item },
  118. } = event;
  119. console.log("handleSub", item, this.data.active);
  120. if (!item || !this.data.active) return;
  121. console.log("this.data.subOptions", this.data.subOptions);
  122. const index = this.data.subOptions.findIndex(
  123. (option) => option.id === item.id
  124. );
  125. console.log("index", index);
  126. const multiple = this.data.subMultiple;
  127. const checked = !item.checked;
  128. const subOptions = this._handle(
  129. this.data.subOptions,
  130. item,
  131. index,
  132. multiple
  133. );
  134. this.setData({ subOptions });
  135. console.log(this.data.subOptions, "suboptions111");
  136. // 检查是否所有症状程度都被取消选中
  137. const hasAnySubChecked = subOptions.some((option) => option.checked);
  138. if (!hasAnySubChecked) {
  139. // 如果没有任何症状程度被选中,则取消整个症状的选中状态
  140. const mainIndex = this.data.options.findIndex(
  141. (option) => option.name === this.data.subTitle
  142. );
  143. if (mainIndex !== -1) {
  144. const options = this.data.options;
  145. options[mainIndex].checked = false;
  146. options[mainIndex].options = options[mainIndex].options?.map(
  147. (option: any) => {
  148. if (!option?.hide) option.checked = false;
  149. return option;
  150. }
  151. );
  152. // 关闭当前弹窗,避免遮挡导致切换其它症状时看起来未选中
  153. this.setData({ options, subOptions: [], subTitle: "" });
  154. return;
  155. }
  156. }
  157. // 注释掉自动关闭弹窗的逻辑,让用户可以继续修改症状程度
  158. if (checked && !multiple) {
  159. this.onConfirm();
  160. }
  161. },
  162. _handle(
  163. options: Option[],
  164. item: Option,
  165. index: number,
  166. multiple?: boolean
  167. ) {
  168. const checked = !item.checked;
  169. if (checked) {
  170. const fn = () => {
  171. if (multiple) {
  172. options[index].checked = checked;
  173. } else {
  174. options.forEach((option) => {
  175. option.checked = option.id === item.id;
  176. });
  177. }
  178. return options;
  179. };
  180. if (item.options?.filter((option) => !(<any>option)?.hide).length) {
  181. this.setData({
  182. subTitle: item.name,
  183. subOptions: item.options,
  184. subMultiple: (<any>item).css === "checkbox",
  185. });
  186. this.onCancel = () => {
  187. this.setData({ subOptions: [] });
  188. };
  189. this.onConfirm = () => {
  190. if (!this.data.subOptions.some((option) => option.checked)) {
  191. wx.showToast({ title: "请至少选择一项", icon: "error" });
  192. } else {
  193. const options = fn();
  194. options[index].options = this.data.subOptions;
  195. this.setData({ subOptions: [], options });
  196. // 单选场景:选择子程度“确定”后直接提交
  197. if (!this.data.payload.multiple) {
  198. this.onSubmit();
  199. }
  200. }
  201. };
  202. } else {
  203. return fn();
  204. }
  205. } else {
  206. options[index].checked = !item.checked;
  207. if (item.options)
  208. options[index].options = item.options.map((option) => {
  209. if (!(<any>option)?.hide) option.checked = !item.checked;
  210. return option;
  211. });
  212. }
  213. return options;
  214. },
  215. onCancel() {},
  216. onConfirm() {},
  217. onSubmit() {
  218. if (this.data.result) return;
  219. if (!this.data.hasSelected) {
  220. wx.showToast({ title: "请至少选择一项", icon: "error" });
  221. } else {
  222. console.log(this.data.options);
  223. const result = this.data.options
  224. .filter((item: any) => item?.checked && !item?.hide)
  225. .map((option: any) => {
  226. const sub = option.options
  227. ?.filter((item: any) => item?.checked && !item?.hide)
  228. .map((item: any) => item.name)
  229. .join(", ");
  230. return [option.name, sub].filter(Boolean).join(": ");
  231. })
  232. .join("; ");
  233. this.setData({ result });
  234. this.triggerEvent("next", { options: this.data.options });
  235. }
  236. },
  237. onSkip() {
  238. if (this.data.result || this.data.hasSelected) return;
  239. if (!this.data.payload.required) {
  240. this.setData({ result: "都没有" });
  241. this.triggerEvent("next", { options: this.data.options });
  242. }
  243. },
  244. },
  245. });