index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. <template>
  2. <view class="app-page">
  3. <button class="avatar-wrapper" open-type="chooseAvatar" @chooseavatar="onChooseAvatar"
  4. style="border: none;background: transparent;margin: 0;padding: 72rpx 0;">
  5. <view class="h-view">
  6. <u--image v-if="form.headimg" width='144rpx' height='144rpx' radius="100%" shape='circle'
  7. customStyle="margin: 0" :src="form.headimg" :fade="true" duration="450" mode='heightFix'>
  8. </u--image>
  9. <view class="v1" v-else>
  10. <u--image width='144rpx' height='144rpx' radius="100%" shape='circle'
  11. :src="`${$getImgBaseUrl()}nologin.png`" :fade="true" duration="450" mode='heightFix'>
  12. </u--image>
  13. </view>
  14. </view>
  15. </button>
  16. <view class="card-box">
  17. <view class="display-flex-between" >
  18. <text class="left-title">昵称</text>
  19. <view class="h-view">
  20. <u-input v-model="form.nickname" placeholder="请输入" type="nickname" border="none" :auto-height="true"
  21. clearable customStyle="margin:0;text-align: right;" />
  22. </view>
  23. </view>
  24. <u-divider ></u-divider>
  25. <view class="display-flex-between" >
  26. <text class="left-title">姓名</text>
  27. <view class="h-view">
  28. <u-input v-model="form.realname" placeholder="请输入" border="none" :auto-height="true" clearable
  29. customStyle="margin:0;text-align: right;" />
  30. </view>
  31. </view>
  32. <u-divider ></u-divider>
  33. <view class="display-flex-between" @click="show2 = true">
  34. <text class="left-title">性别</text>
  35. <view class="h-view" >
  36. {{form.base_sex}} <view class="ml8"><u-icon name="arrow-right" bold color="#333333" size="14"></u-icon></view>
  37. </view>
  38. </view>
  39. <u-divider ></u-divider>
  40. <view class="display-flex-between" >
  41. <text class="left-title">所在地区</text>
  42. <view class="h-view">
  43. <picker mode="region" :value="form.region_area" @change="bindAreaChange">
  44. <view v-if="!form.region_province" class="color-9 display-flex-content-center">省市区县、乡镇等 <view class="ml8"><u-icon name="arrow-right" bold color="#333333" size="14"></u-icon></view></view>
  45. <view v-else class="color-23 display-flex-content-center">{{areaDisplay}} <view class="ml8"><u-icon name="arrow-right" bold color="#333333" size="14"></u-icon></view></view>
  46. </picker>
  47. </view>
  48. </view>
  49. <u-divider ></u-divider>
  50. <view class="display-flex-between" >
  51. <text class="left-title">手机号</text>
  52. <view class="h-view">
  53. <u-input v-model="form.phone" placeholder="请输入" type="number" border="none" :auto-height="true"
  54. clearable :maxlength="11" customStyle="margin:0 20rpx;text-align: right;" />
  55. <button class="btn-c" open-type="getRealtimePhoneNumber"
  56. @getrealtimephonenumber="getrealtimephonenumber" size="mini">获取手机号</button>
  57. </view>
  58. </view>
  59. </view>
  60. <view class="bottom-menu-box">
  61. <view class="agree-box">
  62. <view class="unchecked-tips" v-show="showUnchecked">请先阅读并同意协议</view>
  63. <u-checkbox-group @change="termsChange" v-model="termsChecked" style="margin-left: 30rpx;">
  64. <u-checkbox activeColor="#C29556" name="term" shape="circle" size="40rpx"></u-checkbox>
  65. </u-checkbox-group>
  66. <text class="item-text">
  67. 已阅读并同意
  68. <text class="text-primary fs14 fw600" @click="checkPrimary('2')">《隐私保护协议》</text>
  69. <text class="text-primary fs14 fw600" @click="checkPrimary('1')">《用户协议》</text>
  70. </text>
  71. </view>
  72. <view class="common-btn" @click="commit">提交</view>
  73. </view>
  74. <u-picker :show="show" keyName="label" confirmColor="#815BFF" :columns="[list]" @confirm="confirm"
  75. @cancel="show = false"></u-picker>
  76. <u-picker :show="show2" :columns="columns" ref="uPicker" @confirm="sexConfirm" @cancel="sexCancel" ></u-picker>
  77. </view>
  78. </template>
  79. <script>
  80. import {
  81. uploadBase64File,
  82. } from "@/common/api/common.js";
  83. import {
  84. updateUserInfo,
  85. userRegister,
  86. getUserInfo
  87. } from "@/common/api/user.js";
  88. import {
  89. getUserPhone
  90. } from "@/common/api/common.js";
  91. export default {
  92. data() {
  93. return {
  94. form: {
  95. region_province: '',
  96. region_city: '',
  97. region_area: '',
  98. nickname: undefined,
  99. realname: undefined,
  100. headimg: undefined,
  101. avatarUrl: undefined,
  102. phone: undefined,
  103. base_sex: undefined,
  104. },
  105. columns: [
  106. ['男', '女']
  107. ],
  108. showUnchecked: false,
  109. termsChecked: false,
  110. show: false,
  111. show2: false,
  112. isNeedUpLoad: false,
  113. userInfo: {},
  114. selectItem: {},
  115. }
  116. },
  117. computed: {
  118. areaDisplay() {
  119. const {
  120. region_province = '', region_city = '', region_area = ''
  121. } = this.form
  122. return region_province +' '+ region_city +' ' + region_area
  123. },
  124. },
  125. onLoad(options) {},
  126. onShow() {
  127. this.reUserInfo();
  128. this.getUserInfo();
  129. },
  130. methods: {
  131. getrealtimephonenumber(e) {
  132. console.log("getrealtimephonenumber=>", e)
  133. if (e.detail?.code) {
  134. this.getUserPhone(e.detail?.code)
  135. }
  136. },
  137. async getUserPhone(code) {
  138. const data = {
  139. code: code
  140. }
  141. await getUserPhone(data)
  142. .then(res => {
  143. if (res.data) {
  144. this.form.phone = res.data.purePhoneNumber
  145. }
  146. })
  147. .catch(() => {
  148. uni.hideLoading();
  149. });
  150. },
  151. bindAreaChange(data) {
  152. const {
  153. code,
  154. value
  155. } = data.detail
  156. this.form.region_province = value[0]
  157. this.form.region_city = value[1]
  158. this.form.region_area = value[2]
  159. // this.areaDisplay = value.join('.')
  160. console.log(8999, data, this.form)
  161. },
  162. // 回调参数为包含columnIndex、value、values
  163. sexConfirm(e) {
  164. const {
  165. value,
  166. } = e
  167. console.log(e)
  168. this.form.base_sex = value[0]
  169. this.show2 = false
  170. },
  171. sexCancel(e) {
  172. this.show2 = false
  173. },
  174. checkPrimary(name) {
  175. uni.navigateTo({
  176. url: '/pages/singlePage/index?name=' + name
  177. });
  178. },
  179. termsChange(value) {
  180. if (value.length) {
  181. this.showUnchecked = false;
  182. } else {
  183. this.showUnchecked = true;
  184. }
  185. },
  186. toAuthenticationList() {
  187. uni.navigateTo({
  188. url: '/subPages/authenticationList/index'
  189. })
  190. },
  191. commit() {
  192. if (this.isNeedUpLoad) {
  193. this.getImageInfo()
  194. return
  195. }
  196. if (!this.termsChecked.length) {
  197. this.showUnchecked = true;
  198. return;
  199. }
  200. if (!this.form.region_province) {
  201. uni.$u.toast('请选择所在地区')
  202. return
  203. }
  204. if (!this.form.phone) {
  205. uni.$u.toast('请输入手机号')
  206. return
  207. }
  208. this.userRegister();
  209. },
  210. reUserInfo() {
  211. const userInfo = uni.getStorageSync('userInfo');
  212. if (userInfo && JSON.parse(userInfo).nickname != '' && JSON.parse(userInfo).headimg != '') {
  213. this.userInfo = JSON.parse(userInfo);
  214. const {
  215. headimg,
  216. nickname,
  217. base_sex,
  218. realname,
  219. region_area,
  220. region_city,
  221. region_province,
  222. phone
  223. } =
  224. this.userInfo
  225. this.avatarUrl = headimg
  226. this.form = Object.assign({}, this.form, {
  227. headimg,
  228. nickname,
  229. base_sex,
  230. realname,
  231. region_area,
  232. region_city,
  233. region_province,
  234. phone
  235. })
  236. }
  237. console.log("reUserInfo==>", this.form);
  238. },
  239. async getUserInfo() {
  240. const data = {}
  241. await getUserInfo(data)
  242. .then(res => {
  243. if (res.data) {
  244. uni.setStorageSync('token', res.data.token.token)
  245. uni.setStorageSync('userInfo', JSON.stringify(res.data))
  246. this.userInfo = res.data;
  247. console.log("getUserInfo==>", this.userInfo)
  248. }
  249. })
  250. .catch(() => {
  251. uni.hideLoading();
  252. });
  253. await this.reUserInfo();
  254. },
  255. onChooseAvatar(e) {
  256. const {
  257. avatarUrl
  258. } = e.detail
  259. console.log('成功授权', avatarUrl)
  260. this.form.headimg = avatarUrl
  261. this.isNeedUpLoad = true;
  262. },
  263. getImageInfo() {
  264. // 获取当前图片信息
  265. uni.getImageInfo({
  266. src: this.form.headimg,
  267. success: (image) => {
  268. // 做png/jpeg的类型判断————对不同类型的图像添加不同的转换头信息
  269. if (image.type == 'png' || image.type == 'jpeg') {
  270. // 对符合类型的图片转换为base64类型
  271. uni.getFileSystemManager().readFile({ // 【重点来啦】人家自提供的转码API
  272. filePath: image.path, // 所需转码图像路径
  273. encoding: "base64", // 转码类型
  274. success: (res) => {
  275. // 生成base64
  276. let imageBase64 = 'data:image/' + image.type + ';base64,' + res
  277. .data;
  278. console.log('转base64后:', imageBase64);
  279. this.uploadBase64File(imageBase64)
  280. }
  281. })
  282. } else { // 友好一点,不是以上类型做出提醒
  283. uni.showToast({
  284. title: '当前只支持png/jpeg格式',
  285. duration: 2500,
  286. icon: 'none'
  287. })
  288. }
  289. }
  290. });
  291. },
  292. uploadBase64File(imageBase64) {
  293. uploadBase64File({
  294. base64: imageBase64
  295. }, {
  296. 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
  297. })
  298. .then((res) => {
  299. console.log("uploadFile==>", res.data.url)
  300. this.avatarUrl = res.data.url
  301. this.form.headimg = res.data.url
  302. this.userRegister();
  303. })
  304. .catch(() => {
  305. uni.hideLoading();
  306. });
  307. },
  308. confirm(e) {
  309. this.selectItem = e.value[0];
  310. console.log(e.value[0].label);
  311. this.show = false;
  312. },
  313. userRegister() {
  314. this.isNeedUpLoad = false;
  315. const data = this.form;
  316. updateUserInfo(data)
  317. .then((res) => {
  318. console.log("updateUserInfo==>", res.data)
  319. if (res.data) {
  320. if (res.data.token) {
  321. uni.setStorageSync('token', res.data.token.token)
  322. }
  323. uni.setStorageSync('userInfo', JSON.stringify(res.data))
  324. uni.$u.toast('更新成功')
  325. setTimeout(() => {
  326. uni.navigateBack()
  327. }, 800);
  328. }
  329. });
  330. },
  331. }
  332. }
  333. </script>
  334. <style lang="scss" scoped>
  335. .app-page {
  336. width: 100%;
  337. display: flex;
  338. align-items: center;
  339. flex-direction: column;
  340. }
  341. .card-box {
  342. width: 650rpx;
  343. background: #FFFFFF;
  344. border-radius: 20rpx 20rpx 20rpx 20rpx;
  345. margin: 0 auto 20rpx auto;
  346. padding: 30rpx;
  347. }
  348. .h-view {
  349. flex: 1;
  350. display: flex;
  351. flex-direction: row;
  352. justify-content: flex-end;
  353. align-items: center;
  354. }
  355. .left-title {
  356. font-size: 28rpx;
  357. }
  358. button::after {
  359. border: none;
  360. }
  361. .avatar-wrapper button::before {
  362. padding: 0;
  363. margin: 0;
  364. border-radius: 20rpx;
  365. background: transparent;
  366. border: none;
  367. line-height: 1;
  368. }
  369. .avatar-wrapper button::after {
  370. padding: 0;
  371. margin: 0;
  372. border-radius: 20rpx;
  373. background: transparent;
  374. border: none;
  375. line-height: 1;
  376. }
  377. .agree-box {
  378. display: flex;
  379. color: $gray-1;
  380. position: relative;
  381. align-items: center;
  382. margin: 0 auto;
  383. .unchecked-tips {
  384. position: absolute;
  385. height: 50rpx;
  386. color: #fff;
  387. background-color: rgba($color: #27282a, $alpha: 1);
  388. top: -60rpx;
  389. left: 0;
  390. border-radius: 8rpx;
  391. line-height: 50rpx;
  392. font-size: 24rpx;
  393. padding: 0 16rpx;
  394. &::after {
  395. display: "block";
  396. content: "";
  397. position: absolute;
  398. width: 20rpx;
  399. height: 20rpx;
  400. // background: rgba($color: #27282a, $alpha: 1);
  401. bottom: -6rpx;
  402. left: 10rpx;
  403. transform: rotate(45deg);
  404. border-radius: 4rpx;
  405. }
  406. }
  407. .u-checkbox {
  408. flex-shrink: 0;
  409. align-items: flex-start;
  410. margin-top: 6rpx;
  411. }
  412. .item-text {
  413. font-size: 24rpx;
  414. }
  415. }
  416. .bottom-view {
  417. margin-bottom: var(--window-bottom);
  418. padding-bottom: calc(260rpx);
  419. }
  420. .bottom-menu-box {
  421. height: calc(260rpx);
  422. display: flex;
  423. flex-direction: column;
  424. justify-content: center;
  425. align-items: flex-start;
  426. position: fixed;
  427. z-index: 9;
  428. background: white;
  429. bottom: var(--window-bottom);
  430. left: 0;
  431. right: 0;
  432. width: 100vw;
  433. .primary-btn {
  434. width: 713rpx;
  435. margin-top: 50rpx;
  436. height: 78rpx;
  437. line-height: 78rpx;
  438. background: #815BFF;
  439. border-radius: 40rpx;
  440. font-size: 32rpx;
  441. font-family: PingFang SC-Medium, PingFang SC;
  442. font-weight: 500;
  443. color: #FFFFFF;
  444. }
  445. .common-btn {
  446. // width: 713rpx;
  447. width: calc(100% - 80rpx);
  448. box-sizing: border-box;
  449. margin: 0 auto;
  450. margin-top: 50rpx;
  451. background: linear-gradient( 315deg, #CA9359 0%, #E2B98E 100%);
  452. border-radius: 292rpx 292rpx 292rpx 292rpx;
  453. border:0;
  454. }
  455. button::after {
  456. height: 78rpx;
  457. line-height: 78rpx;
  458. }
  459. .primary-btn:active {
  460. opacity: 0.7;
  461. }
  462. }
  463. .btn-c{
  464. width: 180rpx;
  465. height: 56rpx;
  466. border-radius: 8rpx 8rpx 8rpx 8rpx;
  467. border: 2rpx solid #C29556;
  468. padding: 0 10px;
  469. }
  470. </style>