-
+
GERP
企业级业务
统一管理平台
diff --git a/src/views/Profile.vue b/src/views/Profile.vue
index 125b23a..d282526 100644
--- a/src/views/Profile.vue
+++ b/src/views/Profile.vue
@@ -8,13 +8,118 @@
* - UserGender:-1=保密,1=男,0=女
* - UserAccountLicense:0=禁用,1=启用
* - UserPositionStatus:1=在职,0=停职
+ *
+ * 操作能力:修改头像(/Modify/ModifyELTUserAvatar)、修改名字(/API/User/ModifyPersonalConfig)、
+ * 修改密码(/API/User/ModifyPassword)。
*/
-import { computed } from 'vue'
+import { computed, ref } from 'vue'
+import { ElMessage } from 'element-plus'
import { useUserStore } from '@/stores/user'
-import { getAvatarUrl } from '@/api/auth'
+import { getAvatarUrl, uploadAvatar, modifyPersonalConfig, modifyPassword } from '@/api/auth'
const userStore = useUserStore()
-const avatarUrl = getAvatarUrl()
+
+/** 头像版本号:上传成功后 +1,附加到 URL 时间戳强制刷新浏览器缓存 */
+const avatarVersion = ref(0)
+const avatarUrl = computed(() => getAvatarUrl(avatarVersion.value))
+
+const avatarUploading = ref(false)
+const fileInput = ref
-
-
- 个人中心
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+ 保存
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+ 确认修改
+
+
@@ -94,15 +317,168 @@ const positionStatus = computed(() => {
box-sizing: border-box;
overflow: auto;
}
+
+.profile-card-header {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
.profile {
display: flex;
- gap: 32px;
+ gap: 24px;
align-items: flex-start;
}
-.avatar {
+
+/* 左侧头像卡片 */
+.profile-side {
+ width: 200px;
+ flex-shrink: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 20px 16px;
+ background: var(--el-fill-color-light);
+ border-radius: 12px;
+ text-align: center;
+}
+
+/* 头像可点击更换,hover 显示遮罩 */
+.avatar-wrap {
+ position: relative;
width: 120px;
height: 120px;
border-radius: 50%;
+ cursor: pointer;
+ overflow: hidden;
+ border: 3px solid var(--el-bg-color);
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+}
+
+.avatar {
+ width: 100%;
+ height: 100%;
+ border-radius: 50%;
object-fit: cover;
+ display: block;
+}
+
+.avatar-mask {
+ position: absolute;
+ inset: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 4px;
+ background: rgba(0, 0, 0, 0.5);
+ color: #fff;
+ font-size: 12px;
+ opacity: 0;
+ transition: opacity 0.2s;
+ border-radius: 50%;
+}
+
+.avatar-wrap:hover .avatar-mask,
+.avatar-wrap.uploading .avatar-mask {
+ opacity: 1;
+}
+
+.avatar-file-input {
+ display: none;
+}
+
+.profile-name {
+ margin-top: 14px;
+ font-size: 18px;
+ font-weight: 600;
+ color: var(--el-text-color-primary);
+ word-break: break-all;
+}
+
+.profile-role {
+ margin-top: 8px;
+}
+
+.profile-signature {
+ margin-top: 12px;
+ font-size: 12px;
+ color: var(--el-text-color-secondary);
+ line-height: 1.6;
+ word-break: break-all;
+}
+
+.profile-actions {
+ margin-top: 16px;
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ width: 100%;
+}
+
+/* 右侧信息区 */
+.profile-main {
+ flex: 1;
+ min-width: 0;
+}
+
+.profile-desc {
+ margin-bottom: 16px;
+
+ :deep(.el-descriptions__title) {
+ font-weight: 600;
+ }
+}
+
+.role-tag {
+ margin: 2px 6px 2px 0;
+}
+
+.uuid-text {
+ font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
+ font-size: 12px;
+ word-break: break-all;
+}
+
+/* 移动端:头像卡片与信息纵向堆叠 */
+@media (max-width: 768px) {
+ .profile {
+ flex-direction: column;
+ }
+ .profile-side {
+ width: 100%;
+ }
+ .profile-desc {
+ :deep(.el-descriptions__body) {
+ display: block;
+ }
+ :deep(.el-descriptions__table) {
+ width: 100%;
+ }
+ }
+}
+
+
+
+
diff --git a/src/views/app/AppConfigPage.vue b/src/views/app/AppConfigPage.vue
index 78e653c..78a72e7 100644
--- a/src/views/app/AppConfigPage.vue
+++ b/src/views/app/AppConfigPage.vue
@@ -12,7 +12,8 @@
import { ref, computed, watch, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
-import { appApi, type AppConfigItem, type CompanyScopeItem } from '@/api/app'
+import { appApi, type AppConfigItem, type CompanyScopeItem, type VirtualMappingItem, type PositionTemplateDiffItem, type PositionTemplateRemoveItem } from '@/api/app'
+import type { EntityPickerConfig } from '@/types/api'
import { setPageTitle } from '@/utils/serverScope'
const route = useRoute()
@@ -152,11 +153,228 @@ async function onCopy(): Promise
+ 个人中心
+ 管理员
+ 普通用户
+
+
-
-
-
- {{ userStore.userInfo?.UserName || '-' }}
- {{ email }}
- {{ userStore.userInfo?.UserTele || '-' }}
- {{ genderText }}
-
- {{ emailVerify.text }}
-
-
- {{ accountStatus.text }}
-
-
- {{ positionStatus.text }}
-
- {{ userStore.currentRole || '-' }}
-
- {{ userStore.isAdmin ? '是' : '否' }}
-
- {{ userStore.userInfo?.UserCreateTime || '-' }}
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ 更换头像
+
+ {{ displayName }}
+
+ {{ userStore.currentRole || '无当前角色' }}
+
+ {{ signature }}
+
+
+
+ 修改名字
+
+
+ 修改密码
+
+
+
+
+
+
+
+ {{ userStore.userInfo?.UserName || '-' }}
+ {{ userStore.userInfo?.DisplayName || '-' }}
+ {{ email }}
+ {{ userStore.userInfo?.UserTele || '-' }}
+ {{ genderText }}
+ {{ userStore.userInfo?.UserPersonalSignature || '-' }}
+
+
+
+
+
+ {{ emailVerify.text }}
+
+
+ {{ accountStatus.text }}
+
+
+ {{ positionStatus.text }}
+
+
+
+ {{ userStore.isAdmin ? '是' : '否' }}
+
+
+
+
+
+
+ {{ userStore.currentRole || '-' }}
+
+ {{ userStore.userInfo?.UserUUID || '-' }}
+
+ {{ userStore.userInfo?.UserCreateTime || '-' }}
+ {{ userStore.userInfo?.UserLastLoginDate || '-' }}
+
+
+ {{ r }}
+
+ -
+
+
+
+
+ 虚拟职务绑定
+ 把真实职务对应到应用虚拟职务(由应用清单声明可见菜单)· 绑定范围:{{ scopeLabel }}
+
+
+ 一键绑定
+
+
+ 保存绑定
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ vp.Name }}
+ {{ vp.Code }}
+
+
+
+
+ 通用部门与职务模板
+ 应用声明的通用部门与职务(按名称匹配,同名已有则直接复用)
+
+
+ 移除通用部门与职务
+
+
+ 同步通用部门与职务
+
+
+
+
+ 应用声明的通用部门与职务(按名称匹配,同名已有则直接复用)。点击"同步"补齐缺失项;点击"移除"仅删除所有员工均未持有的职务及已清空的通用部门。
+
+ 即将将下列的通用部门和职务加入到本租户,是否允许?
+ 将移除下列应用声明的通用部门与职务(仅删除所有员工均未持有的职务及已清空的部门):
+ {{ a.AppCode }}
{{ a.AppDesc || '暂无描述' }}
@@ -308,11 +353,36 @@ onMounted(loadMarket)
class="app-installed-tag"
>{{ n }}