message-again.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. // module/chats/components/message-select/message-select.ts
  2. import { Get, Post } from "../../../../lib/request/method";
  3. interface Option {
  4. id: string;
  5. name: string;
  6. checked?: boolean;
  7. options: Option[] | null;
  8. }
  9. interface HandleEvent {
  10. mark: {
  11. type: "sub" | "options";
  12. index: number;
  13. item: Option;
  14. };
  15. }
  16. Component({
  17. properties: {
  18. payload: {
  19. type: Object,
  20. value: { title: "", multiple: false, options: [] },
  21. result: "",
  22. },
  23. active: { type: Boolean, value: false },
  24. workId: { type: Number, value: 0 },
  25. },
  26. data: {
  27. placeholder: "请输入",
  28. safeBottomRpx: 0,
  29. // 键盘逻辑
  30. inputBoxBottom: 0, //初始华底部的值
  31. inputText: "",
  32. messages: [],
  33. showrePlenish: false,
  34. inputFocus: false,
  35. // end
  36. options: [],
  37. subOptions: [] as Option[],
  38. subMultiple: false,
  39. itemHeight: 48,
  40. result: "",
  41. hasSelected: false,
  42. required: false,
  43. multiple: true,
  44. value1: null,
  45. radioList: [
  46. {
  47. id: "Y",
  48. label: "有",
  49. value: 0,
  50. },
  51. {
  52. id: "N",
  53. label: "没有",
  54. value: 1,
  55. },
  56. ],
  57. symptomResult: "",
  58. btnDisabled: false,
  59. followObj: {},
  60. labelList: [],
  61. symptomsList: [],
  62. isHaveNewSyndrome: "",
  63. isAnalysis: 0,
  64. InputHeight:0,
  65. },
  66. attached() {
  67. this.setData({
  68. isAnalysis: wx.getStorageSync("isAnalysis"),
  69. });
  70. const systemInfo = wx.getSystemInfoSync();
  71. const windowHeight = systemInfo.windowHeight;
  72. const safeAreaBottom = systemInfo.safeArea?.bottom ?? windowHeight; // 没有safeArea时,bottom等于windowHeight
  73. const safeBottom = windowHeight - safeAreaBottom; // 安全区底部距离(px)
  74. const tabBarHeight = 100; // 底部tabbar的高度
  75. const safeBottomRpx = (750 / systemInfo.windowWidth) * safeBottom; // rpx
  76. // 初始的底部bottom 底部安全区的高度+tabbar的高度
  77. this.setData({
  78. inputBoxBottom: safeBottomRpx + tabBarHeight,
  79. safeBottomRpx: safeBottomRpx,
  80. InputHeight:safeBottomRpx + tabBarHeight,
  81. });
  82. this.setData({
  83. hasSelected: this.data.options
  84. .filter((option) => !option.hide)
  85. .some((option) => option.checked),
  86. });
  87. this.getContent();
  88. this.getStatus();
  89. },
  90. observers: {
  91. options(options: AnyArray) {
  92. this.setData({
  93. hasSelected: options
  94. .filter((option) => !option.hide)
  95. .some((option) => option.checked),
  96. });
  97. },
  98. },
  99. methods: {
  100. handleInput(e: any) {
  101. this.setData({ inputText: e.detail.value });
  102. },
  103. // 发送信息
  104. send() {
  105. const text = this.data.inputText.trim();
  106. // 如果输入框内容为空,则不发送信息
  107. if (!text) {
  108. wx.showToast({ title: "发送的信息不能为空", icon: "none" });
  109. if (this.data.inputFocus) {
  110. this.setData({
  111. inputFocus: true,
  112. });
  113. }
  114. return;
  115. }
  116. const userMessage = {
  117. id: Date.now().toString(),
  118. content: text,
  119. sender: "user",
  120. timestamp: Date.now(),
  121. status: "sending",
  122. };
  123. this.setData({
  124. messages: [...this.data.messages, userMessage],
  125. });
  126. if (this.data.messages.length === 2 && this.data.symptomResult === "有") {
  127. this.setData({
  128. showrePlenish: false,
  129. });
  130. this.triggerEvent("nextType", { MessageType: 2 });
  131. this.triggerEvent("boxBottom", {
  132. inputBoxBottom: this.data.InputHeight - 60,
  133. });
  134. } else if (
  135. this.data.messages.length === 1 &&
  136. this.data.symptomResult === "没有"
  137. ) {
  138. this.setData({
  139. showrePlenish: false,
  140. });
  141. this.triggerEvent("nextType", { MessageType: 2 });
  142. this.triggerEvent("boxBottom", {
  143. inputBoxBottom: this.data.InputHeight - 60,
  144. });
  145. } else if (
  146. this.data.messages.length === 1 &&
  147. this.data.symptomResult === "有"
  148. ) {
  149. this.setData({
  150. placeholder: "请问还有其他要补充的吗?",
  151. inputBoxBottom: this.data.InputHeight,
  152. });
  153. this.triggerEvent("boxBottom", {
  154. inputBoxBottom: this.data.InputHeight,
  155. });
  156. }
  157. this.triggerEvent("scroll", { id: "bottom" });
  158. // 发送信息之后 输入框内容清空
  159. this.setData({
  160. inputText: "",
  161. });
  162. },
  163. // 键盘聚焦
  164. onInputFocus(e: any) {
  165. const systemInfo = wx.getSystemInfoSync();
  166. const height = (750 / systemInfo.windowWidth) * e.detail.height; // 转为rpx
  167. this.setData({
  168. inputFocus: true,
  169. inputBoxBottom: height,
  170. });
  171. this.triggerEvent("boxBottom", {
  172. inputBoxBottom: height,
  173. });
  174. this.triggerEvent("scroll", { id: "bottom" });
  175. },
  176. // 键盘失焦
  177. onInputBlur(e: any) {
  178. // 输入框失焦之后 底部高度是tabbar高度+安全区的高度
  179. this.setData({
  180. inputFocus: false,
  181. inputBoxBottom: this.data.InputHeight,
  182. });
  183. this.triggerEvent("boxBottom", {
  184. inputBoxBottom: this.data.InputHeight,
  185. });
  186. this.triggerEvent("scroll", { id: "bottom" });
  187. },
  188. // 在字典中取症状的状态
  189. async getStatus() {
  190. const dict = await Get("/dict/getDicts", {
  191. transform({ data }: any) {
  192. return data;
  193. },
  194. });
  195. // 查找出是随访病症的状态
  196. let statusArr = dict.filter(
  197. (item: any) => item.dictType === "followup_syndrome_change"
  198. );
  199. this.setData({
  200. labelList: statusArr[0].items,
  201. });
  202. },
  203. // 获取随访任务详情
  204. async getContent() {
  205. // 先从字典中获取状态
  206. await this.getStatus();
  207. let followArr: any = [];
  208. try {
  209. const res = await Post(
  210. `/followupTaskManage/getFollowupTaskDetail/${this.data?.workId}`,
  211. {},
  212. {
  213. transform({ data }: any) {
  214. return data;
  215. },
  216. }
  217. );
  218. this.setData({ followObj: res });
  219. // 处理数据
  220. if (res.syndromeList.length > 0) {
  221. res.syndromeList.forEach((syndrome: any, index: number) => {
  222. followArr.push({
  223. name: syndrome,
  224. id: index + 1,
  225. checked: false,
  226. apiChecked: false,
  227. options: [],
  228. });
  229. if (this.data.labelList.length > 0) {
  230. this.data.labelList.forEach((label: any, lebelIdx: number) => {
  231. followArr[index].options.push({
  232. name: label.dictLabel,
  233. id: lebelIdx + index + 1 + index,
  234. checked: false,
  235. apiChecked: false,
  236. });
  237. });
  238. }
  239. });
  240. }
  241. this.setData({ options: followArr });
  242. } catch (error: any) {
  243. wx.showToast({ title: error.errMsg, icon: "error" });
  244. }
  245. },
  246. // 选择有或没有
  247. onChangeValue(e: any) {
  248. this.setData({ value1: e.detail.value });
  249. // 输入框底部的bottom也还是最初的inputBoxBottom就可以了
  250. this.triggerEvent("boxBottom", {
  251. inputBoxBottom: this.data.inputBoxBottom,
  252. });
  253. this.setData({
  254. symptomResult: this.data.radioList.find(
  255. (item: any) => item.value === e.detail.value
  256. )?.label,
  257. isHaveNewSyndrome: this.data.radioList.find(
  258. (item: any) => item.value === e.detail.value
  259. )?.id,
  260. });
  261. let followObj: any = {
  262. isHaveNewSyndrome: this.data.isHaveNewSyndrome,
  263. symptomsList: this.data.symptomsList,
  264. };
  265. if (this.data.isHaveNewSyndrome === "N") {
  266. this.setData({ placeholder: "请问还有其他要补充的吗?" });
  267. } else {
  268. this.setData({ placeholder: "请描述新的症状?" });
  269. }
  270. this.setData({ btnDisabled: true });
  271. wx.setStorageSync("followObj", followObj);
  272. this.setData({
  273. showrePlenish: true,
  274. });
  275. this.triggerEvent("scroll", { id: "bottom" });
  276. },
  277. handleTop(event: HandleEvent) {
  278. if (this.data.result) return;
  279. const {
  280. mark: { item },
  281. } = event;
  282. if (!item) return;
  283. const index = this.data.options.findIndex(
  284. (option) => option.id === item.id
  285. );
  286. const multiple = this.data.multiple;
  287. const checked = !item.checked;
  288. const options = this._handle(this.data.options, item, index, multiple);
  289. this.setData({ options });
  290. if (checked && !multiple) {
  291. this.onSubmit();
  292. }
  293. },
  294. handleSub(event: HandleEvent) {
  295. const {
  296. mark: { item },
  297. } = event;
  298. if (!item) return;
  299. const index = this.data.subOptions.findIndex(
  300. (option) => option.id === item.id
  301. );
  302. const multiple = this.data.subMultiple;
  303. let checked;
  304. this.data.subOptions.forEach((option: any, index: number) => {
  305. if (option.id === item.id) {
  306. checked = option.checked = true;
  307. } else {
  308. option.checked = false;
  309. }
  310. });
  311. const subOptions = this._handle(
  312. this.data.subOptions,
  313. item,
  314. index,
  315. multiple
  316. );
  317. this.setData({ subOptions });
  318. if (checked && !multiple) {
  319. this.onConfirm();
  320. }
  321. },
  322. _handle(
  323. options: Option[],
  324. item: Option,
  325. index: number,
  326. multiple?: boolean
  327. ) {
  328. const checked = !item.checked;
  329. if (checked) {
  330. const fn = () => {
  331. if (multiple) {
  332. options[index].checked = checked;
  333. } else {
  334. options.forEach((option) => {
  335. option.checked = option.id === item.id;
  336. });
  337. }
  338. return options;
  339. };
  340. if (item.options?.filter((option) => !(<any>option)?.hide).length) {
  341. this.setData({
  342. subTitle: item.name,
  343. subOptions: item.options,
  344. subMultiple: true,
  345. });
  346. this.onCancel = () => {
  347. this.setData({ subOptions: [] });
  348. };
  349. this.onConfirm = () => {
  350. if (!this.data.subOptions.some((option) => option.checked)) {
  351. wx.showToast({ title: "请至少选择一项", icon: "error" });
  352. } else {
  353. const options = fn();
  354. options[index].options = this.data.subOptions;
  355. this.setData({ subOptions: [], options });
  356. }
  357. };
  358. } else {
  359. return fn();
  360. }
  361. } else {
  362. options[index].checked = !item.checked;
  363. if (item.options)
  364. options[index].options = item.options.map((option) => {
  365. if (!(<any>option)?.hide) option.checked = !item.checked;
  366. return option;
  367. });
  368. }
  369. return options;
  370. },
  371. onSubmit() {
  372. if (this.data.result) return;
  373. if (!this.data.hasSelected) {
  374. wx.showToast({ title: "请至少选择一项", icon: "error" });
  375. } else {
  376. const result = this.data.options
  377. .filter((item: any) => item?.checked && !item?.hide)
  378. .map((option: any) => {
  379. const sub = option.options
  380. ?.filter((item: any) => item?.checked && !item?.hide)
  381. .map((item: any) => item.name)
  382. .join(", ");
  383. return [option.name, sub].filter(Boolean).join(": ");
  384. })
  385. .join("; ");
  386. this.setData({ result });
  387. let symptomsList: any = [];
  388. this.data.options.forEach((option: any) => {
  389. const isCheck = option.options.every((item: any) => {
  390. return !item.checked;
  391. });
  392. if (isCheck) {
  393. symptomsList.push({ name: option.name, type: "" });
  394. } else {
  395. symptomsList.push({
  396. name: option.name,
  397. type:
  398. option.options.find((item: any) => item.checked)?.name || "",
  399. });
  400. }
  401. });
  402. this.setData({ symptomsList });
  403. this.triggerEvent("scroll", { id: "bottom" });
  404. }
  405. },
  406. onSkip() {
  407. if (this.data.result || this.data.hasSelected) return;
  408. if (!this.data.payload.required) {
  409. this.setData({ result: "无变化" });
  410. this.triggerEvent("next", { options: this.data.options });
  411. }
  412. this.triggerEvent("scroll", { id: "bottom" });
  413. this.setData({ placeholder: "请问还有其他要补充的吗?" });
  414. },
  415. },
  416. onUnload() {
  417. wx.offKeyboardHeightChange(); // 解绑键盘高度变化监听
  418. },
  419. });