提交代码
This commit is contained in:
1 parent
1f9b52e4e4
commit
4a9c50891f
11 files changed
+1695
-221
No files matched your search
@@ -38,7 +38,7 @@ function handleUnauthorized(message = '登录已失效,请重新登录') {
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1];
|
||||
const currentPath = '/' + currentPage.route;
|
||||
|
||||
|
||||
// 如果是新生报名页面,不跳转到登录页,只是静默处理
|
||||
if (currentPath === '/pages/enrollment/index') {
|
||||
console.log('📋 新生报名页面401错误,使用兜底数据,不跳转登录页');
|
||||
@@ -395,6 +395,31 @@ export const api = {
|
||||
url: '/auth/logout',
|
||||
method: 'POST',
|
||||
}),
|
||||
|
||||
// 修改密码
|
||||
resetPassword: (data) =>
|
||||
request({
|
||||
url: '/system/user/profile/updatePwd',
|
||||
method: 'PUT',
|
||||
header: {
|
||||
isEncrypt: 'true', // 修复:使用字符串 'true' 而不是布尔值 true
|
||||
repeatSubmit: false,
|
||||
},
|
||||
data: {
|
||||
oldPassword: data.oldPassword,
|
||||
newPassword: data.newPassword,
|
||||
},
|
||||
}),
|
||||
|
||||
// 更新用户头像
|
||||
// updateUserAvatar: (data) =>
|
||||
// request({
|
||||
// url: '/system/user/profile/updateAvatar',
|
||||
// method: 'PUT',
|
||||
// data: {
|
||||
// avatar: data.avatar,
|
||||
// },
|
||||
// }),
|
||||
};
|
||||
|
||||
// 便捷请求方法封装
|
||||
|
||||
@@ -294,6 +294,14 @@
|
||||
"navigationBarBackgroundColor": "#1890ff",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/user/resetPasswd",
|
||||
"style": {
|
||||
"navigationBarTitleText": "修改密码",
|
||||
"navigationBarBackgroundColor": "#0051d9",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
|
||||
@@ -460,7 +460,7 @@
|
||||
</Card> -->
|
||||
|
||||
<!-- 系统管理 -->
|
||||
<!-- <Card v-if="hasSystemServices">
|
||||
<Card>
|
||||
<template #header>
|
||||
<view class="section-header">
|
||||
<u-icon name="setting" size="18" color="#f5222d" />
|
||||
@@ -468,7 +468,27 @@
|
||||
</view>
|
||||
</template>
|
||||
<GridLayout :columns="3" gap="16px">
|
||||
<ServiceItem
|
||||
<ServiceItem title="修改密码" @click="gotoResetPassword">
|
||||
<template #icon>
|
||||
<image
|
||||
src="/static/00118.png"
|
||||
mode="aspectFit"
|
||||
style="width: 24px; height: 24px"
|
||||
/>
|
||||
</template>
|
||||
</ServiceItem>
|
||||
|
||||
<!-- <ServiceItem title="修改头像" @click="gotoChangeAvatar">
|
||||
<template #icon>
|
||||
<image
|
||||
src="/static/password.png"
|
||||
mode="aspectFit"
|
||||
style="width: 24px; height: 24px"
|
||||
/>
|
||||
</template>
|
||||
</ServiceItem> -->
|
||||
|
||||
<!-- <ServiceItem
|
||||
v-if="hasPermi(['system:mobileuser:list'])"
|
||||
title="用户管理"
|
||||
@click="handleServiceClick"
|
||||
@@ -530,9 +550,9 @@
|
||||
<template #icon>
|
||||
<u-icon name="wifi" size="24" />
|
||||
</template>
|
||||
</ServiceItem>
|
||||
</ServiceItem> -->
|
||||
</GridLayout>
|
||||
</Card> -->
|
||||
</Card>
|
||||
|
||||
<!-- 工作流 -->
|
||||
<Card v-if="hasWorkflowServices">
|
||||
@@ -946,6 +966,20 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
// 跳转到修改密码页面
|
||||
gotoResetPassword() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/user/resetPasswd',
|
||||
});
|
||||
},
|
||||
|
||||
// 跳转到修改头像页面
|
||||
gotoChangeAvatar() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/user/changeaAvatar',
|
||||
});
|
||||
},
|
||||
|
||||
// 图片加载成功处理
|
||||
handleImageLoad(event) {
|
||||
console.log('✅ 轮播图片加载成功:', event.detail);
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,932 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<!-- 页面头部 -->
|
||||
<u-navbar :title="pageTitle" :border-bottom="false" bg-color="#3c9cff" title-color="#fff">
|
||||
<view slot="left" @click="goBack">
|
||||
<u-icon name="arrow-left" color="#fff" size="22"></u-icon>
|
||||
</view>
|
||||
</u-navbar>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<u-loading-page :loading="loading" loading-text="加载中..."></u-loading-page>
|
||||
|
||||
<!-- 主要内容 -->
|
||||
<view v-if="!loading" class="main-content">
|
||||
<view class="avatar-container">
|
||||
<!-- 当前头像预览 -->
|
||||
<view class="current-avatar-section">
|
||||
<text class="section-title">当前头像</text>
|
||||
<view class="avatar-preview">
|
||||
<image
|
||||
:src="currentAvatar"
|
||||
mode="aspectFill"
|
||||
class="avatar-image"
|
||||
@error="handleAvatarError"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 新头像预览区域 -->
|
||||
<view class="new-avatar-section">
|
||||
<text class="section-title">新头像预览</text>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<view v-if="avatarLoading || wechatImageLoading" class="avatar-loading">
|
||||
<u-loading-icon mode="circle" size="32"></u-loading-icon>
|
||||
<text class="loading-text">
|
||||
{{ wechatImageLoading ? '正在处理图片...' : '加载中...' }}
|
||||
</text>
|
||||
<text v-if="uploadProgress > 0" class="progress-text">
|
||||
上传进度: {{ uploadProgress }}%
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<!-- 已有新头像 - 点击可预览或重新选择 -->
|
||||
<view v-else-if="newAvatar" class="avatar-wrapper" @click="handleAvatarClick">
|
||||
<image
|
||||
:src="newAvatar"
|
||||
mode="aspectFill"
|
||||
class="avatar-image"
|
||||
@error="handleAvatarError"
|
||||
/>
|
||||
|
||||
<!-- 头像操作遮罩 -->
|
||||
<view class="avatar-overlay">
|
||||
<view class="overlay-content">
|
||||
<u-icon
|
||||
name="camera-fill"
|
||||
color="rgba(255,255,255,0.9)"
|
||||
size="24"
|
||||
></u-icon>
|
||||
<text class="overlay-text">点击更换头像</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 头像角标 -->
|
||||
<view class="avatar-badge">
|
||||
<u-icon name="checkmark-circle-fill" color="#52c41a" size="20"></u-icon>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 - 点击选择头像 -->
|
||||
<view v-else class="avatar-placeholder" @click="handlePhotoUpload">
|
||||
<text class="placeholder-text">选择新头像</text>
|
||||
<text class="placeholder-note">点击选择图片</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 快捷操作按钮 -->
|
||||
<view class="avatar-quick-actions">
|
||||
<view class="placeholder-tips">
|
||||
<text class="tip-item">
|
||||
• 建议尺寸:200x200像素 • 支持格式:JPG、PNG • 文件大小:不超过10MB
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view v-if="newAvatar" class="submit-section">
|
||||
<button
|
||||
class="submit-btn"
|
||||
:class="{ 'btn-loading': isSubmitting }"
|
||||
:disabled="isSubmitting"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
<u-icon v-if="isSubmitting" name="loading" size="16" color="#ffffff" />
|
||||
<text class="btn-text">{{ isSubmitting ? '上传中...' : '确认修改' }}</text>
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- 微信环境提示 -->
|
||||
<view v-if="!isWechatBrowser" class="wechat-tip">
|
||||
<u-icon name="info-circle" size="16" color="#fa8c16" />
|
||||
<text class="tip-text">建议在微信中使用以获得最佳体验</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { api, request } from '@/common/request';
|
||||
import { userManager } from '@/utils/user';
|
||||
import { REQUEST_CONFIG } from '@/common/config';
|
||||
import weChatSDK from '@/utils/wechat.js';
|
||||
|
||||
export default {
|
||||
name: 'ChangeAvatar',
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
avatarLoading: false,
|
||||
currentAvatar: '',
|
||||
newAvatar: '',
|
||||
isSubmitting: false,
|
||||
pageTitle: '修改头像',
|
||||
|
||||
// 微信SDK相关
|
||||
wechatSDK: weChatSDK,
|
||||
isWechatBrowser: false,
|
||||
wechatInitializing: false,
|
||||
wechatImageLoading: false,
|
||||
uploadProgress: 0,
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
this.loadCurrentAvatar();
|
||||
this.checkWechatEnvironment();
|
||||
},
|
||||
methods: {
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
||||
// 加载当前头像
|
||||
loadCurrentAvatar() {
|
||||
const userInfo = userManager.getCurrentUser();
|
||||
this.currentAvatar = userInfo?.avatar || '/static/111.png';
|
||||
},
|
||||
|
||||
// 检查微信环境并自动初始化SDK
|
||||
async checkWechatEnvironment() {
|
||||
this.isWechatBrowser = this.wechatSDK.isWeChatBrowser();
|
||||
|
||||
if (this.isWechatBrowser) {
|
||||
console.log('检测到微信环境,自动初始化微信SDK...');
|
||||
await this.initWechatSDK();
|
||||
} else {
|
||||
console.log('非微信环境,使用标准图片选择功能');
|
||||
}
|
||||
},
|
||||
|
||||
// 初始化微信SDK
|
||||
async initWechatSDK() {
|
||||
if (this.wechatInitializing) return;
|
||||
|
||||
this.wechatInitializing = true;
|
||||
console.log('开始初始化微信SDK...');
|
||||
|
||||
try {
|
||||
// 检查微信环境
|
||||
if (!this.isWechatBrowser) {
|
||||
throw new Error('当前不在微信浏览器环境中');
|
||||
}
|
||||
|
||||
// 使用微信SDK工具类初始化
|
||||
const configData = await this.wechatSDK.init({
|
||||
debug: false,
|
||||
});
|
||||
|
||||
console.log('✅ 微信SDK初始化成功!', configData);
|
||||
|
||||
// 验证图片相关API可用性
|
||||
try {
|
||||
const checkResult = await this.wechatSDK.checkJsApi([
|
||||
'chooseImage',
|
||||
'previewImage',
|
||||
'uploadImage',
|
||||
'downloadImage',
|
||||
]);
|
||||
console.log('图片API可用性检查完成:', checkResult);
|
||||
} catch (checkError) {
|
||||
console.warn('API可用性检查失败:', checkError.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('微信SDK初始化失败:', error);
|
||||
uni.showToast({
|
||||
title: '微信SDK初始化失败',
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
});
|
||||
} finally {
|
||||
this.wechatInitializing = false;
|
||||
}
|
||||
},
|
||||
|
||||
// === 头像处理相关方法 ===
|
||||
|
||||
// 头像上传处理(主要入口)
|
||||
handlePhotoUpload() {
|
||||
if (this.isWechatBrowser) {
|
||||
if (this.wechatSDK.isInitialized) {
|
||||
this.chooseWechatImage();
|
||||
} else {
|
||||
this.showWechatInitDialog();
|
||||
}
|
||||
} else {
|
||||
this.chooseImage();
|
||||
}
|
||||
},
|
||||
|
||||
// 头像点击处理(已有新头像时)
|
||||
handleAvatarClick() {
|
||||
uni.showActionSheet({
|
||||
itemList: ['预览头像', '更换头像', '删除头像'],
|
||||
success: (res) => {
|
||||
switch (res.tapIndex) {
|
||||
case 0:
|
||||
this.handleAvatarPreview();
|
||||
break;
|
||||
case 1:
|
||||
this.handleAvatarReselect();
|
||||
break;
|
||||
case 2:
|
||||
this.handleAvatarDelete();
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 预览头像
|
||||
handleAvatarPreview() {
|
||||
if (this.newAvatar) {
|
||||
uni.previewImage({
|
||||
urls: [this.newAvatar],
|
||||
current: this.newAvatar,
|
||||
success: () => {
|
||||
console.log('头像预览打开成功');
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error('预览头像失败:', error);
|
||||
uni.showToast({
|
||||
title: '预览失败',
|
||||
icon: 'none',
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 重新选择头像
|
||||
handleAvatarReselect() {
|
||||
uni.showModal({
|
||||
title: '确认操作',
|
||||
content: '确定要重新选择头像吗?当前头像将被替换。',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.handlePhotoUpload();
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 删除头像
|
||||
handleAvatarDelete() {
|
||||
uni.showModal({
|
||||
title: '确认删除',
|
||||
content: '确定要删除当前头像吗?删除后无法恢复。',
|
||||
confirmColor: '#ff5722',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.clearAvatarData();
|
||||
uni.showToast({
|
||||
title: '头像已删除',
|
||||
icon: 'success',
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 清空头像数据
|
||||
clearAvatarData() {
|
||||
this.newAvatar = '';
|
||||
this.uploadProgress = 0;
|
||||
},
|
||||
|
||||
// 显示微信初始化对话框
|
||||
showWechatInitDialog() {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '微信SDK未初始化,是否立即初始化?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.initWechatSDK();
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 显示非微信环境提示
|
||||
showNonWechatTip() {
|
||||
uni.showModal({
|
||||
title: '环境提示',
|
||||
content:
|
||||
'建议在微信中使用此功能以获得最佳体验。\n\n在微信中打开此页面可以:\n• 直接选择相册图片\n• 拍照上传\n• 图片预览和编辑',
|
||||
showCancel: false,
|
||||
confirmText: '我知道了',
|
||||
});
|
||||
},
|
||||
|
||||
// 选择微信图片
|
||||
async chooseWechatImage() {
|
||||
if (!this.wechatSDK.isInitialized) {
|
||||
console.log('请先初始化微信SDK');
|
||||
await this.initWechatSDK();
|
||||
return;
|
||||
}
|
||||
|
||||
this.wechatImageLoading = true;
|
||||
this.uploadProgress = 0;
|
||||
console.log('正在打开微信图片选择器...');
|
||||
|
||||
try {
|
||||
const res = await this.wechatSDK.chooseImage({
|
||||
count: 1, // 头像只选择一张
|
||||
sizeType: ['original', 'compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
});
|
||||
|
||||
console.log('✅ 微信图片选择成功,共', res.localIds.length, '张');
|
||||
|
||||
// 将选择的图片设置为头像预览
|
||||
if (res.localIds.length > 0) {
|
||||
this.newAvatar = res.localIds[0];
|
||||
console.log('📷 已设置头像预览');
|
||||
|
||||
// 显示上传提示
|
||||
uni.showToast({
|
||||
title: '正在上传头像...',
|
||||
icon: 'loading',
|
||||
duration: 2000,
|
||||
});
|
||||
|
||||
// 自动上传图片到微信服务器并保存到OSS
|
||||
await this.uploadWechatImageToOSS(res.localIds[0]);
|
||||
|
||||
// 上传成功提示
|
||||
uni.showToast({
|
||||
title: '头像上传成功!',
|
||||
icon: 'success',
|
||||
duration: 1500,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('选择微信图片失败:', error);
|
||||
|
||||
// 显示错误提示
|
||||
uni.showModal({
|
||||
title: '选择图片失败',
|
||||
content: error.message || '请检查微信环境或网络连接',
|
||||
showCancel: false,
|
||||
confirmText: '我知道了',
|
||||
});
|
||||
|
||||
// 重置头像预览
|
||||
this.newAvatar = '';
|
||||
} finally {
|
||||
this.wechatImageLoading = false;
|
||||
this.uploadProgress = 0;
|
||||
}
|
||||
},
|
||||
|
||||
// 上传微信图片到OSS
|
||||
async uploadWechatImageToOSS(localId) {
|
||||
try {
|
||||
console.log('📤 开始上传微信图片,localId:', localId);
|
||||
|
||||
// 步骤1:上传到微信服务器(20%进度)
|
||||
this.uploadProgress = 10;
|
||||
console.log('📤 正在上传到微信服务器...');
|
||||
|
||||
const wxUploadRes = await new Promise((resolve, reject) => {
|
||||
wx.uploadImage({
|
||||
localId: localId,
|
||||
isShowProgressTips: 0, // 关闭微信自带的进度提示
|
||||
success: resolve,
|
||||
fail: reject,
|
||||
});
|
||||
});
|
||||
|
||||
const mediaId = wxUploadRes.serverId;
|
||||
this.uploadProgress = 30;
|
||||
console.log('✅ 微信服务器上传成功,mediaId:', mediaId);
|
||||
|
||||
// 步骤2:保存到OSS(80%进度)
|
||||
this.uploadProgress = 50;
|
||||
console.log('💾 正在保存到云端存储...');
|
||||
|
||||
const ossResponse = await request({
|
||||
url: '/system/wechat/downloadToOss',
|
||||
method: 'GET',
|
||||
params: {
|
||||
mediaId: mediaId,
|
||||
},
|
||||
timeout: 30000, // 30秒超时
|
||||
});
|
||||
|
||||
if (ossResponse.code === 200) {
|
||||
const ossResult = ossResponse.data;
|
||||
this.uploadProgress = 90;
|
||||
|
||||
console.log('🎉 头像保存成功!', ossResult);
|
||||
|
||||
// 更新新头像URL
|
||||
this.newAvatar = ossResult.url;
|
||||
|
||||
// 上传进度完成
|
||||
this.uploadProgress = 100;
|
||||
|
||||
return ossResult;
|
||||
} else {
|
||||
throw new Error(ossResponse.msg || '保存头像到云端存储失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('上传微信图片失败:', error);
|
||||
|
||||
// 上传失败时重置进度
|
||||
this.uploadProgress = 0;
|
||||
|
||||
// 显示详细错误信息
|
||||
let errorMsg = '头像上传失败,请重试';
|
||||
if (error.message.includes('timeout')) {
|
||||
errorMsg = '上传超时,请检查网络连接后重试';
|
||||
} else if (error.message.includes('mediaId')) {
|
||||
errorMsg = '微信服务器上传失败,请重试';
|
||||
} else if (error.message.includes('OSS')) {
|
||||
errorMsg = '保存到云端存储失败,请重试';
|
||||
}
|
||||
|
||||
uni.showToast({
|
||||
title: errorMsg,
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
});
|
||||
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
// 选择图片(非微信环境)
|
||||
chooseImage() {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ['compressed'],
|
||||
sourceType: ['album'],
|
||||
success: (res) => {
|
||||
this.handleImageSelected(res.tempFilePaths[0]);
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error('选择图片失败:', error);
|
||||
uni.showToast({
|
||||
title: '选择图片失败',
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 拍照
|
||||
takePhoto() {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ['compressed'],
|
||||
sourceType: ['camera'],
|
||||
success: (res) => {
|
||||
this.handleImageSelected(res.tempFilePaths[0]);
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error('拍照失败:', error);
|
||||
uni.showToast({
|
||||
title: '拍照失败',
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 处理选中的图片
|
||||
handleImageSelected(filePath) {
|
||||
// 检查文件大小
|
||||
uni.getFileInfo({
|
||||
filePath: filePath,
|
||||
success: (res) => {
|
||||
const fileSizeInMB = res.size / (1024 * 1024);
|
||||
if (fileSizeInMB > 10) {
|
||||
uni.showToast({
|
||||
title: '图片大小不能超过10MB',
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 压缩图片
|
||||
this.compressImage(filePath);
|
||||
},
|
||||
fail: (error) => {
|
||||
console.error('获取文件信息失败:', error);
|
||||
// 直接使用原图
|
||||
this.newAvatar = filePath;
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 压缩图片
|
||||
compressImage(filePath) {
|
||||
// 检查是否支持压缩图片API
|
||||
if (typeof uni.compressImage === 'function' && uni.compressImage) {
|
||||
try {
|
||||
uni.compressImage({
|
||||
src: filePath,
|
||||
quality: 80,
|
||||
success: (res) => {
|
||||
console.log('图片压缩成功:', res.tempFilePath);
|
||||
this.newAvatar = res.tempFilePath;
|
||||
},
|
||||
fail: (error) => {
|
||||
console.warn('压缩图片失败,使用原图:', error);
|
||||
// 使用原图
|
||||
this.newAvatar = filePath;
|
||||
},
|
||||
complete: () => {
|
||||
// 确保有值
|
||||
if (!this.newAvatar) {
|
||||
this.newAvatar = filePath;
|
||||
}
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn('compressImage API调用异常,使用原图:', error);
|
||||
this.newAvatar = filePath;
|
||||
}
|
||||
} else {
|
||||
console.log('当前环境不支持图片压缩API,使用原图');
|
||||
// 不支持压缩时直接使用原图
|
||||
this.newAvatar = filePath;
|
||||
}
|
||||
},
|
||||
|
||||
// 处理头像加载错误
|
||||
handleAvatarError() {
|
||||
this.currentAvatar = '/static/111.png';
|
||||
},
|
||||
|
||||
// 提交头像
|
||||
async handleSubmit() {
|
||||
if (!this.newAvatar) {
|
||||
uni.showToast({
|
||||
title: '请先选择头像',
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.isSubmitting = true;
|
||||
|
||||
try {
|
||||
let avatarUrl = this.newAvatar;
|
||||
|
||||
// 如果不是微信上传的图片,需要先上传到服务器
|
||||
if (!this.newAvatar.startsWith('http')) {
|
||||
const uploadResult = await this.uploadAvatar(this.newAvatar);
|
||||
avatarUrl = uploadResult.url;
|
||||
}
|
||||
|
||||
// 更新用户信息
|
||||
await api.updateUserAvatar({
|
||||
avatar: avatarUrl,
|
||||
});
|
||||
|
||||
// 更新本地用户信息
|
||||
userManager.updateUserInfo({
|
||||
avatar: avatarUrl,
|
||||
});
|
||||
|
||||
uni.showToast({
|
||||
title: '头像修改成功',
|
||||
icon: 'success',
|
||||
duration: 2000,
|
||||
});
|
||||
|
||||
// 延迟返回上一页
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 2000);
|
||||
} catch (error) {
|
||||
console.error('修改头像失败:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '修改头像失败',
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
});
|
||||
} finally {
|
||||
this.isSubmitting = false;
|
||||
}
|
||||
},
|
||||
|
||||
// 上传头像到服务器(非微信环境使用)
|
||||
uploadAvatar(filePath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const token = uni.getStorageSync('access_token');
|
||||
const clientid = uni.getStorageSync('clientid') || 'mobile';
|
||||
|
||||
// 构建完整URL
|
||||
let fullUrl;
|
||||
if (REQUEST_CONFIG.baseURL.startsWith('/')) {
|
||||
// 开发环境,baseURL是'/api',需要使用完整的服务器URL
|
||||
fullUrl = `http://localhost:8080${REQUEST_CONFIG.baseURL}/system/user/profile/avatar`;
|
||||
} else {
|
||||
// 生产环境,直接拼接
|
||||
fullUrl = REQUEST_CONFIG.baseURL + '/system/user/profile/avatar';
|
||||
}
|
||||
|
||||
uni.uploadFile({
|
||||
url: fullUrl,
|
||||
filePath: filePath,
|
||||
name: 'avatarfile',
|
||||
header: {
|
||||
authorization: token ? `Bearer ${token}` : '',
|
||||
clientid: clientid,
|
||||
},
|
||||
success: (res) => {
|
||||
try {
|
||||
const data = JSON.parse(res.data);
|
||||
if (data.code === 200) {
|
||||
resolve(data.data);
|
||||
} else {
|
||||
reject(new Error(data.msg || '上传失败'));
|
||||
}
|
||||
} catch (error) {
|
||||
reject(new Error('解析响应失败'));
|
||||
}
|
||||
},
|
||||
fail: (error) => {
|
||||
reject(new Error('上传失败'));
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f6fa;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
flex: 1;
|
||||
padding: 20rpx;
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.avatar-container {
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.current-avatar-section,
|
||||
.new-avatar-section {
|
||||
padding: 30rpx;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
margin-bottom: 20rpx;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.avatar-loading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
border: 2rpx dashed #d9d9d9;
|
||||
border-radius: 50%;
|
||||
background-color: #fafafa;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
font-size: 24rpx;
|
||||
margin-top: 16rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.progress-text {
|
||||
font-size: 20rpx;
|
||||
color: #1890ff;
|
||||
margin-top: 12rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.avatar-wrapper {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
|
||||
&:hover .avatar-overlay {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-image {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
border-radius: 50%;
|
||||
border: 3rpx solid #ffffff;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.avatar-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.overlay-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.overlay-text {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
font-size: 20rpx;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.avatar-badge {
|
||||
position: absolute;
|
||||
top: -6rpx;
|
||||
right: calc(50% - 100rpx + 6rpx);
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.avatar-placeholder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
border: 2rpx dashed #d9d9d9;
|
||||
border-radius: 50%;
|
||||
background-color: #fafafa;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.placeholder-text {
|
||||
font-size: 24rpx;
|
||||
color: #8c939d;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.placeholder-note {
|
||||
font-size: 20rpx;
|
||||
color: #c0c4cc;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.placeholder-tips {
|
||||
padding: 16rpx 20rpx;
|
||||
background: rgba(24, 144, 255, 0.05);
|
||||
border-radius: 8rpx;
|
||||
border: 1px solid rgba(24, 144, 255, 0.1);
|
||||
}
|
||||
|
||||
.tip-item {
|
||||
display: block;
|
||||
font-size: 20rpx;
|
||||
color: #666;
|
||||
margin-bottom: 6rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-quick-actions {
|
||||
padding: 20rpx 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.submit-section {
|
||||
padding: 30rpx;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
background: linear-gradient(135deg, #52c41a, #389e0d);
|
||||
border: none;
|
||||
border-radius: 12rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16rpx;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background: #cccccc;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
&.btn-loading {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.wechat-tip {
|
||||
margin: 20rpx 30rpx;
|
||||
padding: 16rpx 20rpx;
|
||||
background-color: #fffbe6;
|
||||
border: 1px solid #ffe58f;
|
||||
border-radius: 8rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
font-size: 28rpx;
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
font-size: 28rpx;
|
||||
color: #faad14;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 375px) {
|
||||
.main-content {
|
||||
padding: 16rpx 12rpx;
|
||||
}
|
||||
|
||||
.avatar-container {
|
||||
padding: 20rpx 16rpx;
|
||||
}
|
||||
|
||||
.avatar-image {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
}
|
||||
|
||||
.avatar-wrapper {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
}
|
||||
|
||||
.avatar-overlay {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
}
|
||||
|
||||
.avatar-placeholder {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,418 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<!-- 页面头部 -->
|
||||
<!-- <view class="page-header">
|
||||
<view class="header-content">
|
||||
<view class="back-btn" @click="goBack">
|
||||
<u-icon name="arrow-left" size="20" color="#ffffff" />
|
||||
</view>
|
||||
<text class="page-title">修改密码</text>
|
||||
<view class="placeholder"></view>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
<!-- 主要内容 -->
|
||||
<view class="main-content">
|
||||
<view class="form-container">
|
||||
<!-- 旧密码 -->
|
||||
<view class="form-item">
|
||||
<view class="input-label">
|
||||
<u-icon name="lock" size="16" color="#666666" />
|
||||
<text class="label-text">旧密码</text>
|
||||
</view>
|
||||
<view class="input-wrapper">
|
||||
<input
|
||||
v-model="formData.oldPassword"
|
||||
type="password"
|
||||
placeholder="请输入旧密码"
|
||||
class="input-field"
|
||||
:class="{ 'input-error': errors.oldPassword }"
|
||||
@blur="validateOldPassword"
|
||||
/>
|
||||
<view v-if="errors.oldPassword" class="error-message">
|
||||
{{ errors.oldPassword }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 新密码 -->
|
||||
<view class="form-item">
|
||||
<view class="input-label">
|
||||
<u-icon name="lock-open" size="16" color="#666666" />
|
||||
<text class="label-text">新密码</text>
|
||||
</view>
|
||||
<view class="input-wrapper">
|
||||
<input
|
||||
v-model="formData.newPassword"
|
||||
type="password"
|
||||
placeholder="请输入新密码"
|
||||
class="input-field"
|
||||
:class="{ 'input-error': errors.newPassword }"
|
||||
@blur="validateNewPassword"
|
||||
/>
|
||||
<view v-if="errors.newPassword" class="error-message">
|
||||
{{ errors.newPassword }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 确认新密码 -->
|
||||
<view class="form-item">
|
||||
<view class="input-label">
|
||||
<u-icon name="checkmark-circle" size="16" color="#666666" />
|
||||
<text class="label-text">确认新密码</text>
|
||||
</view>
|
||||
<view class="input-wrapper">
|
||||
<input
|
||||
v-model="formData.confirmPassword"
|
||||
type="password"
|
||||
placeholder="请再次输入新密码"
|
||||
class="input-field"
|
||||
:class="{ 'input-error': errors.confirmPassword }"
|
||||
@blur="validateConfirmPassword"
|
||||
/>
|
||||
<view v-if="errors.confirmPassword" class="error-message">
|
||||
{{ errors.confirmPassword }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-section">
|
||||
<button
|
||||
class="submit-btn"
|
||||
:class="{ 'btn-loading': isSubmitting }"
|
||||
:disabled="isSubmitting || !isFormValid"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
<u-icon v-if="isSubmitting" name="loading" size="16" color="#ffffff" />
|
||||
<text class="btn-text">{{ isSubmitting ? '提交中...' : '确认修改' }}</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { api } from '@/common/request';
|
||||
|
||||
export default {
|
||||
name: 'ResetPassword',
|
||||
data() {
|
||||
return {
|
||||
formData: {
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
},
|
||||
errors: {
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
},
|
||||
isSubmitting: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isFormValid() {
|
||||
return (
|
||||
this.formData.oldPassword.trim() !== '' &&
|
||||
this.formData.newPassword.trim() !== '' &&
|
||||
this.formData.confirmPassword.trim() !== '' &&
|
||||
!this.errors.oldPassword &&
|
||||
!this.errors.newPassword &&
|
||||
!this.errors.confirmPassword
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
||||
// 验证旧密码
|
||||
validateOldPassword() {
|
||||
if (!this.formData.oldPassword.trim()) {
|
||||
this.errors.oldPassword = '请输入旧密码';
|
||||
return false;
|
||||
}
|
||||
this.errors.oldPassword = '';
|
||||
return true;
|
||||
},
|
||||
|
||||
// 验证新密码
|
||||
validateNewPassword() {
|
||||
const password = this.formData.newPassword.trim();
|
||||
|
||||
if (!password) {
|
||||
this.errors.newPassword = '请输入新密码';
|
||||
return false;
|
||||
}
|
||||
|
||||
if (password.length < 6) {
|
||||
this.errors.newPassword = '密码长度不能少于6位';
|
||||
return false;
|
||||
}
|
||||
|
||||
if (password.length > 20) {
|
||||
this.errors.newPassword = '密码长度不能超过20位';
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查是否包含数字和字母
|
||||
const hasNumber = /\d/.test(password);
|
||||
const hasLetter = /[a-zA-Z]/.test(password);
|
||||
|
||||
if (!hasNumber || !hasLetter) {
|
||||
this.errors.newPassword = '密码必须包含数字和字母';
|
||||
return false;
|
||||
}
|
||||
|
||||
this.errors.newPassword = '';
|
||||
return true;
|
||||
},
|
||||
|
||||
// 验证确认密码
|
||||
validateConfirmPassword() {
|
||||
if (!this.formData.confirmPassword.trim()) {
|
||||
this.errors.confirmPassword = '请确认新密码';
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.formData.newPassword !== this.formData.confirmPassword) {
|
||||
this.errors.confirmPassword = '两次输入的密码不一致';
|
||||
return false;
|
||||
}
|
||||
|
||||
this.errors.confirmPassword = '';
|
||||
return true;
|
||||
},
|
||||
|
||||
// 提交表单
|
||||
async handleSubmit() {
|
||||
// 验证所有字段
|
||||
const isOldValid = this.validateOldPassword();
|
||||
const isNewValid = this.validateNewPassword();
|
||||
const isConfirmValid = this.validateConfirmPassword();
|
||||
|
||||
if (!isOldValid || !isNewValid || !isConfirmValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.isFormValid) {
|
||||
uni.showToast({
|
||||
title: '请完善表单信息',
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.isSubmitting = true;
|
||||
|
||||
try {
|
||||
// 调用修改密码API
|
||||
await api.resetPassword({
|
||||
oldPassword: this.formData.oldPassword,
|
||||
newPassword: this.formData.newPassword,
|
||||
});
|
||||
|
||||
uni.showToast({
|
||||
title: '密码修改成功',
|
||||
icon: 'success',
|
||||
duration: 2000,
|
||||
});
|
||||
|
||||
// 延迟返回上一页
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 2000);
|
||||
} catch (error) {
|
||||
console.error('修改密码失败:', error);
|
||||
uni.showToast({
|
||||
title: error.message || '修改密码失败',
|
||||
icon: 'none',
|
||||
duration: 2000,
|
||||
});
|
||||
} finally {
|
||||
this.isSubmitting = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page-container {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f5f5;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* 页面头部 */
|
||||
.page-header {
|
||||
background: linear-gradient(135deg, #007aff, #0051d9);
|
||||
padding: calc(var(--status-bar-height) + 12px) 16px 16px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.header-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
/* 主要内容 */
|
||||
.main-content {
|
||||
flex: 1;
|
||||
padding: 20px 16px;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
background-color: #ffffff;
|
||||
border-radius: 12px;
|
||||
padding: 24px 20px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.form-item {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.label-text {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.input-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
padding: 0 16px;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 8px;
|
||||
font-size: 16px;
|
||||
background-color: #ffffff;
|
||||
transition: all 0.3s ease;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:focus {
|
||||
border-color: #007aff;
|
||||
box-shadow: 0 0 0 2px rgba(0, 122, 255, 0.1);
|
||||
}
|
||||
|
||||
&.input-error {
|
||||
border-color: #ff4d4f;
|
||||
box-shadow: 0 0 0 2px rgba(255, 77, 79, 0.1);
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
.error-message {
|
||||
font-size: 14px;
|
||||
color: #ff4d4f;
|
||||
margin-top: 4px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.submit-section {
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
background: linear-gradient(135deg, #007aff, #0051d9);
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background: #cccccc;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
&.btn-loading {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 375px) {
|
||||
.main-content {
|
||||
padding: 16px 12px;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
padding: 20px 16px;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
height: 44px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
height: 44px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -78,9 +78,9 @@
|
||||
</view>
|
||||
|
||||
<!-- 快捷操作按钮 -->
|
||||
<view class="photo-quick-actions">
|
||||
<view class="photo-quick-actions">
|
||||
<view class="placeholder-tips">
|
||||
<text class="tip-item">• 建议尺寸:2寸证件照 • 支持格式:JPG、PNG • 文件大小:不超过10MB</text>
|
||||
<text class="tip-item">• 建议尺寸:2寸证件照 • 支持格式:JPG、PNG • 文件大小:不超过10MB</text>
|
||||
</view>
|
||||
<!-- <u-button
|
||||
size="small"
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="body_1" width="3182" height="3197">
|
||||
|
||||
<g transform="matrix(1.3333334 0 0 1.3333334 0 0)">
|
||||
<image x="0" y="0" xlink:href="data:image/png;base64,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 truncated
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.7 MiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
@@ -107,7 +107,7 @@ export const userManager = {
|
||||
|
||||
return {
|
||||
name: this.getDisplayName(),
|
||||
avatar: user.avatar || '/static/logo-2.png',
|
||||
avatar: user.avatar || '/static/logo.svg',
|
||||
deptName: user.deptName || '未设置部门',
|
||||
status: user.status,
|
||||
loginDate: user.loginDate,
|
||||
|
||||
Reference in new issue
Block a user