personal_info.vue 10 KB

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