confirme-order.ts 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. import DictionariesBehavior from "../../../../core/behavior/dictionaries.behavior";
  2. import PageContainerBehavior from "../../../../core/behavior/page-container.behavior";
  3. import { handleWeChatPayment } from "../../../../utils/util";
  4. import { getAddressListMethod, purchaseOfflineTreatmentMethod } from "../../request";
  5. import tickleBehavior, {
  6. getTickleContext,
  7. } from "../../../../core/behavior/tickle.behavior";
  8. // module/order/pages/confirme-order/confirme-order.ts
  9. Page({
  10. behaviors: [PageContainerBehavior, DictionariesBehavior, tickleBehavior],
  11. properties: {},
  12. data: {
  13. totalGoodsCount: 0,
  14. goodsList: [] as Array<{
  15. category: string;
  16. goods: Array<{
  17. id: string;
  18. name: string;
  19. description?: string;
  20. image: string;
  21. price: number;
  22. quantity: number;
  23. checked: boolean;
  24. }>;
  25. }>,
  26. selectAll: true,
  27. selectedCount: 0,
  28. totalPrice: 0,
  29. remark: '',
  30. remarkLength: 0,
  31. showDetail: false,
  32. isPaymentLoading: false, // 支付加载状态
  33. name: "",
  34. phone: "",
  35. address: "",
  36. isDefault: '',
  37. provinceName: '',
  38. cityName: '',
  39. areaName: '',
  40. },
  41. onLoad(options: any) {
  42. if (options.isDefault) {
  43. this.setData({
  44. isDefault: options.isDefault,
  45. });
  46. }
  47. this.load('');
  48. },
  49. onShow() {
  50. //先接收用户选择的地址,如果接收到用户选择的地址就用用户选择的,如果没有则使用默认地址
  51. const selectedAddress = wx.getStorageSync('selectedAddress');
  52. if (selectedAddress && this.data.isDefault === '1') {
  53. this.setData({
  54. showDetail: false,
  55. name: selectedAddress.liaison || "",
  56. phone: selectedAddress.phone || "",
  57. address: `${selectedAddress.provinceName || ""}${selectedAddress.cityName || ""}${selectedAddress.areaName || ""}${selectedAddress.detailAddress || ""}`,
  58. provinceName: selectedAddress.provinceName || "",
  59. cityName: selectedAddress.cityName || "",
  60. areaName: selectedAddress.areaName || "",
  61. });
  62. } else {
  63. this.getDefaultAddress();
  64. }
  65. },
  66. onHide() {
  67. wx.removeStorageSync('selectedAddress');
  68. },
  69. observers: {
  70. 'goodsList': function () {
  71. this.calculateSummary();
  72. }
  73. },
  74. // 获取用户的默认地址
  75. async getDefaultAddress() {
  76. wx.showLoading({ title: "加载中" });
  77. try {
  78. // 获取所有的地址列表
  79. const res = await getAddressListMethod("", "");
  80. if (res && res.length > 0) {
  81. res.forEach((item: any) => {
  82. item.fullAddress = `${item.provinceName} ${item.cityName} ${item.areaName} ${item.detailAddress}`;
  83. item.tag = item.tagList[0] || "";
  84. });
  85. // 过滤出默认地址
  86. const defaultAddress = res.find((item: any) => item.isDefault === "Y");
  87. if (defaultAddress) {
  88. // 有默认地址,直接渲染在页面上
  89. this.setData({
  90. showDetail: false,
  91. name: defaultAddress.liaison || "",
  92. phone: defaultAddress.phone || "",
  93. address: `${defaultAddress.provinceName || ""}${defaultAddress.cityName || ""}${defaultAddress.areaName || ""}${defaultAddress.detailAddress || ""}`,
  94. addressList: res, // 保存所有地址列表,用于修改地址时使用
  95. provinceName: defaultAddress.provinceName || "",
  96. cityName: defaultAddress.cityName || "",
  97. areaName: defaultAddress.areaName || "",
  98. });
  99. } else {
  100. // 没有默认地址,显示"请选择配送地址"
  101. this.setData({
  102. showDetail: true,
  103. name: "",
  104. phone: "",
  105. address: "",
  106. addressList: res, // 保存所有地址列表,用于修改地址时使用
  107. });
  108. }
  109. } else {
  110. // 没有地址数据
  111. this.setData({
  112. showDetail: true,
  113. name: "",
  114. phone: "",
  115. address: "",
  116. addressList: [],
  117. });
  118. }
  119. } catch (error: any) {
  120. getTickleContext.call(this).showWarnMessage(error.errMsg);
  121. // 出错时也显示"请选择配送地址"
  122. this.setData({
  123. showDetail: true,
  124. name: "",
  125. phone: "",
  126. address: "",
  127. addressList: [],
  128. });
  129. }
  130. wx.hideLoading();
  131. },
  132. // 切换收货地址
  133. changeAddress() {
  134. wx.navigateTo({
  135. url:
  136. "/module/article/pages/manage-address/manage-address?type=confirmeOrder",
  137. });
  138. },
  139. // 订单详情
  140. async load(_id: string) {
  141. wx.showLoading({ title: "加载中" });
  142. try {
  143. // 使用存储的selectedGoods数据渲染商品列表
  144. const selectedGoods = wx.getStorageSync('selectedGoods') || [];
  145. const totalPrice = wx.getStorageSync('totalPrice') || 0;
  146. if (selectedGoods && selectedGoods.length > 0) {
  147. // 使用存储的数据渲染商品列表
  148. const goodsList = selectedGoods;
  149. let totalGoodsCount = 0;
  150. goodsList.forEach((category: any) => {
  151. if (category.goods && Array.isArray(category.goods)) {
  152. totalGoodsCount += category.goods.length;
  153. }
  154. });
  155. this.setData({
  156. goodsList,
  157. totalGoodsCount,
  158. totalPrice: parseFloat(totalPrice.toString()),
  159. });
  160. this.calculateSummary();
  161. } else {
  162. // 如果没有存储数据,提示用户
  163. wx.showToast({
  164. title: "暂无商品数据",
  165. icon: "none",
  166. });
  167. }
  168. } catch (error: any) {
  169. wx.showToast({
  170. title: error.errMsg || "加载失败",
  171. icon: "none",
  172. });
  173. }
  174. wx.hideLoading();
  175. },
  176. // 立即支付
  177. async onPayment() {
  178. if (this.data.isPaymentLoading) {
  179. return;
  180. }
  181. this.setData({ isPaymentLoading: true });
  182. try {
  183. // 调用支付接口
  184. const items = this.data.goodsList.map((item: any) => {
  185. return item.goods.map((goods: any) => {
  186. return {
  187. id: goods.id,
  188. quantity: goods.quantity,
  189. };
  190. });
  191. }).flat();
  192. const healthAnalysisReportId = wx.getStorageSync('healthAnalysisReportId');
  193. const params = {
  194. healthAnalysisReportId: healthAnalysisReportId,
  195. items,
  196. remark: this.data.remark || '',
  197. liaison: this.data.name || '',
  198. phone: this.data.phone || '',
  199. detailAddress: this.data.address || '',
  200. provinceName: this.data.provinceName || '',
  201. cityName: this.data.cityName || '',
  202. areaName: this.data.areaName || '',
  203. };
  204. if (!healthAnalysisReportId) {
  205. wx.showToast({
  206. title: "健康评估报告ID不能为空",
  207. icon: "none",
  208. });
  209. this.setData({ isPaymentLoading: false });
  210. return;
  211. }
  212. const payResult: any = await purchaseOfflineTreatmentMethod(params);
  213. if (payResult) {
  214. const paymentParams = payResult;
  215. handleWeChatPayment(paymentParams, (_res: any) => {
  216. // 支付成功,跳转到成功页面
  217. wx.redirectTo({
  218. url: "/module/article/pages/success-page/success-page?title=订单支付成功",
  219. });
  220. }, (error: any) => {
  221. this.setData({ isPaymentLoading: false });
  222. if (error?.errMsg === 'requestPayment:fail cancel') {
  223. // 支付取消跳到支付订单页面
  224. wx.navigateBack({ delta: 1 });
  225. }
  226. // wx.showToast({
  227. // title: error?.errMsg || error?.message || "支付失败,请重试",
  228. // icon: "none",
  229. // });
  230. });
  231. } else {
  232. wx.showToast({
  233. title: "支付失败",
  234. icon: "none",
  235. });
  236. }
  237. } catch (error: any) {
  238. wx.showToast({
  239. title: error.errMsg,
  240. icon: "none",
  241. });
  242. } finally {
  243. this.setData({ isPaymentLoading: false });
  244. }
  245. },
  246. // 商品复选框变化
  247. onGoodsCheckChange(e: any) {
  248. const { categoryIndex, goodsIndex } = e.currentTarget.dataset;
  249. const checked = e.detail.checked;
  250. const goodsList = this.data.goodsList;
  251. const goods = goodsList[categoryIndex].goods[goodsIndex];
  252. goods.checked = checked;
  253. // 如果勾选且数量为0,设置为1
  254. if (checked && goods.quantity === 0) {
  255. goods.quantity = 1;
  256. }
  257. // 单价为0的商品,如果勾选,确保数量为1
  258. if (checked && goods.price === 0 && goods.quantity !== 1) {
  259. goods.quantity = 1;
  260. }
  261. this.setData({ goodsList });
  262. this.calculateSummary();
  263. },
  264. // 数量变化(加减按钮)
  265. onQuantityChange(e: any) {
  266. const { categoryIndex, goodsIndex, type } = e.currentTarget.dataset;
  267. const goodsList = this.data.goodsList;
  268. const goods = goodsList[categoryIndex].goods[goodsIndex];
  269. // 单价为0的商品数量最多只能是1
  270. if (goods.price === 0) {
  271. if (type === "plus") {
  272. // 如果数量已经是1或更多,不能再加
  273. if (goods.quantity >= 1) {
  274. return;
  275. }
  276. // 如果数量为0,增加到1
  277. goods.quantity = 1;
  278. goods.checked = true;
  279. this.setData({ goodsList });
  280. this.calculateSummary();
  281. } else if (type === "minus") {
  282. // 点击减号,数量为1时弹出确认对话框
  283. if (goods.quantity === 1) {
  284. wx.showModal({
  285. title: '提示',
  286. content: '您想要删除该商品吗?',
  287. success: (res) => {
  288. if (res.confirm) {
  289. // 用户确认删除
  290. this.removeGoods(categoryIndex, goodsIndex);
  291. }
  292. // 用户取消,不做任何操作,保持数量为1
  293. }
  294. });
  295. } else if (goods.quantity === 0) {
  296. // 已经是0,不能再减
  297. return;
  298. } else {
  299. // 其他情况(理论上不应该出现),确保数量不超过1
  300. goods.quantity = Math.min(1, goods.quantity - 1);
  301. this.setData({ goodsList });
  302. this.calculateSummary();
  303. }
  304. }
  305. } else {
  306. // 非0价格商品的正常逻辑
  307. if (type === "plus") {
  308. const newQuantity = goods.quantity + 1;
  309. goods.quantity = newQuantity;
  310. if (!goods.checked) {
  311. goods.checked = true;
  312. }
  313. this.setData({ goodsList });
  314. this.calculateSummary();
  315. } else if (type === "minus") {
  316. // 点击减号
  317. if (goods.quantity === 1) {
  318. // 数量为1时,点击减号会变为0,弹出确认对话框
  319. wx.showModal({
  320. title: '提示',
  321. content: '您想要删除该商品吗?',
  322. success: (res) => {
  323. if (res.confirm) {
  324. // 用户确认删除
  325. this.removeGoods(categoryIndex, goodsIndex);
  326. }
  327. // 用户取消,不做任何操作,保持数量为1
  328. }
  329. });
  330. } else {
  331. // 数量大于1,正常减少
  332. const newQuantity = goods.quantity - 1;
  333. goods.quantity = newQuantity;
  334. this.setData({ goodsList });
  335. this.calculateSummary();
  336. }
  337. }
  338. }
  339. },
  340. // 删除商品
  341. removeGoods(categoryIndex: number, goodsIndex: number) {
  342. const goodsList = JSON.parse(JSON.stringify(this.data.goodsList)); // 深拷贝
  343. const category = goodsList[categoryIndex];
  344. // 从该分类中删除商品
  345. category.goods.splice(goodsIndex, 1);
  346. // 如果该分类没有商品了,删除该分类
  347. if (category.goods.length === 0) {
  348. goodsList.splice(categoryIndex, 1);
  349. }
  350. this.setData({ goodsList });
  351. this.calculateSummary();
  352. },
  353. // 数量输入
  354. onQuantityInput(e: any) {
  355. const { categoryIndex, goodsIndex } = e.currentTarget.dataset;
  356. const value = parseInt(e.detail.value) || 0;
  357. const goodsList = this.data.goodsList;
  358. const goods = goodsList[categoryIndex].goods[goodsIndex];
  359. // 单价为0的商品数量最多只能是1
  360. if (goods.price === 0) {
  361. if (value > 1) {
  362. goods.quantity = 1;
  363. } else if (value < 0) {
  364. goods.quantity = 0;
  365. goods.checked = false;
  366. } else {
  367. goods.quantity = value;
  368. // 如果数量为0,取消勾选
  369. if (value === 0) {
  370. goods.checked = false;
  371. } else if (value > 0 && !goods.checked) {
  372. goods.checked = true;
  373. }
  374. }
  375. } else {
  376. goods.quantity = Math.max(0, value);
  377. }
  378. this.setData({ goodsList });
  379. },
  380. // 数量输入失焦
  381. onQuantityBlur(e: any) {
  382. const { categoryIndex, goodsIndex } = e.currentTarget.dataset;
  383. const goodsList = this.data.goodsList;
  384. const goods = goodsList[categoryIndex].goods[goodsIndex];
  385. // 单价为0的商品数量最多只能是1
  386. if (goods.price === 0) {
  387. if (goods.quantity > 1) {
  388. goods.quantity = 1;
  389. } else if (goods.quantity === 0) {
  390. // 数量为0,取消勾选
  391. goods.checked = false;
  392. } else if (goods.quantity > 0 && goods.quantity <= 1) {
  393. // 数量在0-1之间,如果已勾选但数量小于1,设置为1
  394. if (goods.checked && goods.quantity < 1) {
  395. goods.quantity = 1;
  396. } else if (!goods.checked && goods.quantity > 0) {
  397. // 如果数量大于0但未勾选,自动勾选
  398. goods.checked = true;
  399. }
  400. }
  401. } else {
  402. // 非0价格商品的逻辑
  403. if (goods.quantity === 0) {
  404. goods.checked = false;
  405. } else if (!goods.checked) {
  406. // 如果数量大于0且未勾选,自动勾选
  407. goods.checked = true;
  408. }
  409. }
  410. this.setData({ goodsList });
  411. this.calculateSummary();
  412. },
  413. // 计算汇总信息
  414. calculateSummary() {
  415. const goodsList = this.data.goodsList;
  416. let selectedCount = 0;
  417. let totalGoodsCount = 0; // 所有选中商品的总数量
  418. let totalPrice = 0;
  419. let allChecked = true;
  420. goodsList.forEach((category: any) => {
  421. category.goods.forEach((goods: any) => {
  422. if (goods.checked && goods.quantity > 0) {
  423. selectedCount++; // 已选件数 = 选中的商品种类数
  424. totalGoodsCount += goods.quantity; // 累加所有选中商品的数量
  425. totalPrice += goods.price * goods.quantity;
  426. }
  427. if (!goods.checked || goods.quantity === 0) {
  428. allChecked = false;
  429. }
  430. });
  431. });
  432. this.setData({
  433. selectedCount,
  434. totalPrice: parseFloat(totalPrice.toFixed(2)),
  435. selectAll: allChecked,
  436. totalGoodsCount: totalGoodsCount
  437. });
  438. },
  439. // 备注输入处理
  440. onRemarkInput(e: any) {
  441. const value = e.detail.value;
  442. const length = value.length;
  443. // 限制最大长度为200
  444. if (length > 200) {
  445. return;
  446. }
  447. this.setData({
  448. remark: value,
  449. remarkLength: length
  450. });
  451. },
  452. });