personal_info.vue 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. <template>
  2. <view class="personal-info">
  3. <!-- 上传 -->
  4. <view class="upload-box border-bottom">
  5. <up-upload
  6. @afterRead="
  7. async (e) => {
  8. await afterRead(e);
  9. getImage();
  10. }
  11. "
  12. name="1"
  13. :maxCount="1"
  14. :previewImage="false"
  15. :deletable="false"
  16. :multiple="false"
  17. >
  18. <!-- <template #default> -->
  19. <view class="upload-block">
  20. <up-avatar
  21. size="160rpx"
  22. shape="circle"
  23. :src="userInfo.avatar"
  24. mode="aspectFill"
  25. ></up-avatar>
  26. </view>
  27. <!-- </template> -->
  28. </up-upload>
  29. </view>
  30. <view class="flex-center-between border-bottom personal-info-item">
  31. <text class="label_width">昵称</text>
  32. <up-input
  33. class="title-input"
  34. placeholder="请输入"
  35. type="text"
  36. confirmType="完成"
  37. maxlength="50"
  38. :adjustPosition="false"
  39. border="none"
  40. :showWordLimit="true"
  41. v-model="userInfo.nickname"
  42. inputAlign="right"
  43. @blur="changeName"
  44. ></up-input>
  45. </view>
  46. <view class="flex-center-between border-bottom personal-info-item">
  47. <text class="label_width">手机号</text>
  48. <text class="gray">{{telEncrypt(userInfo.phone)}}</text>
  49. </view>
  50. <view class="flex-center-between border-bottom personal-info-item" @click="pickerSexShow = true">
  51. <text class="label_width">性别</text>
  52. <view class="flex-center-between">
  53. <text>{{sexText}}</text>
  54. <uni-icons type="right" size="21" color="#888"></uni-icons>
  55. </view>
  56. </view>
  57. <view class="flex-center-between border-bottom personal-info-item">
  58. <text class="label_width">地址</text>
  59. <picker mode="multiSelector" @change="bindRegionChange" @columnchange="bindMultiPickerColumnChange"
  60. :value="valueRegion" :range="multiArray">
  61. <view class='flex-center-between'>
  62. <view class="picker line1">{{ region[0] }},{{ region[1] }},{{ region[2] }}</view>
  63. <uni-icons type="right" size="21" color="#888"></uni-icons>
  64. </view>
  65. </picker>
  66. <!-- <up-input
  67. class="title-input"
  68. placeholder="请输入"
  69. type="text"
  70. confirmType="完成"
  71. maxlength="50"
  72. :adjustPosition="false"
  73. border="none"
  74. :showWordLimit="true"
  75. v-model="userInfo.addres"
  76. inputAlign="right"
  77. @blur="change"
  78. ></up-input> -->
  79. </view>
  80. <view class="flex-center-between border-bottom personal-info-item">
  81. <text class="label_width">年龄</text>
  82. <up-input
  83. class="title-input"
  84. placeholder="请输入"
  85. type="text"
  86. confirmType="完成"
  87. maxlength="50"
  88. :adjustPosition="false"
  89. border="none"
  90. :showWordLimit="true"
  91. v-model="userInfo.age"
  92. inputAlign="right"
  93. @blur="change"
  94. ></up-input>
  95. </view>
  96. <view class="flex-center-between border-bottom personal-info-item">
  97. <text class="label_width">个人简介</text>
  98. <up-input
  99. class="title-input"
  100. placeholder="请输入"
  101. type="text"
  102. confirmType="完成"
  103. maxlength="50"
  104. :adjustPosition="false"
  105. border="none"
  106. :showWordLimit="true"
  107. v-model="userInfo.mark"
  108. inputAlign="right"
  109. @blur="change"
  110. ></up-input>
  111. </view>
  112. <view
  113. class="flex-center-between border-bottom personal-info-item"
  114. @tap.stop="setPayword"
  115. >
  116. <text class="label_width">支付密码</text>
  117. <!-- <up-input
  118. class="title-input"
  119. placeholder="请输入"
  120. type="text"
  121. confirmType="完成"
  122. maxlength="6"
  123. :adjustPosition="false"
  124. border="none"
  125. :showWordLimit="true"
  126. v-model="userInfo.payPassword"
  127. inputAlign="right"
  128. :password="true"
  129. :disabled="true"
  130. :passwordVisibilityToggle="false"
  131. disabledColor=""
  132. ></up-input> -->
  133. <text>* * * * * *</text>
  134. </view>
  135. <up-picker
  136. @confirm="changeSex"
  137. @cancel="pickerSexShow = false"
  138. :show="pickerSexShow"
  139. :columns="[
  140. [
  141. { label: '男', id: 1 },
  142. { label: '女', id: 2 },
  143. { label: '保密', id: 3 },
  144. ],
  145. ]"
  146. keyName="label"
  147. valueName="id"
  148. ></up-picker>
  149. <button
  150. @click="submitFn"
  151. class="submit-btn"
  152. >提交</button>
  153. <!-- 页面内 容结束 -->
  154. <PayPop ref="paypopRef" :pwdlength="6" @pwd_e="handlerPwd"></PayPop>
  155. </view>
  156. </template>
  157. <script setup>
  158. import { ref, computed, nextTick } from "vue";
  159. import PayPop from "../../components/pay-pop/pay-pop.vue";
  160. import { useImageUpload } from "@/hooks/useImageUpload";
  161. import { useAppStore } from "@/stores/app";
  162. import { onLoad } from "@dcloudio/uni-app";
  163. import { useToast } from "@/hooks/useToast";
  164. import { getUserInfo, userEdit, registerpayPasswordAPI } from "@/api/user";
  165. import { getCity } from "@/api/api.js";
  166. import Cache from "@/utils/cache";
  167. import { telEncrypt } from "@/utils/util.js";
  168. const paypopRef = ref(null);
  169. const { Toast } = useToast();
  170. const { imageList, afterRead, deletePic, uploadLoading } = useImageUpload({
  171. pid: 5,
  172. model: "book",
  173. });
  174. const appStore = useAppStore();
  175. const userInfo = ref({
  176. avatar: "",
  177. nickname: "",
  178. addres: "",
  179. mark: "",
  180. sex: "",
  181. age: "",
  182. });
  183. const pickerSexShow = ref(false);
  184. const sexText = computed(() => {
  185. return userInfo.value.sex == 1
  186. ? "男"
  187. : userInfo.value.sex == 2
  188. ? "女"
  189. : userInfo.value.sex == 3
  190. ? "保密"
  191. : "未知";
  192. });
  193. //省市区选择
  194. const district = ref([]);
  195. const multiArray = ref([[], [], []]);
  196. const multiIndex = ref([0, 0, 0]);
  197. const region = ref(["省", "市", "区"]);
  198. const valueRegion = ref([0, 0, 0]);
  199. onLoad(() => {
  200. console.log("personal_info 页面 onLoad");
  201. fetchUserInfo();
  202. getCityList();
  203. });
  204. const changeSex = (e) => {
  205. console.log("changeSex", e.value[0]);
  206. userInfo.value.sex = e.value[0].id;
  207. pickerSexShow.value = false;
  208. // change();
  209. };
  210. // 设置支付密码
  211. const setPayword = () => {
  212. console.log(111111);
  213. console.log(paypopRef.value);
  214. nextTick(() => {
  215. paypopRef.value.Open();
  216. });
  217. };
  218. const handlerPwd = async (e) => {
  219. const res = await registerpayPasswordAPI({
  220. account: appStore.userInfo.phone,
  221. payPassword: e,
  222. });
  223. uni.showToast({
  224. title: "修改成功",
  225. duration: 2000,
  226. });
  227. change();
  228. };
  229. // 获取用户头像
  230. async function getImage() {
  231. console.log("getImage", imageList.value[0]);
  232. if (imageList.value.length > 0) {
  233. if (imageList.value[0].status == "success") {
  234. userInfo.value.avatar = imageList.value[0].info.url;
  235. // change();
  236. } else {
  237. Toast({ title: "上传失败" });
  238. }
  239. }
  240. imageList.value = [];
  241. }
  242. function submitFn() {
  243. change();
  244. }
  245. function changeName(e) {
  246. // console.log(e)
  247. // console.log(userInfo.value)
  248. }
  249. const change = async () => {
  250. await userEdit(userInfo.value);
  251. Toast({ title: "修改成功", endtime: 1500 });
  252. appStore.USERINFO();
  253. setTimeout(() => {
  254. uni.navigateBack();
  255. }, 1600);
  256. // const { data } = await getUserInfo(appStore.uid);
  257. // appStore.UPDATE_userPanelInfo(data);
  258. };
  259. // 获取用户信息
  260. async function fetchUserInfo() {
  261. try {
  262. const { data } = await getUserInfo(appStore.uid);
  263. userInfo.value = data;
  264. userInfo.value.addres = userInfo.value.addres || "";
  265. const list = userInfo.value.addres.split("-");
  266. if (list.length > 0) {
  267. region.value = [list[0], list[1], list[2]];
  268. }
  269. } catch (error) {
  270. console.error("otherUserinfo", error);
  271. Toast({ title: "获取用户信息失败" });
  272. }
  273. }
  274. function bindRegionChange(e) {
  275. const mi = multiIndex.value;
  276. const province = district.value[mi[0]] || { child: [] };
  277. const ma = multiArray.value;
  278. const value = e.detail.value;
  279. region.value = [ma[0][value[0]], ma[1][value[1]], ma[2][value[2]]];
  280. userInfo.value.addres = region.value.join("-");
  281. valueRegion.value = [0, 0, 0];
  282. // change();
  283. initialize();
  284. }
  285. function getCityList() {
  286. getCity().then((res) => {
  287. district.value = res.data;
  288. let oneDay = 24 * 3600 * 1000;
  289. Cache.setItem({ name: "cityList", value: res.data, expires: oneDay * 7 }); //设置七天过期时间
  290. initialize();
  291. });
  292. }
  293. function initialize() {
  294. if (district.value.length) {
  295. let province = [],
  296. city = [],
  297. area = [];
  298. let cityChildren = district.value[0].child || [];
  299. let areaChildren = cityChildren.length ? cityChildren[0].child || [] : [];
  300. district.value.forEach((item) => province.push(item.name));
  301. cityChildren.forEach((item) => city.push(item.name));
  302. areaChildren.forEach((item) => area.push(item.name));
  303. multiArray.value = [province, city, area];
  304. }
  305. }
  306. function bindMultiPickerColumnChange(e) {
  307. const column = e.detail.column;
  308. const value = e.detail.value;
  309. const ma = multiArray.value;
  310. const mi = multiIndex.value;
  311. mi[column] = value;
  312. switch (column) {
  313. case 0:
  314. const currentCity = district.value[value] || { child: [] };
  315. const areaList = currentCity.child[0] || { child: [] };
  316. ma[1] = currentCity.child.map((item) => item.name);
  317. ma[2] = areaList.child.map((item) => item.name);
  318. break;
  319. case 1:
  320. const cityList = district.value[mi[0]].child[mi[1]].child || [];
  321. ma[2] = cityList.map((item) => item.name);
  322. break;
  323. case 2:
  324. break;
  325. }
  326. multiArray.value = [...ma];
  327. multiIndex.value = [...mi];
  328. }
  329. </script>
  330. <style lang="scss">
  331. .personal-info {
  332. padding: 0 30rpx;
  333. .upload-block {
  334. display: flex;
  335. justify-content: center;
  336. width: 90vw;
  337. box-sizing: border-box;
  338. padding: 80rpx 0;
  339. }
  340. .personal-info-item {
  341. padding: 30rpx 0;
  342. .label_width {
  343. width: 200rpx;
  344. display: inline-block;
  345. }
  346. }
  347. .submit-btn {
  348. font-size: 28rpx;
  349. color: #fff;
  350. height: 80rpx;
  351. line-height: 80rpx;
  352. border-radius: 50rpx;
  353. background-color: $header-color;
  354. border: none;
  355. margin-top: 20px;
  356. }
  357. }
  358. </style>