@uxda/appkit 4.3.32 → 4.3.33

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