@uxda/appkit 4.2.0 → 4.2.2

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