@uxda/appkit 4.0.3 → 4.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/.eslintrc.mjs +7 -7
  2. package/README.md +187 -187
  3. package/babel.config.js +12 -12
  4. package/package.json +75 -80
  5. package/project.config.json +15 -15
  6. package/project.tt.json +13 -13
  7. package/rollup.config.mjs +56 -56
  8. package/src/Appkit.ts +65 -65
  9. package/src/balance/api/endpoints.ts +126 -126
  10. package/src/balance/api/index.ts +82 -82
  11. package/src/balance/components/AccountView.vue +748 -748
  12. package/src/balance/components/BalanceCard.vue +205 -209
  13. package/src/balance/components/BalanceReminder.vue +85 -85
  14. package/src/balance/components/ConsumptionFilter.vue +218 -218
  15. package/src/balance/components/ConsumptionRules.vue +68 -68
  16. package/src/balance/components/DateFilter.vue +227 -226
  17. package/src/balance/components/DateRange.vue +78 -0
  18. package/src/balance/components/ListFilter.vue +64 -0
  19. package/src/balance/components/ListFilterPicker.vue +187 -0
  20. package/src/balance/components/SecondBalance.vue +71 -71
  21. package/src/balance/components/Tip.vue +45 -45
  22. package/src/balance/components/index.ts +13 -9
  23. package/src/balance/types.ts +91 -90
  24. package/src/components/bt-cropper/index.vue +774 -774
  25. package/src/components/bt-cropper/utils/calcCropper.js +42 -42
  26. package/src/components/bt-cropper/utils/calcImagePosition.js +23 -23
  27. package/src/components/bt-cropper/utils/calcImageSize.js +37 -37
  28. package/src/components/bt-cropper/utils/calcPointDistance.js +12 -12
  29. package/src/components/bt-cropper/utils/calcRightAndBottom.js +7 -7
  30. package/src/components/bt-cropper/utils/ratio.js +3 -3
  31. package/src/components/bt-cropper/utils/tools.js +25 -25
  32. package/src/components/dd-area/index.vue +225 -225
  33. package/src/components/dd-icon/doc.md +21 -21
  34. package/src/components/dd-icon/index.vue +23 -23
  35. package/src/components/dd-notice-bar/index.vue +78 -78
  36. package/src/components/dd-search/doc.md +34 -34
  37. package/src/components/dd-search/index.vue +168 -168
  38. package/src/components/dd-selector/index.vue +124 -124
  39. package/src/components/dd-skeleton/doc.md +19 -19
  40. package/src/components/dd-skeleton/index.vue +36 -36
  41. package/src/components/ocr-id/index.vue +114 -114
  42. package/src/components/ocr-id/types.d.ts +12 -12
  43. package/src/global.ts +6 -6
  44. package/src/index.ts +89 -89
  45. package/src/main.scss +1 -1
  46. package/src/notice/api/endpoints.ts +17 -17
  47. package/src/notice/api/index.ts +82 -82
  48. package/src/notice/components/NoticeBanner.vue +243 -243
  49. package/src/notice/components/NoticeEntry.vue +99 -99
  50. package/src/notice/components/NoticeList.vue +315 -315
  51. package/src/notice/components/NoticePopup.vue +161 -161
  52. package/src/notice/components/index.ts +5 -5
  53. package/src/notice/components/useCommonList.ts +86 -86
  54. package/src/notice/components/useNotice.ts +35 -35
  55. package/src/notice/index.ts +1 -1
  56. package/src/notice/types.ts +25 -25
  57. package/src/payment/api/config.ts +7 -7
  58. package/src/payment/api/endpoints.ts +103 -103
  59. package/src/payment/api/index.ts +71 -71
  60. package/src/payment/components/AmountPicker.vue +93 -93
  61. package/src/payment/components/RechargeResult.vue +69 -69
  62. package/src/payment/components/RechargeView.vue +154 -154
  63. package/src/payment/components/RightsPicker.vue +105 -105
  64. package/src/payment/components/TradeView.vue +298 -298
  65. package/src/payment/components/UserAgreement.vue +234 -234
  66. package/src/payment/components/index.ts +22 -22
  67. package/src/payment/index.ts +5 -5
  68. package/src/payment/services/index.ts +16 -16
  69. package/src/payment/services/invoke-recharge.ts +25 -25
  70. package/src/payment/services/request-payment.ts +58 -58
  71. package/src/payment/types.ts +28 -28
  72. package/src/register/components/SelfRegistration.vue +254 -254
  73. package/src/register/components/index.ts +2 -2
  74. package/src/shared/components/AppDrawer.vue +58 -58
  75. package/src/shared/components/AppVerify.vue +98 -0
  76. package/src/shared/components/DeviceVersion.vue +68 -68
  77. package/src/shared/components/EmptyView.vue +33 -33
  78. package/src/shared/components/OcrIcon.vue +119 -0
  79. package/src/shared/components/PageHeader.vue +79 -79
  80. package/src/shared/components/index.ts +7 -5
  81. package/src/shared/composables/index.ts +7 -5
  82. package/src/shared/composables/useCountdown.ts +46 -46
  83. package/src/shared/composables/useCrypto.ts +76 -0
  84. package/src/shared/composables/useDragBox.ts +97 -97
  85. package/src/shared/composables/useEncode.ts +43 -43
  86. package/src/shared/composables/useSafeArea.ts +46 -46
  87. package/src/shared/composables/useTabbar.ts +24 -24
  88. package/src/shared/composables/useUpload.ts +55 -0
  89. package/src/shared/composables/useValidator.ts +31 -31
  90. package/src/shared/http/Http.ts +136 -136
  91. package/src/shared/http/index.ts +1 -1
  92. package/src/shared/http/types.ts +157 -157
  93. package/src/shared/index.ts +3 -3
  94. package/src/shared/weixin/payment.ts +38 -38
  95. package/src/styles/fonts.scss +2 -2
  96. package/src/styles/vars.scss +3 -3
  97. package/src/user/api/endpoints.ts +17 -17
  98. package/src/user/api/index.ts +87 -87
  99. package/src/user/components/LoginSetting.vue +114 -114
  100. package/src/user/components/UserBinding.vue +307 -307
  101. package/src/user/components/UserBindingSuccess.vue +80 -80
  102. package/src/user/components/UserEntry.vue +137 -142
  103. package/src/user/components/UserFeedback.vue +440 -440
  104. package/src/user/components/UserFeedbackEntry.vue +192 -192
  105. package/src/user/components/UserHeadCrop.vue +65 -65
  106. package/src/user/components/UserInfo.vue +632 -632
  107. package/src/user/components/UserResourceEmpty.vue +75 -75
  108. package/src/user/components/index.ts +21 -21
  109. package/src/user/index.ts +1 -1
  110. package/tsconfig.json +30 -30
  111. package/types/global.d.ts +21 -21
  112. package/types/vue.d.ts +10 -10
  113. package/dist/appkit.css +0 -2331
  114. package/dist/assets/asset-3B_CoPto +0 -1
  115. package/dist/assets/asset-DcH8Kg-2 +0 -1
  116. package/dist/index.js +0 -7176
