address.uvue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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, { render }) => {
  80. await request({
  81. url: "/app/user/address/page",
  82. method: "POST",
  83. data
  84. })
  85. .then((res) => {
  86. if (res != null) {
  87. render(res);
  88. }
  89. })
  90. .catch((err) => {
  91. ui.showToast({
  92. message: (err as Response).message!
  93. });
  94. })
  95. .finally(() => {
  96. ui.hideLoading();
  97. });
  98. });
  99. // 默认地址id
  100. const defaultId = ref<number>(0);
  101. // 地址列表数据
  102. const addressList = computed(() =>
  103. list.value.map((e) => {
  104. e["isDefault"] = e["isDefault"] == 1 ? true : false;
  105. const d = parse<UserAddress>(e)!;
  106. if (d.isDefault) {
  107. defaultId.value = d.id!;
  108. }
  109. return d;
  110. })
  111. );
  112. // 添加地址
  113. function toAdd() {
  114. router.to("/pages/template/shop/address-edit");
  115. }
  116. // 编辑地址
  117. function toEdit(id: number) {
  118. router.push({
  119. path: "/pages/template/shop/address-edit",
  120. query: { id }
  121. });
  122. }
  123. // 删除地址
  124. function onDelete(id: number) {
  125. ui.showConfirm({
  126. title: t("提示"),
  127. message: t("删除地址后无法恢复,确认要删除该地址吗?"),
  128. callback: (action) => {
  129. if (action == "confirm") {
  130. request({
  131. url: "/app/user/address/delete",
  132. method: "POST",
  133. data: { ids: [id] }
  134. })
  135. .then(() => {
  136. ui.showToast({
  137. message: t("删除成功")
  138. });
  139. refresh({});
  140. })
  141. .catch((err) => {
  142. ui.showToast({
  143. message: (err as Response).message!
  144. });
  145. });
  146. }
  147. }
  148. });
  149. }
  150. // 设为默认地址
  151. function onDefaultChange(item: UserAddress) {
  152. // 遍历地址列表,设置选中的地址为默认地址,其他地址取消默认
  153. addressList.value.forEach((e) => {
  154. if (e.id == item.id) {
  155. // 切换当前地址的默认状态
  156. e.isDefault = !e.isDefault;
  157. // 如果取消了默认,则重置默认地址ID
  158. if (!e.isDefault) {
  159. defaultId.value = 0;
  160. }
  161. } else {
  162. // 其他地址全部取消默认
  163. e.isDefault = false;
  164. }
  165. });
  166. request({
  167. url: "/app/user/address/update",
  168. method: "POST",
  169. data: {
  170. id: item.id,
  171. isDefault: item.isDefault
  172. }
  173. });
  174. }
  175. onPullDownRefresh(() => {
  176. refresh({ page: 1 }).finally(() => {
  177. uni.stopPullDownRefresh();
  178. });
  179. });
  180. onReachBottom(() => {
  181. loadMore();
  182. });
  183. onReady(() => {
  184. ui.showLoading(t("加载中"));
  185. // 默认请求
  186. refresh({
  187. page: 1,
  188. size: 20
  189. });
  190. onPageShow(() => {
  191. refresh({});
  192. });
  193. });
  194. </script>