wx.uvue 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. <template>
  2. <cl-popup
  3. v-model="editVisible"
  4. direction="center"
  5. :title="t('提示')"
  6. size="80%"
  7. @close="onEditClose"
  8. >
  9. <view class="p-4 pt-0">
  10. <cl-text color="info" :pt="{ className: 'text-sm' }">
  11. {{ t("为提供更好的服务,我们邀请您填写昵称、头像等公开信息") }}
  12. </cl-text>
  13. <view
  14. class="flex flex-row justify-between items-center bg-surface-100 rounded-xl p-2 px-3 mt-3 h-[95rpx]"
  15. >
  16. <cl-text>{{ t("头像") }}</cl-text>
  17. <view class="relative">
  18. <cl-avatar :size="60" :src="editForm.avatarUrl"></cl-avatar>
  19. <button
  20. class="absolute top-0 right-0 h-10 w-10 z-10 opacity-0 p-0 m-0"
  21. open-type="chooseAvatar"
  22. @chooseavatar="onEditChooseAvatar"
  23. ></button>
  24. </view>
  25. </view>
  26. <view
  27. class="flex flex-row justify-between items-center bg-surface-100 rounded-xl p-2 px-3 mt-3 h-[95rpx]"
  28. >
  29. <cl-text>{{ t("昵称") }}</cl-text>
  30. <cl-input
  31. v-model="editForm.nickName"
  32. type="nickname"
  33. :border="false"
  34. :placeholder="t('点击输入昵称')"
  35. :maxlength="16"
  36. :pt="{
  37. className: '!bg-transparent !px-0 flex-1',
  38. inner: {
  39. className: 'text-right'
  40. }
  41. }"
  42. ></cl-input>
  43. </view>
  44. <view class="flex flex-row mt-4">
  45. <cl-button
  46. size="large"
  47. text
  48. border
  49. type="light"
  50. :pt="{
  51. className: 'flex-1 !rounded-xl h-[80rpx]'
  52. }"
  53. @tap="editClose"
  54. >{{ t("取消") }}</cl-button
  55. >
  56. <cl-button
  57. size="large"
  58. :pt="{
  59. className: 'flex-1 !rounded-xl h-[80rpx]'
  60. }"
  61. :loading="editLoading"
  62. @tap="editSave"
  63. >{{ t("确认") }}</cl-button
  64. >
  65. </view>
  66. </view>
  67. </cl-popup>
  68. </template>
  69. <script setup lang="ts">
  70. import {
  71. parse,
  72. request,
  73. router,
  74. upload,
  75. userInfo,
  76. useStore,
  77. useWx,
  78. type Response,
  79. type Token
  80. } from "@/cool";
  81. import { t } from "@/locale";
  82. import { useUi } from "@/uni_modules/cool-ui";
  83. import { reactive, ref } from "vue";
  84. const emit = defineEmits(["success"]);
  85. const { user } = useStore();
  86. const ui = useUi();
  87. const wx = useWx();
  88. // 是否显示编辑
  89. const editVisible = ref(false);
  90. // 是否保存中
  91. const editLoading = ref(false);
  92. // 编辑表单
  93. type EditForm = {
  94. avatarUrl: string;
  95. nickName: string;
  96. };
  97. const editForm = reactive<EditForm>({
  98. avatarUrl: "",
  99. nickName: ""
  100. });
  101. // 编辑打开
  102. function editOpen() {
  103. editVisible.value = true;
  104. }
  105. // 编辑关闭
  106. function editClose() {
  107. editVisible.value = false;
  108. }
  109. // 编辑保存
  110. async function editSave() {
  111. // 校验头像是否已上传
  112. if (editForm.avatarUrl == "") {
  113. ui.showToast({
  114. message: t("请上传头像")
  115. });
  116. return;
  117. }
  118. // 校验昵称是否已填写
  119. if (editForm.nickName == "") {
  120. ui.showToast({
  121. message: t("请输入昵称")
  122. });
  123. return;
  124. }
  125. // 设置保存状态为加载中
  126. editLoading.value = true;
  127. // 上传头像并更新用户信息
  128. await upload(editForm.avatarUrl)
  129. .then((url) => {
  130. // 上传成功后,更新用户昵称和头像
  131. user.update({
  132. nickName: editForm.nickName,
  133. avatarUrl: url
  134. });
  135. // 关闭弹窗
  136. editClose();
  137. // 跳转首页
  138. router.nextLogin();
  139. })
  140. .catch((err) => {
  141. // 上传失败,提示错误信息
  142. ui.showToast({
  143. message: (err as Response).message!
  144. });
  145. });
  146. // 恢复保存状态
  147. editLoading.value = false;
  148. }
  149. // 编辑选择头像
  150. function onEditChooseAvatar(e: UniEvent) {
  151. // #ifdef MP-WEIXIN
  152. editForm.avatarUrl = e.detail.avatarUrl;
  153. // #endif
  154. }
  155. // 编辑关闭
  156. function onEditClose() {
  157. editVisible.value = false;
  158. }
  159. // 微信小程序登录
  160. async function miniLogin() {
  161. // #ifdef MP
  162. ui.showLoading(t("登录中"));
  163. await wx.miniLogin().then(async (data) => {
  164. await request({
  165. url: "/app/user/login/mini",
  166. method: "POST",
  167. data
  168. })
  169. .then(async (res) => {
  170. // 设置token
  171. user.setToken(parse<Token>(res)!);
  172. // 获取用户信息
  173. await user.get();
  174. // 是否首次注册,根据业务情况调整判断逻辑
  175. if (userInfo.value?.nickName == "微信用户") {
  176. // 打开编辑弹窗
  177. editOpen();
  178. } else {
  179. // 跳转首页
  180. router.nextLogin();
  181. }
  182. })
  183. .catch((err) => {
  184. ui.showToast({
  185. message: (err as Response).message!
  186. });
  187. });
  188. });
  189. ui.hideLoading();
  190. // #endif
  191. }
  192. // 微信APP登录
  193. function appLogin() {
  194. // 开发中
  195. }
  196. // 微信登录
  197. async function login() {
  198. // #ifdef MP
  199. miniLogin();
  200. // #endif
  201. // #ifdef APP
  202. appLogin();
  203. // #endif
  204. }
  205. defineExpose({
  206. login,
  207. editOpen,
  208. editClose
  209. });
  210. </script>