@@ -1,632 +1,632 @@
1
- <template>
2
- <scroll-view :scroll-y="!userState.visible && !avatarVisible" class="user-info">
3
- <DdSkeleton v-if="firstLoading" :row="3"></DdSkeleton>
4
- <div v-else class="user-info-wrap">
5
- <div class="user-info-tit">账号信息</div>
6
- <div class="user-info-head">
7
- <div class="user-info-head-avatar" @click="avatarVisible = true">
8
- <img
9
- class="user-info-head-img"
10
- mode="aspectFit"
11
- v-if="userInfo.avatar"
12
- :src="userInfo.avatar"
13
- alt=""
14
- />
15
- <img
16
- class="user-info-head-img"
17
- mode="aspectFit"
18
- v-else
19
- src="https://cdn.ddjf.com/static/images/wx-yunservice/account-head.png"
20
- alt=""
21
- />
22
- <div class="user-info-head-upload">
23
- <img
24
- class="user-info-head-upload-icon"
25
- mode="aspectFit"
26
- src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzQiIGhlaWdodD0iMzQiIHZpZXdCb3g9IjAgMCAzNCAzNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yMi4wOTk5IDE4LjQyMjRDMjIuMDk5OSAxNS41ODMyIDE5LjgxNjYgMTMuMjgxNiAxNi45OTk5IDEzLjI4MTZDMTQuMTgzMyAxMy4yODE2IDExLjg5OTkgMTUuNTgzMiAxMS44OTk5IDE4LjQyMjRDMTEuODk5OSAyMS4yNjE2IDE0LjE4MzMgMjMuNTYzMiAxNi45OTk5IDIzLjU2MzJDMTkuODE2NiAyMy41NjMyIDIyLjA5OTkgMjEuMjYxNiAyMi4wOTk5IDE4LjQyMjRWMTguNDIyNFoiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iMi41NSIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIzLjc5OTkgNS45OTg4QzIzLjc5OTkgNi4yMzUzOSAyMy45OTAyIDYuNDI3MiAyNC4yMjQ5IDYuNDI3MkgyNS45MjVDMjkuNDQ1OCA2LjQyNzIgMzIuMyA5LjMwNDIxIDMyLjMgMTIuODUzMlYyMy45OTE2QzMyLjMgMjcuNTQwNiAyOS40NDU4IDMwLjQxNzYgMjUuOTI1IDMwLjQxNzZIOC4wNzQ5NEM0LjU1NDE0IDMwLjQxNzYgMS42OTk5NSAyNy41NDA2IDEuNjk5OTUgMjMuOTkxNlYxMi44NTMyQzEuNjk5OTUgOS4zMDQyMSA0LjU1NDE0IDYuNDI3MiA4LjA3NDk0IDYuNDI3Mkg5Ljc3NDk1QzEwLjAwOTcgNi40MjcyIDEwLjIgNi4yMzUzOSAxMC4yIDUuOTk4OEMxMC4yIDUuNzA5NDkgMTAuMjQwNiA1LjQyOTc1IDEwLjMxNjUgNS4xNjUwNkMxMC42NzQ4IDMuOTE0NTEgMTEuODE4OSAzIDEzLjE3NSAzSDIwLjgyNUMyMi40NjggMyAyMy43OTk5IDQuMzQyNjEgMjMuNzk5OSA1Ljk5ODhWNS45OTg4WiIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIyLjU1IiBzdHJva2UtbGluZWNhcD0ic3F1YXJlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNy42NDk5IDEwLjI4MjhDOC44MjM1MSAxMC4yODI4IDkuNzc0OSAxMS4yNDE4IDkuNzc0OSAxMi40MjQ4QzkuNzc0OSAxMy42MDc4IDguODIzNTEgMTQuNTY2OCA3LjY0OTkgMTQuNTY2OEM2LjQ3NjMgMTQuNTY2OCA1LjUyNDkgMTMuNjA3OCA1LjUyNDkgMTIuNDI0OEM1LjUyNDkgMTEuMjQxOCA2LjQ3NjMgMTAuMjgyOCA3LjY0OTkgMTAuMjgyOFoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo="
27
- alt=""
28
- />
29
- </div>
30
- </div>
31
- <nut-cell
32
- title="登录手机号"
33
- is-link
34
- :desc="encodePhone(userInfo.mobile || '')"
35
- @click="toBinding"
36
- />
37
- </div>
38
-
39
- <div class="user-info-tit">企业/团队</div>
40
- <div class="user-info-team">
41
- <div v-for="(item, key) in userInfo.tenantInfoList" :key="key" class="user-info-team-item">
42
- <div class="user-info-team-item-avatar">
43
- <img
44
- v-if="item.tenantLogo"
45
- class="user-info-team-item-avatar-img"
46
- mode="aspectFit"
47
- :src="item.tenantLogo"
48
- alt=""
49
- />
50
- <img
51
- v-else
52
- class="user-info-team-item-avatar-img empty"
53
- mode="aspectFit"
54
- src="https://cdn.ddjf.com/static/images/customer-center/tenant-logo.png"
55
- alt=""
56
- />
57
- </div>
58
- <div class="user-info-team-item-bd">
59
- <div class="user-info-team-item-title">{{ item.tenantName }}</div>
60
- <div class="user-info-team-item-app" v-if="item.appRoleInfo">
61
- <div
62
- class="user-info-team-item-app-tag"
63
- v-for="(aitem, akey) in item.appRoleInfo || []"
64
- :key="akey"
65
- >
66
- {{ aitem.appAbbr }}
67
- </div>
68
- <div class="user-info-team-item-role-btn" @click="toShowRole(item)">
69
- 角色详情
70
- <img
71
- :class="{ showRole: item.showRole }"
72
- class="user-info-team-item-role-btn-icon"
73
- src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE4IDlMMTIgMTVMNiA5IiBzdHJva2U9IiMwMTdGRkYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cjwvc3ZnPgo="
74
- alt=""
75
- />
76
- </div>
77
- </div>
78
- <div class="user-info-team-item-role" v-if="item.showRole">
79
- <div
80
- class="user-info-team-item-role-item"
81
- v-for="(aitem, akey) in item.appRoleInfo || []"
82
- :key="akey"
83
- >
84
- <div class="user-info-team-item-role-item-name">{{ aitem.appAbbr }}</div>
85
- <div class="user-info-team-item-role-item-info">
86
- {{ aitem.roleName }}
87
- </div>
88
- </div>
89
- </div>
90
- <div class="user-info-team-item-user">
91
- {{ item.fullName }}
92
- <img
93
- @click="toUserNameChange(item)"
94
- class="user-info-team-item-user-icon"
95
- src="https://cdn.ddjf.com/static/images/appkit/edit.png"
96
- alt=""
97
- />
98
- </div>
99
- <div class="user-info-team-item-dept">
100
- <div
101
- v-for="(ditem, dkey) in item.deptNames"
102
- :key="dkey"
103
- class="user-info-team-item-dept-item"
104
- >
105
- {{ ditem }}
106
- </div>
107
- </div>
108
- </div>
109
- </div>
110
- </div>
111
-
112
- <div class="user-info-ft">
113
- <nut-button class="user-info-ft-btn" @click="toLogout" plain type="primary"
114
- >退出登录</nut-button
115
- >
116
- </div>
117
- </div>
118
- </scroll-view>
119
-
120
- <!-- 修改用户名弹框 -->
121
- <nut-dialog
122
- title="输入新的用户名"
123
- :border="false"
124
- pop-class="change-username-popup"
125
- v-model:visible="userState.visible"
126
- @cancel="onUserNameCancel"
127
- >
128
- <nut-input :max-length="20" placeholder="请输入新的用户名" v-model="userState.value" />
129
- <template #footer>
130
- <nut-button class="change-username-popup-cancel" type="default" @click="onUserNameCancel">
131
- 取消
132
- </nut-button>
133
- <nut-button class="change-username-popup-ok" type="primary" @click="onUserNameOk">
134
- 确定
135
- </nut-button>
136
- </template>
137
- </nut-dialog>
138
-
139
- <!-- 修改头像弹框 -->
140
- <nut-popup
141
- pop-class="upload-avatar-popup"
142
- style="background: transparent"
143
- v-model:visible="avatarVisible"
144
- :overlay-style="{ background: 'rgba(0, 0, 0, 0.9)' }"
145
- >
146
- <div class="upload-avatar-popup-box">
147
- <img
148
- class="upload-avatar-popup-avatar"
149
- mode="aspectFit"
150
- v-if="userInfo.avatar"
151
- :src="userInfo.avatar"
152
- alt=""
153
- />
154
- <img
155
- class="upload-avatar-popup-avatar"
156
- mode="aspectFit"
157
- v-else
158
- src="https://cdn.ddjf.com/static/images/wx-yunservice/account-head.png"
159
- alt=""
160
- />
161
- <div class="upload-avatar-popup-btn" @click="toUpload">更换头像</div>
162
- </div>
163
- </nut-popup>
164
- </template>
165
-
166
- <script lang="ts" setup>
167
- import Taro, { useDidShow } from '@tarojs/taro'
168
- import { ref, onMounted, reactive, onUnmounted } from 'vue'
169
- import { useAppKitOptions } from '../../Appkit'
170
- import { useEncode } from '../../shared/composables/useEncode'
171
- import DdSkeleton from '../../components/dd-skeleton/index.vue'
172
- import { useHttp } from '../api'
173
-
174
- const props = withDefaults(
175
- defineProps<{
176
- miniType?: string
177
- app?: string
178
- userId: string
179
- }>(),
180
- {
181
- miniType: '05',
182
- app: '',
183
- userId: '',
184
- }
185
- )
186
-
187
- const { encodePhone } = useEncode()
188
-
189
- useDidShow(() => {
190
- getUserInfoByUserId()
191
- })
192
- onMounted(() => {
193
- Taro.eventCenter.on('USER-HEAD-CROP-OK', updateImage)
194
- })
195
- onUnmounted(() => {
196
- Taro.eventCenter.off('USER-HEAD-CROP-OK')
197
- })
198
-
199
- const firstLoading = ref(true)
200
- const userInfo = ref<any>({})
201
- // 根据用户id,查询用户所在租户列表
202
- function getUserInfoByUserId() {
203
- const $http = useHttp()
204
-
205
- $http
206
- .get(`/cas/sysAccount/getAccountInfo/${props.userId}`)
207
- .then((result: any) => {
208
- userInfo.value = result
209
- firstLoading.value = false
210
- })
211
- .catch(() => {
212
- firstLoading.value = false
213
- })
214
- }
215
-
216
- // 修改头像弹框
217
- const avatarVisible = ref(false)
218
-
219
- // 去上传头像
220
- async function toUpload() {
221
- if (!userInfo.value.avatar) {
222
- const profile = await Taro.getUserProfile({
223
- desc: '头像用于改变默认头像',
224
- })
225
-
226
- const res = await Taro.downloadFile({
227
- url: profile.userInfo.avatarUrl,
228
- })
229
-
230
- updateImage(res.tempFilePath)
231
- } else {
232
- let res = await Taro.chooseImage({
233
- count: 1,
234
- })
235
- if (res.tempFilePaths) {
236
- const filePath = res.tempFilePaths[0]
237
-
238
- emits('crop', filePath)
239
- }
240
- }
241
- }
242
-
243
- // 上传图片
244
- async function updateImage(filePath: string) {
245
- Taro.showLoading({
246
- title: '上传中...',
247
- })
248
- const appkitOptions = useAppKitOptions()
249
- const $http = useHttp()
250
-
251
- let Res: any = await Taro.uploadFile({
252
- url: `${appkitOptions.baseUrl()}/cas/file/uploadImg`,
253
- filePath: filePath,
254
- name: 'file',
255
- formData: {
256
- objectNo: `${userInfo.value.mobile}${Date.now()}`,
257
- objectTypeCode: `MINI_HEADIMAGE${props.miniType}`,
258
- },
259
- header: {
260
- token: appkitOptions.tempToken() || appkitOptions.token(),
261
- },
262
- })
263
- avatarVisible.value = false
264
-
265
- const res = JSON.parse(Res.data)
266
- if (res.success) {
267
- $http
268
- .post('/cas/sysUser/update', {
269
- appCode: props.app,
270
- avatar: res.result,
271
- userId: props.userId,
272
- })
273
- .then(() => {
274
- Taro.hideLoading()
275
- Taro.showToast({ title: '头像上传成功', icon: 'none' })
276
- getUserInfoByUserId()
277
- emits('avatar-success', res.result)
278
- })
279
- .catch(() => {
280
- Taro.hideLoading()
281
- })
282
- } else {
283
- Taro.hideLoading()
284
- }
285
- }
286
-
287
- // 查看角色详情
288
- function toShowRole(item: any) {
289
- item.showRole = !item.showRole
290
- }
291
-
292
- // 更换用户名
293
- const userState = reactive({
294
- visible: false,
295
- value: '',
296
- oldName: '',
297
- tenantId: '',
298
- })
299
- function toUserNameChange(item: any) {
300
- userState.visible = true
301
- userState.oldName = item.fullName
302
- userState.tenantId = item.tenantId
303
- }
304
- function onUserNameCancel() {
305
- userState.visible = false
306
- userState.value = ''
307
- userState.oldName = ''
308
- userState.tenantId = ''
309
- }
310
- function onUserNameOk() {
311
- if (!userState.value) {
312
- return Taro.showToast({
313
- title: '请输入用户名',
314
- icon: 'none',
315
- })
316
- }
317
- if (userState.value === userState.oldName) {
318
- return Taro.showToast({
319
- title: '用户名不能与原用户名相同',
320
- icon: 'none',
321
- })
322
- }
323
-
324
- const $http = useHttp()
325
-
326
- $http
327
- .post('/cas/sysUser/updateUserInfoByTenantId', {
328
- fullName: userState.value,
329
- tenantId: userState.tenantId,
330
- userId: props.userId,
331
- })
332
- .then(() => {
333
- Taro.showToast({ title: '用户名修改成功', icon: 'none' })
334
- getUserInfoByUserId()
335
- onUserNameCancel()
336
- emits('username-success')
337
- })
338
- }
339
-
340
- // 退出登录
341
- function toLogout() {
342
- Taro.showModal({
343
- title: '提示',
344
- content: '确定要退出登录吗?',
345
- confirmText: '确定',
346
- success: async (e: any) => {
347
- if (e.confirm) {
348
- emits('logout')
349
- }
350
- },
351
- })
352
- }
353
-
354
- // 去绑定手机号
355
- function toBinding() {
356
- emits('binding', userInfo.value.mobile || '')
357
- }
358
-
359
- // 父组件事件
360
- const emits = defineEmits(['avatar-success', 'logout', 'crop', 'binding', 'username-success'])
361
-
362
- // 外部访问
363
- defineExpose({
364
- updateImage,
365
- })
366
- </script>
367
-
368
- <style lang="scss">
369
- .user-info {
370
- height: 100vh;
371
-
372
- &-wrap {
373
- padding: 0 12px;
374
- padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
375
- box-sizing: border-box;
376
- min-height: 100%;
377
- }
378
- &-tit {
379
- height: 38px;
380
- display: flex;
381
- align-items: center;
382
- color: #666666;
383
- font-size: 12px;
384
- padding-left: 10px;
385
- }
386
- &-head {
387
- border-radius: 5px;
388
- background: #fff;
389
- padding: 30px 11px 0;
390
- &-avatar {
391
- position: relative;
392
- width: 80px;
393
- height: 80px;
394
- margin: 0 auto 25px;
395
- }
396
- &-img {
397
- width: 100%;
398
- height: 100%;
399
- overflow: hidden;
400
- border-radius: 50%;
401
- }
402
- &-upload {
403
- position: absolute;
404
- bottom: -2px;
405
- left: 52px;
406
- width: 29px;
407
- height: 29px;
408
- background: #333333;
409
- overflow: hidden;
410
- border-radius: 50%;
411
- display: flex;
412
- align-items: center;
413
- justify-content: center;
414
- &-icon {
415
- width: 17px;
416
- height: 17px;
417
- }
418
- }
419
- }
420
- &-team {
421
- &-item {
422
- border-radius: 5px;
423
- background: #fff;
424
- display: flex;
425
- padding: 15px;
426
- margin-bottom: 10px;
427
- &-avatar {
428
- width: 38px;
429
- height: 38px;
430
- margin-right: 15px;
431
- border-radius: 5px;
432
- background: rgba(1, 127, 255, 0.3);
433
- display: flex;
434
- align-items: center;
435
- justify-content: center;
436
- &-img {
437
- width: 100%;
438
- height: 100%;
439
- }
440
- .empty {
441
- width: 20px;
442
- height: 40px;
443
- }
444
- }
445
- &-title {
446
- font-size: 16px;
447
- font-weight: 500;
448
- margin-bottom: 5px;
449
- }
450
- &-app {
451
- display: flex;
452
- align-items: center;
453
- flex-wrap: wrap;
454
- &-tag {
455
- border: 1px solid rgba(53, 53, 53, 0.2);
456
- font-size: 10px;
457
- height: 18px;
458
- display: inline-flex;
459
- align-items: center;
460
- justify-content: center;
461
- padding: 0 6px;
462
- border-radius: 2px;
463
- margin: 0 10px 6px 0;
464
- }
465
- }
466
- &-bd {
467
- flex: 1;
468
- }
469
- &-role {
470
- padding: 10px;
471
- background: rgba(245, 245, 245, 0.5);
472
- border-radius: 5px;
473
- margin-bottom: 10px;
474
- &-btn {
475
- color: var(--app-primary-color, #017fff);
476
- font-size: 10px;
477
- display: inline-flex;
478
- align-items: center;
479
- margin-bottom: 6px;
480
- &-icon {
481
- width: 12px;
482
- height: 12px;
483
- position: relative;
484
- top: 1px;
485
- &.showRole {
486
- transform: rotate(180deg);
487
- }
488
- }
489
- }
490
- &-item {
491
- display: flex;
492
- font-size: 10px;
493
- margin-bottom: 10px;
494
- &:last-child {
495
- margin-bottom: 0;
496
- }
497
- &-name {
498
- opacity: 0.5;
499
- white-space: nowrap;
500
- margin-right: 10px;
501
- min-width: 40px;
502
- }
503
- &-info {
504
- flex: 1;
505
- color: #1a1a1a;
506
- }
507
- }
508
- }
509
- &-user {
510
- margin-bottom: 4px;
511
- font-size: 12px;
512
- display: flex;
513
- align-items: center;
514
- &-icon {
515
- width: 10px;
516
- height: 10px;
517
- margin-left: 4px;
518
- }
519
- }
520
- &-dept {
521
- display: flex;
522
- flex-wrap: wrap;
523
- font-size: 10px;
524
- color: rgba(26, 26, 26, 0.8);
525
- &-item {
526
- font-size: 10px;
527
- color: rgba(26, 26, 26, 0.5);
528
- margin: 4px 10px 4px 0;
529
- &:first-child {
530
- color: rgba(26, 26, 26, 0.8);
531
- }
532
- }
533
- }
534
- }
535
- }
536
-
537
- &-ft {
538
- &-btn {
539
- width: 100%;
540
- border-color: transparent !important;
541
- color: rgba(27, 63, 107, 0.8) !important;
542
- }
543
- }
544
-
545
- .nut-cell {
546
- padding: 11px 0;
547
- margin: 0;
548
- box-shadow: none;
549
- border-bottom: 1px solid #f0f0f0;
550
- font-size: 16px;
551
- .nut-cell__value {
552
- font-size: 16px;
553
- color: #000;
554
- }
555
- .nut-cell__link {
556
- color: #ccc;
557
- margin-left: 8px;
558
- }
559
- }
560
- }
561
- .upload-avatar-popup {
562
- &-box {
563
- display: flex;
564
- flex-direction: column;
565
- align-items: center;
566
- justify-content: center;
567
- }
568
- &-avatar {
569
- width: 320px;
570
- height: 320px;
571
- overflow: hidden;
572
- border-radius: 50%;
573
- margin-bottom: 50px;
574
- }
575
- &-btn {
576
- width: 106px;
577
- height: 37px;
578
- border-radius: 50px;
579
- border: 1px solid #ffffff;
580
- display: flex;
581
- justify-content: center;
582
- align-items: center;
583
- color: #ffffff;
584
- font-size: 16px;
585
- }
586
- }
587
- .change-username-popup {
588
- .nut-dialog {
589
- min-height: auto;
590
- }
591
- .nut-input {
592
- height: 40px;
593
- padding: 0;
594
- display: flex;
595
- align-items: center;
596
- font-size: 16px;
597
- border: none;
598
- .input-text {
599
- width: 100%;
600
- height: 100%;
601
- font-size: 14px;
602
- }
603
- .nut-input-value,
604
- .nut-input-inner,
605
- .nut-input-box {
606
- height: 100%;
607
- overflow: hidden;
608
- background: #f5f5f5;
609
- border-radius: 6px;
610
- }
611
- .nut-placeholder {
612
- color: #cccccc;
613
- line-height: 38px;
614
- height: 38px;
615
- }
616
- .nut-input-box {
617
- padding: 0 15px;
618
- }
619
- }
620
- &-cancel.nut-button {
621
- border-radius: 15px;
622
- font-size: 14px;
623
- height: 30px;
624
- }
625
- &-ok.nut-button {
626
- background: var(--app-primary-color, #017fff);
627
- height: 30px;
628
- font-size: 14px;
629
- border-radius: 15px;
630
- }
631
- }
632
- </style>
1
+ <template>
2
+ <scroll-view :scroll-y="!userState.visible && !avatarVisible" class="user-info">
3
+ <DdSkeleton v-if="firstLoading" :row="3"></DdSkeleton>
4
+ <div v-else class="user-info-wrap">
5
+ <div class="user-info-tit">账号信息</div>
6
+ <div class="user-info-head">
7
+ <div class="user-info-head-avatar" @click="avatarVisible = true">
8
+ <img
9
+ class="user-info-head-img"
10
+ mode="aspectFit"
11
+ v-if="userInfo.avatar"
12
+ :src="userInfo.avatar"
13
+ alt=""
14
+ />
15
+ <img
16
+ class="user-info-head-img"
17
+ mode="aspectFit"
18
+ v-else
19
+ src="https://cdn.ddjf.com/static/images/wx-yunservice/account-head.png"
20
+ alt=""
21
+ />
22
+ <div class="user-info-head-upload">
23
+ <img
24
+ class="user-info-head-upload-icon"
25
+ mode="aspectFit"
26
+ src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzQiIGhlaWdodD0iMzQiIHZpZXdCb3g9IjAgMCAzNCAzNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yMi4wOTk5IDE4LjQyMjRDMjIuMDk5OSAxNS41ODMyIDE5LjgxNjYgMTMuMjgxNiAxNi45OTk5IDEzLjI4MTZDMTQuMTgzMyAxMy4yODE2IDExLjg5OTkgMTUuNTgzMiAxMS44OTk5IDE4LjQyMjRDMTEuODk5OSAyMS4yNjE2IDE0LjE4MzMgMjMuNTYzMiAxNi45OTk5IDIzLjU2MzJDMTkuODE2NiAyMy41NjMyIDIyLjA5OTkgMjEuMjYxNiAyMi4wOTk5IDE4LjQyMjRWMTguNDIyNFoiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iMi41NSIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIvPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIzLjc5OTkgNS45OTg4QzIzLjc5OTkgNi4yMzUzOSAyMy45OTAyIDYuNDI3MiAyNC4yMjQ5IDYuNDI3MkgyNS45MjVDMjkuNDQ1OCA2LjQyNzIgMzIuMyA5LjMwNDIxIDMyLjMgMTIuODUzMlYyMy45OTE2QzMyLjMgMjcuNTQwNiAyOS40NDU4IDMwLjQxNzYgMjUuOTI1IDMwLjQxNzZIOC4wNzQ5NEM0LjU1NDE0IDMwLjQxNzYgMS42OTk5NSAyNy41NDA2IDEuNjk5OTUgMjMuOTkxNlYxMi44NTMyQzEuNjk5OTUgOS4zMDQyMSA0LjU1NDE0IDYuNDI3MiA4LjA3NDk0IDYuNDI3Mkg5Ljc3NDk1QzEwLjAwOTcgNi40MjcyIDEwLjIgNi4yMzUzOSAxMC4yIDUuOTk4OEMxMC4yIDUuNzA5NDkgMTAuMjQwNiA1LjQyOTc1IDEwLjMxNjUgNS4xNjUwNkMxMC42NzQ4IDMuOTE0NTEgMTEuODE4OSAzIDEzLjE3NSAzSDIwLjgyNUMyMi40NjggMyAyMy43OTk5IDQuMzQyNjEgMjMuNzk5OSA1Ljk5ODhWNS45OTg4WiIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIyLjU1IiBzdHJva2UtbGluZWNhcD0ic3F1YXJlIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNy42NDk5IDEwLjI4MjhDOC44MjM1MSAxMC4yODI4IDkuNzc0OSAxMS4yNDE4IDkuNzc0OSAxMi40MjQ4QzkuNzc0OSAxMy42MDc4IDguODIzNTEgMTQuNTY2OCA3LjY0OTkgMTQuNTY2OEM2LjQ3NjMgMTQuNTY2OCA1LjUyNDkgMTMuNjA3OCA1LjUyNDkgMTIuNDI0OEM1LjUyNDkgMTEuMjQxOCA2LjQ3NjMgMTAuMjgyOCA3LjY0OTkgMTAuMjgyOFoiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo="
27
+ alt=""
28
+ />
29
+ </div>
30
+ </div>
31
+ <nut-cell
32
+ title="登录手机号"
33
+ is-link
34
+ :desc="encodePhone(userInfo.mobile || '')"
35
+ @click="toBinding"
36
+ />
37
+ </div>
38
+
39
+ <div class="user-info-tit">企业/团队</div>
40
+ <div class="user-info-team">
41
+ <div v-for="(item, key) in userInfo.tenantInfoList" :key="key" class="user-info-team-item">
42
+ <div class="user-info-team-item-avatar">
43
+ <img
44
+ v-if="item.tenantLogo"
45
+ class="user-info-team-item-avatar-img"
46
+ mode="aspectFit"
47
+ :src="item.tenantLogo"
48
+ alt=""
49
+ />
50
+ <img
51
+ v-else
52
+ class="user-info-team-item-avatar-img empty"
53
+ mode="aspectFit"
54
+ src="https://cdn.ddjf.com/static/images/customer-center/tenant-logo.png"
55
+ alt=""
56
+ />
57
+ </div>
58
+ <div class="user-info-team-item-bd">
59
+ <div class="user-info-team-item-title">{{ item.tenantName }}</div>
60
+ <div class="user-info-team-item-app" v-if="item.appRoleInfo">
61
+ <div
62
+ class="user-info-team-item-app-tag"
63
+ v-for="(aitem, akey) in item.appRoleInfo || []"
64
+ :key="akey"
65
+ >
66
+ {{ aitem.appAbbr }}
67
+ </div>
68
+ <div class="user-info-team-item-role-btn" @click="toShowRole(item)">
69
+ 角色详情
70
+ <img
71
+ :class="{ showRole: item.showRole }"
72
+ class="user-info-team-item-role-btn-icon"
73
+ src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE4IDlMMTIgMTVMNiA5IiBzdHJva2U9IiMwMTdGRkYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+Cjwvc3ZnPgo="
74
+ alt=""
75
+ />
76
+ </div>
77
+ </div>
78
+ <div class="user-info-team-item-role" v-if="item.showRole">
79
+ <div
80
+ class="user-info-team-item-role-item"
81
+ v-for="(aitem, akey) in item.appRoleInfo || []"
82
+ :key="akey"
83
+ >
84
+ <div class="user-info-team-item-role-item-name">{{ aitem.appAbbr }}</div>
85
+ <div class="user-info-team-item-role-item-info">
86
+ {{ aitem.roleName }}
87
+ </div>
88
+ </div>
89
+ </div>
90
+ <div class="user-info-team-item-user">
91
+ {{ item.fullName }}
92
+ <img
93
+ @click="toUserNameChange(item)"
94
+ class="user-info-team-item-user-icon"
95
+ src="https://cdn.ddjf.com/static/images/appkit/edit.png"
96
+ alt=""
97
+ />
98
+ </div>
99
+ <div class="user-info-team-item-dept">
100
+ <div
101
+ v-for="(ditem, dkey) in item.deptNames"
102
+ :key="dkey"
103
+ class="user-info-team-item-dept-item"
104
+ >
105
+ {{ ditem }}
106
+ </div>
107
+ </div>
108
+ </div>
109
+ </div>
110
+ </div>
111
+
112
+ <div class="user-info-ft">
113
+ <nut-button class="user-info-ft-btn" @click="toLogout" plain type="primary"
114
+ >退出登录</nut-button
115
+ >
116
+ </div>
117
+ </div>
118
+ </scroll-view>
119
+
120
+ <!-- 修改用户名弹框 -->
121
+ <nut-dialog
122
+ title="输入新的用户名"
123
+ :border="false"
124
+ pop-class="change-username-popup"
125
+ v-model:visible="userState.visible"
126
+ @cancel="onUserNameCancel"
127
+ >
128
+ <nut-input :max-length="20" placeholder="请输入新的用户名" v-model="userState.value" />
129
+ <template #footer>
130
+ <nut-button class="change-username-popup-cancel" type="default" @click="onUserNameCancel">
131
+ 取消
132
+ </nut-button>
133
+ <nut-button class="change-username-popup-ok" type="primary" @click="onUserNameOk">
134
+ 确定
135
+ </nut-button>
136
+ </template>
137
+ </nut-dialog>
138
+
139
+ <!-- 修改头像弹框 -->
140
+ <nut-popup
141
+ pop-class="upload-avatar-popup"
142
+ style="background: transparent"
143
+ v-model:visible="avatarVisible"
144
+ :overlay-style="{ background: 'rgba(0, 0, 0, 0.9)' }"
145
+ >
146
+ <div class="upload-avatar-popup-box">
147
+ <img
148
+ class="upload-avatar-popup-avatar"
149
+ mode="aspectFit"
150
+ v-if="userInfo.avatar"
151
+ :src="userInfo.avatar"
152
+ alt=""
153
+ />
154
+ <img
155
+ class="upload-avatar-popup-avatar"
156
+ mode="aspectFit"
157
+ v-else
158
+ src="https://cdn.ddjf.com/static/images/wx-yunservice/account-head.png"
159
+ alt=""
160
+ />
161
+ <div class="upload-avatar-popup-btn" @click="toUpload">更换头像</div>
162
+ </div>
163
+ </nut-popup>
164
+ </template>
165
+
166
+ <script lang="ts" setup>
167
+ import Taro, { useDidShow } from '@tarojs/taro'
168
+ import { ref, onMounted, reactive, onUnmounted } from 'vue'
169
+ import { useAppKitOptions } from '../../Appkit'
170
+ import { useEncode } from '../../shared/composables/useEncode'
171
+ import DdSkeleton from '../../components/dd-skeleton/index.vue'
172
+ import { useHttp } from '../api'
173
+
174
+ const props = withDefaults(
175
+ defineProps<{
176
+ miniType?: string
177
+ app?: string
178
+ userId: string
179
+ }>(),
180
+ {
181
+ miniType: '05',
182
+ app: '',
183
+ userId: '',
184
+ }
185
+ )
186
+
187
+ const { encodePhone } = useEncode()
188
+
189
+ useDidShow(() => {
190
+ getUserInfoByUserId()
191
+ })
192
+ onMounted(() => {
193
+ Taro.eventCenter.on('USER-HEAD-CROP-OK', updateImage)
194
+ })
195
+ onUnmounted(() => {
196
+ Taro.eventCenter.off('USER-HEAD-CROP-OK')
197
+ })
198
+
199
+ const firstLoading = ref(true)
200
+ const userInfo = ref<any>({})
201
+ // 根据用户id,查询用户所在租户列表
202
+ function getUserInfoByUserId() {
203
+ const $http = useHttp()
204
+
205
+ $http
206
+ .get(`/cas/sysAccount/getAccountInfo/${props.userId}`)
207
+ .then((result: any) => {
208
+ userInfo.value = result
209
+ firstLoading.value = false
210
+ })
211
+ .catch(() => {
212
+ firstLoading.value = false
213
+ })
214
+ }
215
+
216
+ // 修改头像弹框
217
+ const avatarVisible = ref(false)
218
+
219
+ // 去上传头像
220
+ async function toUpload() {
221
+ if (!userInfo.value.avatar) {
222
+ const profile = await Taro.getUserProfile({
223
+ desc: '头像用于改变默认头像',
224
+ })
225
+
226
+ const res = await Taro.downloadFile({
227
+ url: profile.userInfo.avatarUrl,
228
+ })
229
+
230
+ updateImage(res.tempFilePath)
231
+ } else {
232
+ let res = await Taro.chooseImage({
233
+ count: 1,
234
+ })
235
+ if (res.tempFilePaths) {
236
+ const filePath = res.tempFilePaths[0]
237
+
238
+ emits('crop', filePath)
239
+ }
240
+ }
241
+ }
242
+
243
+ // 上传图片
244
+ async function updateImage(filePath: string) {
245
+ Taro.showLoading({
246
+ title: '上传中...',
247
+ })
248
+ const appkitOptions = useAppKitOptions()
249
+ const $http = useHttp()
250
+
251
+ let Res: any = await Taro.uploadFile({
252
+ url: `${appkitOptions.baseUrl()}/cas/file/uploadImg`,
253
+ filePath: filePath,
254
+ name: 'file',
255
+ formData: {
256
+ objectNo: `${userInfo.value.mobile}${Date.now()}`,
257
+ objectTypeCode: `MINI_HEADIMAGE${props.miniType}`,
258
+ },
259
+ header: {
260
+ token: appkitOptions.tempToken() || appkitOptions.token(),
261
+ },
262
+ })
263
+ avatarVisible.value = false
264
+
265
+ const res = JSON.parse(Res.data)
266
+ if (res.success) {
267
+ $http
268
+ .post('/cas/sysUser/update', {
269
+ appCode: props.app,
270
+ avatar: res.result,
271
+ userId: props.userId,
272
+ })
273
+ .then(() => {
274
+ Taro.hideLoading()
275
+ Taro.showToast({ title: '头像上传成功', icon: 'none' })
276
+ getUserInfoByUserId()
277
+ emits('avatar-success', res.result)
278
+ })
279
+ .catch(() => {
280
+ Taro.hideLoading()
281
+ })
282
+ } else {
283
+ Taro.hideLoading()
284
+ }
285
+ }
286
+
287
+ // 查看角色详情
288
+ function toShowRole(item: any) {
289
+ item.showRole = !item.showRole
290
+ }
291
+
292
+ // 更换用户名
293
+ const userState = reactive({
294
+ visible: false,
295
+ value: '',
296
+ oldName: '',
297
+ tenantId: '',
298
+ })
299
+ function toUserNameChange(item: any) {
300
+ userState.visible = true
301
+ userState.oldName = item.fullName
302
+ userState.tenantId = item.tenantId
303
+ }
304
+ function onUserNameCancel() {
305
+ userState.visible = false
306
+ userState.value = ''
307
+ userState.oldName = ''
308
+ userState.tenantId = ''
309
+ }
310
+ function onUserNameOk() {
311
+ if (!userState.value) {
312
+ return Taro.showToast({
313
+ title: '请输入用户名',
314
+ icon: 'none',
315
+ })
316
+ }
317
+ if (userState.value === userState.oldName) {
318
+ return Taro.showToast({
319
+ title: '用户名不能与原用户名相同',
320
+ icon: 'none',
321
+ })
322
+ }
323
+
324
+ const $http = useHttp()
325
+
326
+ $http
327
+ .post('/cas/sysUser/updateUserInfoByTenantId', {
328
+ fullName: userState.value,
329
+ tenantId: userState.tenantId,
330
+ userId: props.userId,
331
+ })
332
+ .then(() => {
333
+ Taro.showToast({ title: '用户名修改成功', icon: 'none' })
334
+ getUserInfoByUserId()
335
+ onUserNameCancel()
336
+ emits('username-success')
337
+ })
338
+ }
339
+
340
+ // 退出登录
341
+ function toLogout() {
342
+ Taro.showModal({
343
+ title: '提示',
344
+ content: '确定要退出登录吗?',
345
+ confirmText: '确定',
346
+ success: async (e: any) => {
347
+ if (e.confirm) {
348
+ emits('logout')
349
+ }
350
+ },
351
+ })
352
+ }
353
+
354
+ // 去绑定手机号
355
+ function toBinding() {
356
+ emits('binding', userInfo.value.mobile || '')
357
+ }
358
+
359
+ // 父组件事件
360
+ const emits = defineEmits(['avatar-success', 'logout', 'crop', 'binding', 'username-success'])
361
+
362
+ // 外部访问
363
+ defineExpose({
364
+ updateImage,
365
+ })
366
+ </script>
367
+
368
+ <style lang="scss">
369
+ .user-info {
370
+ height: 100vh;
371
+
372
+ &-wrap {
373
+ padding: 0 12px;
374
+ padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
375
+ box-sizing: border-box;
376
+ min-height: 100%;
377
+ }
378
+ &-tit {
379
+ height: 38px;
380
+ display: flex;
381
+ align-items: center;
382
+ color: #666666;
383
+ font-size: 12px;
384
+ padding-left: 10px;
385
+ }
386
+ &-head {
387
+ border-radius: 5px;
388
+ background: #fff;
389
+ padding: 30px 11px 0;
390
+ &-avatar {
391
+ position: relative;
392
+ width: 80px;
393
+ height: 80px;
394
+ margin: 0 auto 25px;
395
+ }
396
+ &-img {
397
+ width: 100%;
398
+ height: 100%;
399
+ overflow: hidden;
400
+ border-radius: 50%;
401
+ }
402
+ &-upload {
403
+ position: absolute;
404
+ bottom: -2px;
405
+ left: 52px;
406
+ width: 29px;
407
+ height: 29px;
408
+ background: #333333;
409
+ overflow: hidden;
410
+ border-radius: 50%;
411
+ display: flex;
412
+ align-items: center;
413
+ justify-content: center;
414
+ &-icon {
415
+ width: 17px;
416
+ height: 17px;
417
+ }
418
+ }
419
+ }
420
+ &-team {
421
+ &-item {
422
+ border-radius: 5px;
423
+ background: #fff;
424
+ display: flex;
425
+ padding: 15px;
426
+ margin-bottom: 10px;
427
+ &-avatar {
428
+ width: 38px;
429
+ height: 38px;
430
+ margin-right: 15px;
431
+ border-radius: 5px;
432
+ background: rgba(1, 127, 255, 0.3);
433
+ display: flex;
434
+ align-items: center;
435
+ justify-content: center;
436
+ &-img {
437
+ width: 100%;
438
+ height: 100%;
439
+ }
440
+ .empty {
441
+ width: 20px;
442
+ height: 40px;
443
+ }
444
+ }
445
+ &-title {
446
+ font-size: 16px;
447
+ font-weight: 500;
448
+ margin-bottom: 5px;
449
+ }
450
+ &-app {
451
+ display: flex;
452
+ align-items: center;
453
+ flex-wrap: wrap;
454
+ &-tag {
455
+ border: 1px solid rgba(53, 53, 53, 0.2);
456
+ font-size: 10px;
457
+ height: 18px;
458
+ display: inline-flex;
459
+ align-items: center;
460
+ justify-content: center;
461
+ padding: 0 6px;
462
+ border-radius: 2px;
463
+ margin: 0 10px 6px 0;
464
+ }
465
+ }
466
+ &-bd {
467
+ flex: 1;
468
+ }
469
+ &-role {
470
+ padding: 10px;
471
+ background: rgba(245, 245, 245, 0.5);
472
+ border-radius: 5px;
473
+ margin-bottom: 10px;
474
+ &-btn {
475
+ color: var(--app-primary-color, #017fff);
476
+ font-size: 10px;
477
+ display: inline-flex;
478
+ align-items: center;
479
+ margin-bottom: 6px;
480
+ &-icon {
481
+ width: 12px;
482
+ height: 12px;
483
+ position: relative;
484
+ top: 1px;
485
+ &.showRole {
486
+ transform: rotate(180deg);
487
+ }
488
+ }
489
+ }
490
+ &-item {
491
+ display: flex;
492
+ font-size: 10px;
493
+ margin-bottom: 10px;
494
+ &:last-child {
495
+ margin-bottom: 0;
496
+ }
497
+ &-name {
498
+ opacity: 0.5;
499
+ white-space: nowrap;
500
+ margin-right: 10px;
501
+ min-width: 40px;
502
+ }
503
+ &-info {
504
+ flex: 1;
505
+ color: #1a1a1a;
506
+ }
507
+ }
508
+ }
509
+ &-user {
510
+ margin-bottom: 4px;
511
+ font-size: 12px;
512
+ display: flex;
513
+ align-items: center;
514
+ &-icon {
515
+ width: 10px;
516
+ height: 10px;
517
+ margin-left: 4px;
518
+ }
519
+ }
520
+ &-dept {
521
+ display: flex;
522
+ flex-wrap: wrap;
523
+ font-size: 10px;
524
+ color: rgba(26, 26, 26, 0.8);
525
+ &-item {
526
+ font-size: 10px;
527
+ color: rgba(26, 26, 26, 0.5);
528
+ margin: 4px 10px 4px 0;
529
+ &:first-child {
530
+ color: rgba(26, 26, 26, 0.8);
531
+ }
532
+ }
533
+ }
534
+ }
535
+ }
536
+
537
+ &-ft {
538
+ &-btn {
539
+ width: 100%;
540
+ border-color: transparent !important;
541
+ color: rgba(27, 63, 107, 0.8) !important;
542
+ }
543
+ }
544
+
545
+ .nut-cell {
546
+ padding: 11px 0;
547
+ margin: 0;
548
+ box-shadow: none;
549
+ border-bottom: 1px solid #f0f0f0;
550
+ font-size: 16px;
551
+ .nut-cell__value {
552
+ font-size: 16px;
553
+ color: #000;
554
+ }
555
+ .nut-cell__link {
556
+ color: #ccc;
557
+ margin-left: 8px;
558
+ }
559
+ }
560
+ }
561
+ .upload-avatar-popup {
562
+ &-box {
563
+ display: flex;
564
+ flex-direction: column;
565
+ align-items: center;
566
+ justify-content: center;
567
+ }
568
+ &-avatar {
569
+ width: 320px;
570
+ height: 320px;
571
+ overflow: hidden;
572
+ border-radius: 50%;
573
+ margin-bottom: 50px;
574
+ }
575
+ &-btn {
576
+ width: 106px;
577
+ height: 37px;
578
+ border-radius: 50px;
579
+ border: 1px solid #ffffff;
580
+ display: flex;
581
+ justify-content: center;
582
+ align-items: center;
583
+ color: #ffffff;
584
+ font-size: 16px;
585
+ }
586
+ }
587
+ .change-username-popup {
588
+ .nut-dialog {
589
+ min-height: auto;
590
+ }
591
+ .nut-input {
592
+ height: 40px;
593
+ padding: 0;
594
+ display: flex;
595
+ align-items: center;
596
+ font-size: 16px;
597
+ border: none;
598
+ .input-text {
599
+ width: 100%;
600
+ height: 100%;
601
+ font-size: 14px;
602
+ }
603
+ .nut-input-value,
604
+ .nut-input-inner,
605
+ .nut-input-box {
606
+ height: 100%;
607
+ overflow: hidden;
608
+ background: #f5f5f5;
609
+ border-radius: 6px;
610
+ }
611
+ .nut-placeholder {
612
+ color: #cccccc;
613
+ line-height: 38px;
614
+ height: 38px;
615
+ }
616
+ .nut-input-box {
617
+ padding: 0 15px;
618
+ }
619
+ }
620
+ &-cancel.nut-button {
621
+ border-radius: 15px;
622
+ font-size: 14px;
623
+ height: 30px;
624
+ }
625
+ &-ok.nut-button {
626
+ background: var(--app-primary-color, #017fff);
627
+ height: 30px;
628
+ font-size: 14px;
629
+ border-radius: 15px;
630
+ }
631
+ }
632
+ </style>