tuniaoui-wx-user-info.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. <template>
  2. <view v-if="openModal" class="wx-authorization-modal">
  3. <view class="wam__mask" @touchmove.prevent="" @tap.stop="closeModal"></view>
  4. <!-- 内容区域 -->
  5. <view class="wam__wrapper">
  6. <!-- 关闭按钮 -->
  7. <view class="wam__close-btn" @tap.stop="closeModal"><text class="tn-icon-close"></text></view>
  8. <!-- 标题 -->
  9. <view class="wam__title">获取您的昵称、头像</view>
  10. <!-- tips -->
  11. <view class="wam__sub-title">点击设置您的用户头像</view>
  12. <!-- 头像选择 -->
  13. <view class="wam__avatar">
  14. <view class="button-shadow">
  15. <button class="button" open-type="chooseAvatar" @chooseavatar="chooseAvatarEvent">
  16. <view v-if="userInfo.avatar" class="avatar__image"><image class="image" :src="userInfo.avatar" mode="aspectFill"></image></view>
  17. <view v-else class="avatar__empty">
  18. <!-- <image class="image" src="https://cdn.nlark.com/yuque/0/2022/jpeg/280373/1668928062708-assets/web-upload/764843cf-055a-4cb6-b5d3-dca528b33fd4.jpeg" mode="aspectFill"></image> -->
  19. <view class="cuIcon-people user-avatar-empty" style="width: 120rpx;height: 120rpx;"></view>
  20. </view>
  21. <view class="avatar--icon"><view class="tn-icon-camera-fill"></view></view>
  22. </button>
  23. </view>
  24. </view>
  25. <!-- 昵称输入 -->
  26. <view class="wam__nickname">
  27. <view class="nickname__data"><input class="input" type="nickname" v-model="userInfo.nickname" @change="changeNickName" placeholder="请输入昵称" placeholder-style="color: #AAAAAA;" /></view>
  28. </view>
  29. <!-- 手机号码输入 -->
  30. <view class="wam__nickname" v-if="system && system.bind_mobile != 0">
  31. <view class="nickname__data"><input class="input" type="text" v-model="userInfo.mobile" @change="changeMobile" placeholder="请输入手机号码" placeholder-style="color: #AAAAAA;" /></view>
  32. </view>
  33. <!-- 保存按钮 -->
  34. <view
  35. class="wam__submit-btn"
  36. :class="[
  37. {
  38. disabled: !userInfo.avatar || !userInfo.nickname
  39. }
  40. ]"
  41. hover-class="tn-btn-hover-class"
  42. :hover-stay-time="150"
  43. @tap.stop="submitUserInfo"
  44. >
  45. 保 存
  46. </view>
  47. </view>
  48. </view>
  49. </template>
  50. <script>
  51. export default {
  52. options: {
  53. // 在微信小程序中将组件节点渲染为虚拟节点,更加接近Vue组件的表现(不会出现shadow节点下再去创建元素)
  54. virtualHost: true
  55. },
  56. props: {
  57. value: {
  58. type: Boolean,
  59. default: false
  60. }
  61. },
  62. data() {
  63. return {
  64. openModal: false,
  65. userInfo: {
  66. avatar: '',
  67. nickname: '',
  68. mobile: '',
  69. },
  70. system: null,
  71. bindMobile: false,
  72. };
  73. },
  74. watch: {
  75. value: {
  76. handler(val) {
  77. this.openModal = val;
  78. if (val == true) {
  79. this.loadUser();
  80. }
  81. },
  82. immediate: true
  83. }
  84. },
  85. methods: {
  86. // 头像选择
  87. chooseAvatarEvent(e) {
  88. this.userInfo.avatar = e.detail.avatarUrl;
  89. },
  90. // 修改用户昵称
  91. changeNickName(e) {
  92. console.log('changeNickName e', e)
  93. let name = e.detail.value
  94. if(name.length === 0) return
  95. this.userInfo.nickname = name
  96. },
  97. // 修改用户手机
  98. changeMobile(e) {
  99. console.log('changeNickName e', e)
  100. let mobile = e.detail.value
  101. if (mobile.length === 0) return
  102. if (!this.validMobile(this.userInfo.mobile)) return
  103. this.userInfo.mobile = mobile
  104. },
  105. // 更新用户信息
  106. submitUserInfo() {
  107. // 判断是否已经选择了用户头像和输入了用户昵称
  108. if (!this.userInfo.avatar || !this.userInfo.nickname) {
  109. return uni.showToast({
  110. icon: 'none',
  111. title: '请选择头像和输入用户信息'
  112. });
  113. }
  114. if (this.system.bind_mobile && this.system.bind_mobile == 2) {
  115. if (!this.userInfo.mobile) {
  116. return uni.showToast({
  117. icon: 'none',
  118. title: '请选输入手机号码'
  119. });
  120. }
  121. if (!this.validMobile(this.userInfo.mobile)) {
  122. return false
  123. }
  124. }
  125. // 更新完成事件
  126. this.$emit('updated', this.userInfo);
  127. },
  128. // 关闭弹框
  129. closeModal() {
  130. if (this.bindMobile) {
  131. return
  132. }
  133. this.$emit('input', false);
  134. },
  135. // 加载缓存用户信息
  136. loadUser() {
  137. let user = uni.getStorageSync('user');
  138. if (user) {
  139. this.userInfo.avatar = user.avatar;
  140. this.userInfo.nickname = user.nickname;
  141. }
  142. let system = uni.getStorageSync('system')
  143. this.system = system
  144. if (system && system.bind_mobile) {
  145. this.bindMobile = true
  146. }
  147. },
  148. // 验证手机号
  149. validMobile(mobile) {
  150. const pattern = /^1[3456789]\d{9}$/;
  151. let result = pattern.test(mobile);
  152. if (!result) {
  153. uni.showToast({
  154. icon: 'none',
  155. title: '手机号码格式不正确'
  156. });
  157. }
  158. return result
  159. },
  160. }
  161. };
  162. </script>
  163. <style lang="scss" scoped>
  164. @import '../../static/iconfont.css';
  165. .wx-authorization-modal {
  166. position: fixed;
  167. left: 0;
  168. top: 0;
  169. width: 100vw;
  170. height: 100vh;
  171. z-index: 99998;
  172. view {
  173. box-sizing: border-box;
  174. }
  175. .image {
  176. width: 100%;
  177. height: 100%;
  178. border-radius: inherit;
  179. }
  180. .wam {
  181. /* mask */
  182. &__mask {
  183. position: absolute;
  184. left: 0;
  185. top: 0;
  186. width: 100%;
  187. height: 100%;
  188. background-color: rgba(0, 0, 0, 0.5);
  189. opacity: 0;
  190. animation: showMask 0.25s ease 0.1s forwards;
  191. }
  192. /* close-btn */
  193. &__close-btn {
  194. position: absolute;
  195. top: 30rpx;
  196. right: 30rpx;
  197. z-index: 99999;
  198. }
  199. /* wrapper */
  200. &__wrapper {
  201. position: absolute;
  202. left: 0;
  203. bottom: 0;
  204. width: 100%;
  205. background-color: #ffffff;
  206. border-radius: 20rpx 20rpx 0rpx 0rpx;
  207. padding: 40rpx;
  208. padding-top: 60rpx;
  209. padding-bottom: 40rpx;
  210. padding-bottom: calc(constant(safe-area-inset-bottom) + 40rpx);
  211. padding-bottom: calc(env(safe-area-inset-bottom) + 40rpx);
  212. transform-origin: center bottom;
  213. transform: scaleY(0);
  214. animation: showWrapper 0.25s ease 0.1s forwards;
  215. z-index: 99999;
  216. }
  217. /* title */
  218. &__title {
  219. font-size: 34rpx;
  220. }
  221. /* sub-title */
  222. &__sub-title {
  223. font-size: 26rpx;
  224. color: #aaaaaa;
  225. margin-top: 16rpx;
  226. padding-bottom: 30rpx;
  227. }
  228. /* 头像选择 */
  229. &__avatar {
  230. width: 100%;
  231. margin-top: 30rpx;
  232. display: flex;
  233. align-items: center;
  234. justify-content: center;
  235. .button-shadow {
  236. border: 8rpx solid rgba(255, 255, 255, 0.05);
  237. box-shadow: 0rpx 0rpx 80rpx 0rpx rgba(0, 0, 0, 0.15);
  238. border-radius: 50%;
  239. }
  240. .button {
  241. position: relative;
  242. width: 160rpx;
  243. height: 160rpx;
  244. border-radius: 50%;
  245. overflow: visible;
  246. background-image: repeating-linear-gradient(45deg, #e4e9ec, #f8f7f8);
  247. color: #ffffff;
  248. background-color: transparent;
  249. padding: 0;
  250. margin: 0;
  251. font-size: inherit;
  252. line-height: inherit;
  253. border: none;
  254. &::after {
  255. border: none;
  256. }
  257. }
  258. .avatar {
  259. &__empty,
  260. &__image {
  261. width: 100%;
  262. height: 100%;
  263. border-radius: inherit;
  264. }
  265. &--icon {
  266. position: absolute;
  267. right: -10rpx;
  268. bottom: -6rpx;
  269. width: 60rpx;
  270. height: 60rpx;
  271. // transform: translate(50%, 50%);
  272. background-color: #1d2541;
  273. color: #ffffff;
  274. border-radius: 50%;
  275. border: 6rpx solid #ffffff;
  276. line-height: 1;
  277. font-size: 36rpx;
  278. display: flex;
  279. align-items: center;
  280. justify-content: center;
  281. }
  282. }
  283. }
  284. /* 昵称 */
  285. &__nickname {
  286. margin-top: 40rpx;
  287. .nickname {
  288. &__data {
  289. margin-top: 16rpx;
  290. width: 100%;
  291. padding: 26rpx 20rpx;
  292. border-radius: 10rpx;
  293. background-color: #f8f7f8;
  294. .input {
  295. color: #080808;
  296. }
  297. }
  298. }
  299. }
  300. /* 保存按钮 */
  301. &__submit-btn {
  302. width: 100%;
  303. background-color: #05c160;
  304. color: #ffffff;
  305. margin-top: 60rpx;
  306. border-radius: 10rpx;
  307. padding: 25rpx;
  308. font-size: 32rpx;
  309. display: flex;
  310. align-items: center;
  311. justify-content: center;
  312. &.disabled {
  313. background-color: #e6e6e6;
  314. }
  315. }
  316. }
  317. }
  318. .tn-btn-hover-class {
  319. box-shadow: inset 10rpx 2rpx 40rpx 0rpx rgba(0, 0, 0, 0.05);
  320. }
  321. @keyframes showMask {
  322. 0% {
  323. opacity: 0;
  324. }
  325. 100% {
  326. opacity: 1;
  327. }
  328. }
  329. @keyframes showWrapper {
  330. 0% {
  331. transform: scaleY(0);
  332. }
  333. 100% {
  334. transform: scaleY(1);
  335. }
  336. }
  337. </style>