address.uvue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. <template>
  2. <cl-page>
  3. <view class="p-3">
  4. <view
  5. class="flex flex-col bg-white rounded-2xl p-4 mb-3 dark:!bg-surface-800"
  6. :class="{
  7. '!mb-0': index == addressList.length - 1
  8. }"
  9. v-for="(item, index) in addressList"
  10. :key="item.id"
  11. >
  12. <view class="flex flex-col">
  13. <cl-text color="info" :pt="{ className: '!text-sm' }"
  14. >{{ item.province }} {{ item.city }} {{ item.district }}</cl-text
  15. >
  16. <cl-text
  17. :pt="{
  18. className: 'my-1'
  19. }"
  20. >{{ item.address }}</cl-text
  21. >
  22. <view class="flex flex-row">
  23. <cl-text :pt="{ className: '!text-sm' }">{{ item.contact }}</cl-text>
  24. <cl-text color="info" :pt="{ className: 'ml-3 !text-sm' }">{{
  25. item.phone
  26. }}</cl-text>
  27. </view>
  28. </view>
  29. <view
  30. class="flex flex-row border border-solid border-gray-100 border-b-0 border-l-0 border-r-0 pt-4 mt-4 dark:!border-surface-700"
  31. >
  32. <cl-radio
  33. v-model="defaultId"
  34. active-icon="checkbox-circle-fill"
  35. inactive-icon="checkbox-blank-circle-line"
  36. :pt="{
  37. className: 'max-w-[300rpx]',
  38. label: {
  39. className: '!text-sm'
  40. },
  41. icon: {
  42. size: 32
  43. }
  44. }"
  45. :value="item.id"
  46. @change="onDefaultChange(item)"
  47. >{{ item.isDefault ? t("已设为默认") : t("设为默认") }}</cl-radio
  48. >
  49. <view
  50. class="flex flex-row items-center justify-center ml-auto"
  51. @tap="onDelete(item.id!)"
  52. >
  53. <cl-icon name="delete-bin-line" :size="28"></cl-icon>
  54. <cl-text :pt="{ className: 'ml-2 !text-sm' }">{{ t("删除") }}</cl-text>
  55. </view>
  56. <view
  57. class="flex flex-row items-center justify-center ml-6"
  58. @tap="toEdit(item.id!)"
  59. >
  60. <cl-icon name="edit-line" :size="28"></cl-icon>
  61. <cl-text :pt="{ className: 'ml-2 !text-sm' }">{{ t("修改") }}</cl-text>
  62. </view>
  63. </view>
  64. </view>
  65. <cl-empty v-if="list.length == 0"></cl-empty>
  66. </view>
  67. <cl-footer>
  68. <cl-button @tap="toAdd()">{{ t("添加地址") }}</cl-button>
  69. </cl-footer>
  70. </cl-page>
  71. </template>
  72. <script lang="ts" setup>
  73. import { useUi } from "@/uni_modules/cool-ui";
  74. import { parse, request, router, usePager, type Response } from "@/cool";
  75. import { t } from "@/locale";
  76. import { computed, ref } from "vue";
  77. import type { UserAddress } from "../types";
  78. const ui = useUi();
  79. const { refresh, list, loadMore } = usePager(async (data) => {
  80. return request({
  81. url: "/app/user/address/page",
  82. method: "POST",
  83. data
  84. })
  85. .catch((err) => {
  86. ui.showToast({
  87. message: (err as Response).message!
  88. });
  89. })
  90. .finally(() => {
  91. ui.hideLoading();
  92. });
  93. });
  94. // 默认地址id
  95. const defaultId = ref<number>(0);
  96. // 地址列表数据
  97. const addressList = computed(() =>
  98. list.value.map((e) => {
  99. e["isDefault"] = e["isDefault"] == 1 ? true : false;
  100. const d = parse<UserAddress>(e)!;
  101. if (d.isDefault) {
  102. defaultId.value = d.id!;
  103. }
  104. return d;
  105. })
  106. );
  107. // 添加地址
  108. function toAdd() {
  109. router.to("/pages/template/shop/address-edit");
  110. }
  111. // 编辑地址
  112. function toEdit(id: number) {
  113. router.push({
  114. path: "/pages/template/shop/address-edit",
  115. query: { id }
  116. });
  117. }
  118. // 删除地址
  119. function onDelete(id: number) {
  120. ui.showConfirm({
  121. title: t("提示"),
  122. message: t("删除地址后无法恢复,确认要删除该地址吗?"),
  123. callback: (action) => {
  124. if (action == "confirm") {
  125. request({
  126. url: "/app/user/address/delete",
  127. method: "POST",
  128. data: { ids: [id] }
  129. })
  130. .then(() => {
  131. ui.showToast({
  132. message: t("删除成功")
  133. });
  134. refresh({});
  135. })
  136. .catch((err) => {
  137. ui.showToast({
  138. message: (err as Response).message!
  139. });
  140. });
  141. }
  142. }
  143. });
  144. }
  145. // 设为默认地址
  146. function onDefaultChange(item: UserAddress) {
  147. // 遍历地址列表,设置选中的地址为默认地址,其他地址取消默认
  148. addressList.value.forEach((e) => {
  149. if (e.id == item.id) {
  150. // 切换当前地址的默认状态
  151. e.isDefault = !e.isDefault;
  152. // 如果取消了默认,则重置默认地址ID
  153. if (!e.isDefault) {
  154. defaultId.value = 0;
  155. }
  156. } else {
  157. // 其他地址全部取消默认
  158. e.isDefault = false;
  159. }
  160. });
  161. request({
  162. url: "/app/user/address/update",
  163. method: "POST",
  164. data: {
  165. id: item.id,
  166. isDefault: item.isDefault
  167. }
  168. });
  169. }
  170. onPullDownRefresh(() => {
  171. refresh({ page: 1 }).finally(() => {
  172. uni.stopPullDownRefresh();
  173. });
  174. });
  175. onReachBottom(() => {
  176. loadMore();
  177. });
  178. onReady(() => {
  179. ui.showLoading(t("加载中"));
  180. // 默认请求
  181. refresh({
  182. page: 1,
  183. size: 20
  184. });
  185. onPageShow(() => {
  186. refresh({});
  187. });
  188. });
  189. </script>