fix: 🐛 头像上传,文件上传问题
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
from rest_framework.decorators import action
|
||||||
|
from rest_framework.parsers import FileUploadParser
|
||||||
|
|
||||||
from dvadmin.system.models import FileList
|
from dvadmin.system.models import FileList
|
||||||
|
from dvadmin.utils.json_response import SuccessResponse
|
||||||
from dvadmin.utils.serializers import CustomModelSerializer
|
from dvadmin.utils.serializers import CustomModelSerializer
|
||||||
from dvadmin.utils.viewset import CustomModelViewSet
|
from dvadmin.utils.viewset import CustomModelViewSet
|
||||||
|
|
||||||
@@ -16,6 +19,7 @@ class FileSerializer(CustomModelSerializer):
|
|||||||
fields = "__all__"
|
fields = "__all__"
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
|
print(self.context['request'])
|
||||||
validated_data['name'] = str(self.initial_data.get('file'))
|
validated_data['name'] = str(self.initial_data.get('file'))
|
||||||
validated_data['url'] = self.initial_data.get('file')
|
validated_data['url'] = self.initial_data.get('file')
|
||||||
return super().create(validated_data)
|
return super().create(validated_data)
|
||||||
@@ -34,3 +38,8 @@ class FileViewSet(CustomModelViewSet):
|
|||||||
serializer_class = FileSerializer
|
serializer_class = FileSerializer
|
||||||
filter_fields = ['name', ]
|
filter_fields = ['name', ]
|
||||||
permission_classes = []
|
permission_classes = []
|
||||||
|
|
||||||
|
@action(detail=False, methods=['post'])
|
||||||
|
def test_post_file(self, request):
|
||||||
|
|
||||||
|
return SuccessResponse(msg='test_is_ok')
|
||||||
|
|||||||
@@ -117,7 +117,6 @@ class MenuViewSet(CustomModelViewSet):
|
|||||||
"""前端拖拽菜单之后重写parent"""
|
"""前端拖拽菜单之后重写parent"""
|
||||||
menu_id = request.data['menu_id']
|
menu_id = request.data['menu_id']
|
||||||
parent_id = request.data['parent_id']
|
parent_id = request.data['parent_id']
|
||||||
print(parent_id)
|
|
||||||
menu = Menu.objects.get(id=menu_id)
|
menu = Menu.objects.get(id=menu_id)
|
||||||
menu.parent_id = parent_id
|
menu.parent_id = parent_id
|
||||||
menu.save()
|
menu.save()
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ class MessageCenterTargetUserListSerializer(CustomModelSerializer):
|
|||||||
def get_is_read(self, instance):
|
def get_is_read(self, instance):
|
||||||
user_id = self.request.user.id
|
user_id = self.request.user.id
|
||||||
message_center_id = instance.id
|
message_center_id = instance.id
|
||||||
queryset = MessageCenterTargetUser.objects.filter(messagecenter__id=message_center_id,users_id=user_id).first()
|
queryset = MessageCenterTargetUser.objects.filter(messagecenter__id=message_center_id, users_id=user_id).first()
|
||||||
if queryset:
|
if queryset:
|
||||||
return queryset.is_read
|
return queryset.is_read
|
||||||
return False
|
return False
|
||||||
@@ -95,12 +95,12 @@ class MessageCenterTargetUserListSerializer(CustomModelSerializer):
|
|||||||
fields = "__all__"
|
fields = "__all__"
|
||||||
read_only_fields = ["id"]
|
read_only_fields = ["id"]
|
||||||
|
|
||||||
|
|
||||||
def websocket_push(user_id, message):
|
def websocket_push(user_id, message):
|
||||||
"""
|
"""
|
||||||
主动推送消息
|
主动推送消息
|
||||||
"""
|
"""
|
||||||
username = "user_"+str(user_id)
|
username = "user_" + str(user_id)
|
||||||
print(103,message)
|
|
||||||
channel_layer = get_channel_layer()
|
channel_layer = get_channel_layer()
|
||||||
async_to_sync(channel_layer.group_send)(
|
async_to_sync(channel_layer.group_send)(
|
||||||
username,
|
username,
|
||||||
@@ -110,6 +110,7 @@ def websocket_push(user_id, message):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class MessageCenterCreateSerializer(CustomModelSerializer):
|
class MessageCenterCreateSerializer(CustomModelSerializer):
|
||||||
"""
|
"""
|
||||||
消息中心-新增-序列化器
|
消息中心-新增-序列化器
|
||||||
@@ -122,10 +123,10 @@ class MessageCenterCreateSerializer(CustomModelSerializer):
|
|||||||
# 在保存之前,根据目标类型,把目标用户查询出来并保存
|
# 在保存之前,根据目标类型,把目标用户查询出来并保存
|
||||||
users = initial_data.get('target_user', [])
|
users = initial_data.get('target_user', [])
|
||||||
if target_type in [1]: # 按角色
|
if target_type in [1]: # 按角色
|
||||||
target_role = initial_data.get('target_role',[])
|
target_role = initial_data.get('target_role', [])
|
||||||
users = Users.objects.filter(role__id__in=target_role).values_list('id', flat=True)
|
users = Users.objects.filter(role__id__in=target_role).values_list('id', flat=True)
|
||||||
if target_type in [2]: # 按部门
|
if target_type in [2]: # 按部门
|
||||||
target_dept = initial_data.get('target_dept',[])
|
target_dept = initial_data.get('target_dept', [])
|
||||||
users = Users.objects.filter(dept__id__in=target_dept).values_list('id', flat=True)
|
users = Users.objects.filter(dept__id__in=target_dept).values_list('id', flat=True)
|
||||||
if target_type in [3]: # 系统通知
|
if target_type in [3]: # 系统通知
|
||||||
users = Users.objects.values_list('id', flat=True)
|
users = Users.objects.values_list('id', flat=True)
|
||||||
@@ -195,7 +196,6 @@ class MessageCenterViewSet(CustomModelViewSet):
|
|||||||
self_user_id = self.request.user.id
|
self_user_id = self.request.user.id
|
||||||
# queryset = MessageCenterTargetUser.objects.filter(users__id=self_user_id).order_by('-create_datetime')
|
# queryset = MessageCenterTargetUser.objects.filter(users__id=self_user_id).order_by('-create_datetime')
|
||||||
queryset = MessageCenter.objects.filter(target_user__id=self_user_id)
|
queryset = MessageCenter.objects.filter(target_user__id=self_user_id)
|
||||||
print(queryset)
|
|
||||||
# queryset = self.filter_queryset(queryset)
|
# queryset = self.filter_queryset(queryset)
|
||||||
page = self.paginate_queryset(queryset)
|
page = self.paginate_queryset(queryset)
|
||||||
if page is not None:
|
if page is not None:
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
"ts-md5": "^1.3.1",
|
"ts-md5": "^1.3.1",
|
||||||
"vue": "^3.2.45",
|
"vue": "^3.2.45",
|
||||||
"vue-clipboard3": "^2.0.0",
|
"vue-clipboard3": "^2.0.0",
|
||||||
|
"vue-cropper": "^1.0.8",
|
||||||
"vue-grid-layout": "^3.0.0-beta1",
|
"vue-grid-layout": "^3.0.0-beta1",
|
||||||
"vue-i18n": "^9.2.2",
|
"vue-i18n": "^9.2.2",
|
||||||
"vue-router": "^4.1.6",
|
"vue-router": "^4.1.6",
|
||||||
|
|||||||
171
web/src/components/avatarSelector/index.vue
Normal file
171
web/src/components/avatarSelector/index.vue
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
<template>
|
||||||
|
<div class="user-info-head" @click="editCropper()">
|
||||||
|
<el-avatar :size="100" :src="options.img" />
|
||||||
|
<el-dialog :title="title" v-model="open" width="600px" append-to-body @opened="modalOpened" @close="closeDialog">
|
||||||
|
<el-row>
|
||||||
|
<el-col class="flex justify-center">
|
||||||
|
<vue-cropper
|
||||||
|
ref="cropper"
|
||||||
|
:img="options.img"
|
||||||
|
:info="true"
|
||||||
|
:autoCrop="options.autoCrop"
|
||||||
|
:autoCropWidth="options.autoCropWidth"
|
||||||
|
:autoCropHeight="options.autoCropHeight"
|
||||||
|
:fixedBox="options.fixedBox"
|
||||||
|
:outputType="options.outputType"
|
||||||
|
@realTime="realTime"
|
||||||
|
:centerBox="true"
|
||||||
|
v-if="visible"
|
||||||
|
class="cropper"
|
||||||
|
/>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<br />
|
||||||
|
<el-row class="flex justify-center">
|
||||||
|
<el-col :lg="2" :md="2">
|
||||||
|
<el-upload action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload">
|
||||||
|
<el-button type="success">
|
||||||
|
选择
|
||||||
|
<el-icon class="el-icon--right"><Plus /></el-icon>
|
||||||
|
</el-button>
|
||||||
|
</el-upload>
|
||||||
|
</el-col>
|
||||||
|
<el-col :lg="{ span: 1, offset: 2 }" :md="2">
|
||||||
|
<el-button icon="RefreshLeft" @click="rotateLeft()"></el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :lg="{ span: 1, offset: 2 }" :md="2">
|
||||||
|
<el-button icon="RefreshRight" @click="rotateRight()"></el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :lg="{ span: 2, offset: 2 }" :md="2">
|
||||||
|
<el-button type="primary" @click="uploadImg()">更新头像</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import 'vue-cropper/dist/index.css';
|
||||||
|
import { VueCropper } from 'vue-cropper';
|
||||||
|
import { useUserInfo } from '/@/stores/userInfo';
|
||||||
|
import { getCurrentInstance, nextTick, reactive, ref } from 'vue';
|
||||||
|
import { base64ToFile } from '/@/utils/tools';
|
||||||
|
const userStore = useUserInfo();
|
||||||
|
const { proxy } = getCurrentInstance();
|
||||||
|
|
||||||
|
const open = ref(false);
|
||||||
|
const visible = ref(false);
|
||||||
|
const title = ref('修改头像');
|
||||||
|
const emit = defineEmits(['uploadImg']);
|
||||||
|
|
||||||
|
//图片裁剪数据
|
||||||
|
const options = reactive({
|
||||||
|
img: userStore.userInfos.avatar, // 裁剪图片的地址
|
||||||
|
autoCrop: true, // 是否默认生成截图框
|
||||||
|
autoCropWidth: 200, // 默认生成截图框宽度
|
||||||
|
autoCropHeight: 200, // 默认生成截图框高度
|
||||||
|
fixedBox: true, // 固定截图框大小 不允许改变
|
||||||
|
outputType: 'png', // 默认生成截图为PNG格式
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 编辑头像 */
|
||||||
|
function editCropper() {
|
||||||
|
open.value = true;
|
||||||
|
}
|
||||||
|
/** 打开弹出层结束时的回调 */
|
||||||
|
function modalOpened() {
|
||||||
|
nextTick(() => {
|
||||||
|
visible.value = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/** 覆盖默认上传行为 */
|
||||||
|
function requestUpload() {}
|
||||||
|
/** 向左旋转 */
|
||||||
|
function rotateLeft() {
|
||||||
|
proxy.$refs.cropper.rotateLeft();
|
||||||
|
}
|
||||||
|
/** 向右旋转 */
|
||||||
|
function rotateRight() {
|
||||||
|
proxy.$refs.cropper.rotateRight();
|
||||||
|
}
|
||||||
|
/** 图片缩放 */
|
||||||
|
function changeScale(num) {
|
||||||
|
num = num || 1;
|
||||||
|
proxy.$refs.cropper.changeScale(num);
|
||||||
|
}
|
||||||
|
/** 上传预处理 */
|
||||||
|
function beforeUpload(file) {
|
||||||
|
if (file.type.indexOf('image/') == -1) {
|
||||||
|
proxy.$modal.msgError('文件格式错误,请上传图片类型,如:JPG,PNG后缀的文件。');
|
||||||
|
} else {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
reader.onload = () => {
|
||||||
|
options.img = reader.result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** 上传图片 */
|
||||||
|
function uploadImg() {
|
||||||
|
// 获取截图的 base64 数据
|
||||||
|
proxy.$refs.cropper.getCropData((data) => {
|
||||||
|
let img = new Image();
|
||||||
|
img.src = data;
|
||||||
|
img.onload = async () => {
|
||||||
|
let _data = compress(img);
|
||||||
|
const imgFile = base64ToFile(_data, 'testname');
|
||||||
|
emit('uploadImg', imgFile);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 压缩图片
|
||||||
|
function compress(img) {
|
||||||
|
let canvas = document.createElement('canvas');
|
||||||
|
let ctx = canvas.getContext('2d');
|
||||||
|
// let initSize = img.src.length;
|
||||||
|
let width = img.width;
|
||||||
|
let height = img.height;
|
||||||
|
canvas.width = width;
|
||||||
|
canvas.height = height;
|
||||||
|
// 铺底色
|
||||||
|
ctx.fillStyle = '#fff';
|
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
ctx.drawImage(img, 0, 0, width, height);
|
||||||
|
// 进行压缩
|
||||||
|
let ndata = canvas.toDataURL('image/jpeg', 0.8);
|
||||||
|
return ndata;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 关闭窗口 */
|
||||||
|
function closeDialog() {
|
||||||
|
options.img = userStore.userInfos.avatar;
|
||||||
|
options.visible = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.user-info-head {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
height: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info-head:hover:after {
|
||||||
|
content: '修改头像';
|
||||||
|
position: absolute;
|
||||||
|
text-align: center;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
color: #000000;
|
||||||
|
font-size: 20px;
|
||||||
|
font-style: normal;
|
||||||
|
cursor: pointer;
|
||||||
|
line-height: 110px;
|
||||||
|
}
|
||||||
|
.cropper {
|
||||||
|
height: 400px;
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -5,11 +5,17 @@
|
|||||||
|
|
||||||
// 用户信息
|
// 用户信息
|
||||||
export interface UserInfosState {
|
export interface UserInfosState {
|
||||||
authBtnList: string[];
|
avatar: string;
|
||||||
photo: string;
|
|
||||||
roles: string[];
|
|
||||||
time: number;
|
|
||||||
userName: string;
|
userName: string;
|
||||||
|
name: string;
|
||||||
|
email: string;
|
||||||
|
mobile: string;
|
||||||
|
gender: string;
|
||||||
|
dept_info: {
|
||||||
|
dept_id: number;
|
||||||
|
dept_name: string;
|
||||||
|
};
|
||||||
|
role_info: any[];
|
||||||
}
|
}
|
||||||
export interface UserInfosStates {
|
export interface UserInfosStates {
|
||||||
userInfos: UserInfosState;
|
userInfos: UserInfosState;
|
||||||
|
|||||||
@@ -11,11 +11,22 @@ import { request } from '../utils/service';
|
|||||||
export const useUserInfo = defineStore('userInfo', {
|
export const useUserInfo = defineStore('userInfo', {
|
||||||
state: (): UserInfosStates => ({
|
state: (): UserInfosStates => ({
|
||||||
userInfos: {
|
userInfos: {
|
||||||
|
avatar: '',
|
||||||
userName: '',
|
userName: '',
|
||||||
photo: '',
|
name: '',
|
||||||
time: 0,
|
email: '',
|
||||||
roles: [],
|
mobile: '',
|
||||||
authBtnList: [],
|
gender: '',
|
||||||
|
dept_info: {
|
||||||
|
dept_id: 0,
|
||||||
|
dept_name: '',
|
||||||
|
},
|
||||||
|
role_info: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
@@ -26,17 +37,22 @@ export const useUserInfo = defineStore('userInfo', {
|
|||||||
} else {
|
} else {
|
||||||
let userInfos: any = await this.getApiUserInfo();
|
let userInfos: any = await this.getApiUserInfo();
|
||||||
this.userInfos.userName = userInfos.data.name;
|
this.userInfos.userName = userInfos.data.name;
|
||||||
this.userInfos.photo = userInfos.data.avatar || 'https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500'
|
this.userInfos.avatar =
|
||||||
this.userInfos.time = new Date().getTime()
|
userInfos.data.avatar || 'https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500';
|
||||||
this.userInfos.roles = ['admin']
|
this.userInfos.name = userInfos.data.name;
|
||||||
Session.set('userInfo', this.userInfos)
|
this.userInfos.email = userInfos.data.email;
|
||||||
|
this.userInfos.mobile = userInfos.data.mobile;
|
||||||
|
this.userInfos.gender = userInfos.data.gender;
|
||||||
|
this.userInfos.dept_info = userInfos.data.dept_info;
|
||||||
|
this.userInfos.role_info = userInfos.data.role_info;
|
||||||
|
Session.set('userInfo', this.userInfos);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async getApiUserInfo() {
|
async getApiUserInfo() {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/system/user/user_info/',
|
url: '/api/system/user/user_info/',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
})
|
});
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
* @param {String} jsonString 需要解析的 json 字符串
|
* @param {String} jsonString 需要解析的 json 字符串
|
||||||
* @param {String} defaultValue 默认值
|
* @param {String} defaultValue 默认值
|
||||||
*/
|
*/
|
||||||
import { uiContext } from "@fast-crud/fast-crud";
|
import { uiContext } from '@fast-crud/fast-crud';
|
||||||
|
|
||||||
export function parse(jsonString = "{}", defaultValue = {}) {
|
export function parse(jsonString = '{}', defaultValue = {}) {
|
||||||
let result = defaultValue;
|
let result = defaultValue;
|
||||||
try {
|
try {
|
||||||
result = JSON.parse(jsonString);
|
result = JSON.parse(jsonString);
|
||||||
@@ -21,7 +21,7 @@ export function parse(jsonString = "{}", defaultValue = {}) {
|
|||||||
* @param {String} msg 状态信息
|
* @param {String} msg 状态信息
|
||||||
* @param {Number} code 状态码
|
* @param {Number} code 状态码
|
||||||
*/
|
*/
|
||||||
export function response(data = {}, msg = "", code = 0) {
|
export function response(data = {}, msg = '', code = 0) {
|
||||||
return [200, { code, msg, data }];
|
return [200, { code, msg, data }];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ export function response(data = {}, msg = "", code = 0) {
|
|||||||
* @param {Any} data 返回值
|
* @param {Any} data 返回值
|
||||||
* @param {String} msg 状态信息
|
* @param {String} msg 状态信息
|
||||||
*/
|
*/
|
||||||
export function responseSuccess(data = {}, msg = "成功") {
|
export function responseSuccess(data = {}, msg = '成功') {
|
||||||
return response(data, msg);
|
return response(data, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ export function responseSuccess(data = {}, msg = "成功") {
|
|||||||
* @param {String} msg 状态信息
|
* @param {String} msg 状态信息
|
||||||
* @param {Number} code 状态码
|
* @param {Number} code 状态码
|
||||||
*/
|
*/
|
||||||
export function responseError(data = {}, msg = "请求失败", code = 500) {
|
export function responseError(data = {}, msg = '请求失败', code = 500) {
|
||||||
return response(data, msg, code);
|
return response(data, msg, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,22 +48,49 @@ export function responseError(data = {}, msg = "请求失败", code = 500) {
|
|||||||
* @description 记录和显示错误
|
* @description 记录和显示错误
|
||||||
* @param {Error} error 错误对象
|
* @param {Error} error 错误对象
|
||||||
*/
|
*/
|
||||||
export function errorLog(error:any,notification=true) {
|
export function errorLog(error: any, notification = true) {
|
||||||
// 打印到控制台
|
// 打印到控制台
|
||||||
console.error(error);
|
console.error(error);
|
||||||
// 显示提示
|
// 显示提示
|
||||||
if(notification){
|
if (notification) {
|
||||||
uiContext.get().notification.error({ message: error.message });
|
uiContext.get().notification.error({ message: error.message });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 创建一个错误
|
* @description 创建一个错误
|
||||||
* @param {String} msg 错误信息
|
* @param {String} msg 错误信息
|
||||||
*/
|
*/
|
||||||
export function errorCreate(msg:any,notification=true) {
|
export function errorCreate(msg: any, notification = true) {
|
||||||
const error = new Error(msg);
|
const error = new Error(msg);
|
||||||
errorLog(error,notification);
|
errorLog(error, notification);
|
||||||
// throw error;
|
// throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function base64ToFile(base64: any, fileName: string) {
|
||||||
|
// 将base64按照 , 进行分割 将前缀 与后续内容分隔开
|
||||||
|
let data = base64.split(',');
|
||||||
|
// 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等)
|
||||||
|
let type = data[0].match(/:(.*?);/)[1];
|
||||||
|
// 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp)
|
||||||
|
let suffix = type.split('/')[1];
|
||||||
|
// 使用atob()对base64数据进行解码 结果是一个文件数据流 以字符串的格式输出
|
||||||
|
const bstr = window.atob(data[1]);
|
||||||
|
// 获取解码结果字符串的长度
|
||||||
|
let n = bstr.length;
|
||||||
|
// 根据解码结果字符串的长度创建一个等长的整形数字数组
|
||||||
|
// 但在创建时 所有元素初始值都为 0
|
||||||
|
const u8arr = new Uint8Array(n);
|
||||||
|
// 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元
|
||||||
|
while (n--) {
|
||||||
|
// charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元
|
||||||
|
u8arr[n] = bstr.charCodeAt(n);
|
||||||
|
}
|
||||||
|
// 利用构造函数创建File文件对象
|
||||||
|
// new File(bits, name, options)
|
||||||
|
const file = new File([u8arr], `${fileName}.${suffix}`, {
|
||||||
|
type: type,
|
||||||
|
});
|
||||||
|
// 将File文件对象返回给方法的调用者
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|||||||
@@ -89,8 +89,8 @@ export default defineComponent({
|
|||||||
const state = reactive({
|
const state = reactive({
|
||||||
isShowPassword: false,
|
isShowPassword: false,
|
||||||
ruleForm: {
|
ruleForm: {
|
||||||
username: 'superadmin',
|
username: '',
|
||||||
password: 'admin123456',
|
password: '',
|
||||||
captcha: '',
|
captcha: '',
|
||||||
captchaKey: '',
|
captchaKey: '',
|
||||||
captchaImgBase: '',
|
captchaImgBase: '',
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import { request } from '/@/utils/service';
|
import { request } from '/@/utils/service';
|
||||||
import { PageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud';
|
import { PageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud';
|
||||||
import {apiPrefix} from "/@/views/system/messageCenter/api";
|
import { apiPrefix } from '/@/views/system/messageCenter/api';
|
||||||
export function GetUserInfo(query: PageQuery) {
|
export function GetUserInfo(query: PageQuery) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/system/user/user_info/',
|
url: '/api/system/user/user_info/',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新用户信息
|
* 更新用户信息
|
||||||
* @param data
|
* @param data
|
||||||
@@ -18,23 +17,22 @@ export function updateUserInfo(data: AddReq) {
|
|||||||
return request({
|
return request({
|
||||||
url: '/api/system/user/update_user_info/',
|
url: '/api/system/user/update_user_info/',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取自己接收的消息
|
* 获取自己接收的消息
|
||||||
* @param query
|
* @param query
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
export function GetSelfReceive (query:PageQuery) {
|
export function GetSelfReceive(query: PageQuery) {
|
||||||
return request({
|
return request({
|
||||||
url: '/api/system/message_center/get_self_receive/',
|
url: '/api/system/message_center/get_self_receive/',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@@ -45,6 +43,21 @@ export function UpdatePassword(data: EditReq) {
|
|||||||
return request({
|
return request({
|
||||||
url: '/api/system/user/change_password/',
|
url: '/api/system/user/change_password/',
|
||||||
method: 'put',
|
method: 'put',
|
||||||
data: data
|
data: data,
|
||||||
})
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/***
|
||||||
|
* 上传头像
|
||||||
|
* @param data
|
||||||
|
*/
|
||||||
|
export function uploadAvatar(data: AddReq) {
|
||||||
|
return request({
|
||||||
|
url: 'api/system/file/',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data',
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,9 @@
|
|||||||
<el-card shadow="hover" header="个人信息">
|
<el-card shadow="hover" header="个人信息">
|
||||||
<div class="personal-user">
|
<div class="personal-user">
|
||||||
<div class="personal-user-left">
|
<div class="personal-user-left">
|
||||||
<el-upload class="h100 personal-user-left-upload" :action="uploadAvatar.action" :headers="uploadAvatar.headers" multiple :limit="1">
|
<!-- <el-avatar :size="100" v-if="state.personalForm.avatar" :src="state.personalForm.avatar" /> -->
|
||||||
<img v-if="state.personalForm.avatar" :src="state.personalForm.avatar" />
|
<!-- <el-avatar :size="100" v-else src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" /> -->
|
||||||
<img v-else src="https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500" />
|
<avatarSelector @uploadImg="uploadImg"></avatarSelector>
|
||||||
</el-upload>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="personal-user-right">
|
<div class="personal-user-right">
|
||||||
<el-row>
|
<el-row>
|
||||||
@@ -174,13 +173,18 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="personal">
|
<script setup lang="ts" name="personal">
|
||||||
import { reactive, computed, onMounted, ref } from 'vue';
|
import { reactive, computed, onMounted, ref, defineAsyncComponent } from 'vue';
|
||||||
import { formatAxis } from '/@/utils/formatTime';
|
import { formatAxis } from '/@/utils/formatTime';
|
||||||
import * as api from './api';
|
import * as api from './api';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
import { getBaseURL } from '/@/utils/baseUrl';
|
import { getBaseURL } from '/@/utils/baseUrl';
|
||||||
import { Session } from '/@/utils/storage';
|
import { Session } from '/@/utils/storage';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
|
import { useUserInfo } from '/@/stores/userInfo';
|
||||||
|
const userStore = useUserInfo();
|
||||||
|
|
||||||
|
// 头像裁剪组件
|
||||||
|
const avatarSelector = defineAsyncComponent(() => import('/@/components/avatarSelector/index.vue'));
|
||||||
|
|
||||||
// 当前时间提示语
|
// 当前时间提示语
|
||||||
const currentTime = computed(() => {
|
const currentTime = computed(() => {
|
||||||
@@ -339,6 +343,17 @@ const settingPassword = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const uploadImg = (data: any) => {
|
||||||
|
console.log(data);
|
||||||
|
let formdata = new FormData();
|
||||||
|
formdata.append('key', 'test_file');
|
||||||
|
formdata.append('file', data);
|
||||||
|
api.uploadAvatar(formdata).then((res: any) => {
|
||||||
|
// userStore.setUserInfos()
|
||||||
|
console.log(res);
|
||||||
|
});
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
@@ -5045,6 +5045,11 @@ vue-clipboard3@^2.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
clipboard "^2.0.6"
|
clipboard "^2.0.6"
|
||||||
|
|
||||||
|
vue-cropper@^1.0.8:
|
||||||
|
version "1.0.8"
|
||||||
|
resolved "https://registry.npmjs.org/vue-cropper/-/vue-cropper-1.0.8.tgz#05853bb7702557d05a4784a8d0cd072b57dd8e4f"
|
||||||
|
integrity sha512-EX9XoT5a/PQ62J6KDZz8hhaFi9ME1k2yBZlRfYCm8iySzTcjw0nDBq8Y65HtyHaH2jJwUKgYfD6mdFCE0GhUzA==
|
||||||
|
|
||||||
vue-cropperjs@^5.0.0:
|
vue-cropperjs@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.npmjs.org/vue-cropperjs/-/vue-cropperjs-5.0.0.tgz#7f8cbc460737af3831b4ded634c95905198e329e"
|
resolved "https://registry.npmjs.org/vue-cropperjs/-/vue-cropperjs-5.0.0.tgz#7f8cbc460737af3831b4ded634c95905198e329e"
|
||||||
|
|||||||
Reference in New Issue
Block a user