select-goods.ts 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. import DictionariesBehavior from "../../../../core/behavior/dictionaries.behavior";
  2. import PageContainerBehavior from "../../../../core/behavior/page-container.behavior";
  3. import tickleBehavior, {
  4. getTickleContext,
  5. } from "../../../../core/behavior/tickle.behavior";
  6. import { getOfflineTreatmentListMethod } from "../../request";
  7. // module/order/pages/select-goods/select-goods.ts
  8. Component({
  9. behaviors: [PageContainerBehavior, DictionariesBehavior, tickleBehavior],
  10. lifetimes: {
  11. attached() {
  12. const healthAnalysisReportId = wx.getStorageSync('healthAnalysisReportId');
  13. if(healthAnalysisReportId){
  14. this.getOfflineTreatmentList(healthAnalysisReportId);
  15. }
  16. },
  17. },
  18. data: {
  19. goodsList: [] as Array<{
  20. category: string;
  21. goods: Array<{
  22. id: string;
  23. name: string;
  24. description?: string;
  25. image: string;
  26. price: number;
  27. quantity: number;
  28. checked: boolean;
  29. badge?: string;
  30. }>;
  31. }>,
  32. selectAll: true,
  33. selectedCount: 0,
  34. totalPrice: 0,
  35. },
  36. observers: {
  37. 'goodsList': function () {
  38. this.calculateSummary();
  39. }
  40. },
  41. methods: {
  42. async getOfflineTreatmentList(healthAnalysisReportId: string) {
  43. const res = await getOfflineTreatmentListMethod(healthAnalysisReportId);
  44. const goodsList: any[] = [];
  45. Object.keys(res).forEach((categoryName: string) => {
  46. const categoryItems = res[categoryName] || [];
  47. if (categoryItems.length > 0) {
  48. const goods = categoryItems.map((item: any) => {
  49. return {
  50. id: item.id || '',
  51. name: item.name || '', //商品名称
  52. description: (() => {
  53. const dose = item?.cpFixedPricingRule?.convertDose ?? '';
  54. const unit = item?.cpFixedPricingRule?.convertUnit ?? '';
  55. return `${dose} ${unit}`;
  56. })(),
  57. image: item.itemImgSecond || '', //商品图片
  58. price: item.cpFixedPricingRule?.unitPrice || 0, //商品单价
  59. quantity: 1, //商品数量
  60. checked: true, //是否选中
  61. };
  62. });
  63. goodsList.push({
  64. category: categoryName,
  65. goods: goods,
  66. });
  67. }
  68. });
  69. this.setData({ goodsList });
  70. this.calculateSummary();
  71. },
  72. // 商品复选框变化
  73. onGoodsCheckChange(e: any) {
  74. const { categoryIndex, goodsIndex } = e.currentTarget.dataset;
  75. const checked = e.detail.checked;
  76. const goodsList = this.data.goodsList;
  77. const goods = goodsList[categoryIndex].goods[goodsIndex];
  78. goods.checked = checked;
  79. // 如果勾选且数量为0,设置为1
  80. if (checked && goods.quantity === 0) {
  81. goods.quantity = 1;
  82. }
  83. // 单价为0的商品,如果勾选,数量固定为1
  84. if (goods.price === 0) {
  85. if (checked) {
  86. goods.quantity = 1;
  87. } else {
  88. goods.quantity = 0;
  89. }
  90. }
  91. this.setData({ goodsList });
  92. this.calculateSummary();
  93. },
  94. // 全选变化
  95. onSelectAllChange(e: any) {
  96. const checked = e.detail.checked;
  97. const goodsList = this.data.goodsList.map(category => ({
  98. ...category,
  99. goods: category.goods.map(goods => ({
  100. ...goods,
  101. checked: checked,
  102. // 0元商品:选中时数量为1,未选中时数量为0
  103. // 非0元商品:选中时如果数量为0则设为1,否则保持原数量
  104. quantity: goods.price === 0
  105. ? (checked ? 1 : 0)
  106. : (checked && goods.quantity === 0 ? 1 : goods.quantity)
  107. }))
  108. }));
  109. this.setData({
  110. goodsList,
  111. selectAll: checked
  112. });
  113. this.calculateSummary();
  114. },
  115. // 数量变化(加减按钮)
  116. onQuantityChange(e: any) {
  117. const { categoryIndex, goodsIndex, type } = e.currentTarget.dataset;
  118. const goodsList = this.data.goodsList;
  119. const goods = goodsList[categoryIndex].goods[goodsIndex];
  120. // 单价为0的商品数量固定为1(如果被选中)
  121. if (goods.price === 0) {
  122. // 0元商品数量固定为1,不允许通过按钮修改
  123. return;
  124. } else {
  125. // 非0价格商品的正常逻辑
  126. let newQuantity = goods.quantity;
  127. if (type === "plus") {
  128. newQuantity = goods.quantity + 1;
  129. } else if (type === "minus") {
  130. newQuantity = Math.max(0, goods.quantity - 1);
  131. }
  132. goods.quantity = newQuantity;
  133. // 如果数量为0,自动取消勾选
  134. if (newQuantity === 0) {
  135. goods.checked = false;
  136. } else if (!goods.checked) {
  137. // 如果数量大于0且未勾选,自动勾选
  138. goods.checked = true;
  139. }
  140. }
  141. this.setData({ goodsList });
  142. this.calculateSummary();
  143. },
  144. // 数量输入
  145. onQuantityInput(e: any) {
  146. const { categoryIndex, goodsIndex } = e.currentTarget.dataset;
  147. const goodsList = this.data.goodsList;
  148. const goods = goodsList[categoryIndex].goods[goodsIndex];
  149. // 单价为0的商品数量固定为1,不允许修改
  150. if (goods.price === 0) {
  151. // 保持数量为1
  152. goods.quantity = 1;
  153. this.setData({ goodsList });
  154. return;
  155. }
  156. const value = parseInt(e.detail.value) || 0;
  157. goods.quantity = Math.max(0, value);
  158. this.setData({ goodsList });
  159. },
  160. // 数量输入失焦
  161. onQuantityBlur(e: any) {
  162. const { categoryIndex, goodsIndex } = e.currentTarget.dataset;
  163. const goodsList = this.data.goodsList;
  164. const goods = goodsList[categoryIndex].goods[goodsIndex];
  165. // 单价为0的商品数量固定为1(如果被选中)
  166. if (goods.price === 0) {
  167. // 如果被选中,数量固定为1
  168. if (goods.checked) {
  169. goods.quantity = 1;
  170. } else {
  171. // 如果未选中,数量为0
  172. goods.quantity = 0;
  173. }
  174. } else {
  175. // 非0价格商品的逻辑
  176. if (goods.quantity === 0) {
  177. goods.checked = false;
  178. } else if (!goods.checked) {
  179. // 如果数量大于0且未勾选,自动勾选
  180. goods.checked = true;
  181. }
  182. }
  183. this.setData({ goodsList });
  184. this.calculateSummary();
  185. },
  186. // 计算汇总信息
  187. calculateSummary() {
  188. const goodsList = this.data.goodsList;
  189. let selectedCount = 0;
  190. let totalPrice = 0;
  191. let allChecked = true;
  192. goodsList.forEach((category: any) => {
  193. category.goods.forEach((goods: any) => {
  194. if (goods.checked && goods.quantity > 0) {
  195. selectedCount++; // 已选件数 = 选中的商品种类数
  196. totalPrice += goods.price * goods.quantity;
  197. }
  198. if (!goods.checked || goods.quantity === 0) {
  199. allChecked = false;
  200. }
  201. });
  202. });
  203. this.setData({
  204. selectedCount,
  205. totalPrice: totalPrice.toFixed(2),
  206. selectAll: allChecked
  207. });
  208. },
  209. // 结算
  210. onCheckout() {
  211. const goodsList = this.data.goodsList;
  212. // 过滤出选中的商品
  213. const selectedGoods = goodsList.map((category: any) => ({
  214. category: category.category,
  215. goods: category.goods.filter((goods: any) => goods.checked && goods.quantity > 0)
  216. })).filter((category: any) => category.goods.length > 0);
  217. if (selectedGoods.length === 0) {
  218. getTickleContext.call(this).showWarnMessage("请至少选择一件商品");
  219. return;
  220. }
  221. // 跳转到确认订单页面
  222. wx.setStorageSync('selectedGoods', selectedGoods);
  223. wx.setStorageSync('totalPrice', this.data.totalPrice);
  224. wx.navigateTo({
  225. url: `/module/order/pages/confirme-order/confirme-order`,
  226. fail: (err) => {
  227. getTickleContext.call(this).showWarnMessage(err.errMsg || "跳转失败");
  228. },
  229. });
  230. },
  231. }
  232. });