@uxda/appkit 4.2.82 → 4.2.84

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