用户管理完成,用户中心完成
This commit is contained in:
parent
04955c9d4d
commit
996d1a2cf8
|
|
@ -13,6 +13,7 @@
|
|||
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||
"axios": "^1.6.3",
|
||||
"countup.js": "^2.8.0",
|
||||
"cropperjs": "^2.0.0",
|
||||
"echarts": "^5.5.0",
|
||||
"echarts-wordcloud": "^2.1.0",
|
||||
"element-plus": "^2.6.3",
|
||||
|
|
@ -22,6 +23,7 @@
|
|||
"pinia": "^2.1.7",
|
||||
"vue": "^3.4.5",
|
||||
"vue-cropper": "1.1.1",
|
||||
"vue-cropperjs": "^5.0.0",
|
||||
"vue-echarts": "^6.6.9",
|
||||
"vue-router": "^4.2.5",
|
||||
"vue-schart": "^2.0.0",
|
||||
|
|
@ -69,6 +71,115 @@
|
|||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element/-/element-2.0.0.tgz",
|
||||
"integrity": "sha512-lsthn0nQq73GExUE7Mg/ss6Q3RXADGDv055hxoLFwvl/wGHgy6ZkYlfLZ/VmgBHC6jDK5IgPBFnqrPqlXWSGBA==",
|
||||
"dependencies": {
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-canvas": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-canvas/-/element-canvas-2.0.0.tgz",
|
||||
"integrity": "sha512-GPtGJgSm92crJhhhwUsaMw3rz2KfJWWSz7kRAlufFEV/EHTP5+6r6/Z1BCGRna830i+Avqbm435XLOtA7PVJwA==",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-crosshair": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-crosshair/-/element-crosshair-2.0.0.tgz",
|
||||
"integrity": "sha512-KfPfyrdeFvUC31Ws7ATtcalWWSaMtrC6bMoCipZhqbUOE7wZoL4ecDSL6BUOZxPa74awZUqfzirCDjHvheBfyw==",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-grid": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-grid/-/element-grid-2.0.0.tgz",
|
||||
"integrity": "sha512-i78SQ0IJTLFveKX6P7svkfMYVdgHrQ8ZmmEw8keFy9n1ZVbK+SK0UHK5FNMRNI/gtVhKJOGEnK/zeyjUdj4Iyw==",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-handle": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-handle/-/element-handle-2.0.0.tgz",
|
||||
"integrity": "sha512-ZJvW+0MkK9E8xYymGdoruaQn2kwjSHFpNSWinjyq6csuVQiCPxlX5ovAEDldmZ9MWePPtWEi3vLKQOo2Yb0T8g==",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-image": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-image/-/element-image-2.0.0.tgz",
|
||||
"integrity": "sha512-9BxiTS/aHRmrjopaFQb9mQQXmx4ruhYHGkDZMVz24AXpMFjUY6OpqrWse/WjzD9tfhMFvEdu17b3VAekcAgpeg==",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/element-canvas": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-selection": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-selection/-/element-selection-2.0.0.tgz",
|
||||
"integrity": "sha512-ensNnbIfJsJ8bhbJTH/RXtk2URFvTOO4TvfRk461n2FPEC588D7rwBmUJxQg74IiTi4y1JbCI+6j+4LyzYBLCQ==",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/element-canvas": "^2.0.0",
|
||||
"@cropper/element-image": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-shade": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-shade/-/element-shade-2.0.0.tgz",
|
||||
"integrity": "sha512-jv/2bbNZnhU4W+T4G0c8ADocLIZvQFTXgCf2RFDNhI5UVxurzWBnDdb8Mx8LnVplnkTqO+xUmHZYve0CwgWo+Q==",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/element-canvas": "^2.0.0",
|
||||
"@cropper/element-selection": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/element-viewer": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/element-viewer/-/element-viewer-2.0.0.tgz",
|
||||
"integrity": "sha512-zY+3VRN5TvpM8twlphYtXw0tzJL2VgzeK7ufhL1BixVqOdRxwP13TprYIhqwGt9EW/SyJZUiaIu396T89kRX8A==",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/element-canvas": "^2.0.0",
|
||||
"@cropper/element-image": "^2.0.0",
|
||||
"@cropper/element-selection": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/elements": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/elements/-/elements-2.0.0.tgz",
|
||||
"integrity": "sha512-PQkPo1nUjxLFUQuHYu+6atfHxpX9B41Xribao6wpvmvmNIFML6LQdNqqWYb6LyM7ujsu71CZdBiMT5oetjJVoQ==",
|
||||
"dependencies": {
|
||||
"@cropper/element": "^2.0.0",
|
||||
"@cropper/element-canvas": "^2.0.0",
|
||||
"@cropper/element-crosshair": "^2.0.0",
|
||||
"@cropper/element-grid": "^2.0.0",
|
||||
"@cropper/element-handle": "^2.0.0",
|
||||
"@cropper/element-image": "^2.0.0",
|
||||
"@cropper/element-selection": "^2.0.0",
|
||||
"@cropper/element-shade": "^2.0.0",
|
||||
"@cropper/element-viewer": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@cropper/utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@cropper/utils/-/utils-2.0.0.tgz",
|
||||
"integrity": "sha512-cprLYr+7kK3faGgoOsTW9gIn5sefDr2KwOmgyjzIXk+8PLpW8FgFKEg5FoWfRD5zMAmkCBuX6rGKDK3VdUEGrg=="
|
||||
},
|
||||
"node_modules/@ctrl/tinycolor": {
|
||||
"version": "3.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
|
||||
|
|
@ -847,6 +958,15 @@
|
|||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/cropperjs": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-2.0.0.tgz",
|
||||
"integrity": "sha512-TO2j0Qre01kPHbow4FuTrbdEB4jTmGRySxW49jyEIqlJZuEBfrvCTT0vC3eRB2WBXudDfKi1Onako6DKWKxeAQ==",
|
||||
"dependencies": {
|
||||
"@cropper/elements": "^2.0.0",
|
||||
"@cropper/utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/csstype": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||
|
|
@ -2474,6 +2594,22 @@
|
|||
"resolved": "https://registry.npmjs.org/vue-cropper/-/vue-cropper-1.1.1.tgz",
|
||||
"integrity": "sha512-WsqKMpaBf9Osi1LQlE/5AKdD0nHWOy1asLXocaG8NomOWO07jiZi968+/PbMmnD0QbPJOumDQaGuGa13qys85A=="
|
||||
},
|
||||
"node_modules/vue-cropperjs": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-cropperjs/-/vue-cropperjs-5.0.0.tgz",
|
||||
"integrity": "sha512-RhnC8O33uRZNkn74aiHZwNHnBJOXWlS4P6gsRI0lw4cZlWjKSCywZI9oSI9POlIPI6OYv30jvnHMXGch85tw7w==",
|
||||
"dependencies": {
|
||||
"cropperjs": "^1.5.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": ">=3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-cropperjs/node_modules/cropperjs": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.6.2.tgz",
|
||||
"integrity": "sha512-nhymn9GdnV3CqiEHJVai54TULFAE3VshJTXSqSJKa8yXAKyBKDWdhHarnlIPrshJ0WMFTGuFvG02YjLXfPiuOA=="
|
||||
},
|
||||
"node_modules/vue-echarts": {
|
||||
"version": "6.6.9",
|
||||
"resolved": "https://registry.npmjs.org/vue-echarts/-/vue-echarts-6.6.9.tgz",
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||
"axios": "^1.6.3",
|
||||
"countup.js": "^2.8.0",
|
||||
"cropperjs": "^2.0.0",
|
||||
"echarts": "^5.5.0",
|
||||
"echarts-wordcloud": "^2.1.0",
|
||||
"element-plus": "^2.6.3",
|
||||
|
|
@ -22,6 +23,7 @@
|
|||
"pinia": "^2.1.7",
|
||||
"vue": "^3.4.5",
|
||||
"vue-cropper": "1.1.1",
|
||||
"vue-cropperjs": "^5.0.0",
|
||||
"vue-echarts": "^6.6.9",
|
||||
"vue-router": "^4.2.5",
|
||||
"vue-schart": "^2.0.0",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
import request from '@/utils/request2'
|
||||
|
||||
|
||||
export const GetRedisInfoService = (Data) => {
|
||||
const params = new URLSearchParams();
|
||||
for (let key in Data) {
|
||||
params.append(key, Data[key])
|
||||
}
|
||||
let request1 = getRequest();
|
||||
return request1.post('/tool/get_redis', params,{
|
||||
headers: {
|
||||
'token': Data.token, // 闂佽绻愭蹇涘箯閿燂拷 token 闂備礁鎼ú锔锯偓绗涘啰鏆﹂柛娆忣槺閳绘棃鏌i幋鐏活亝绂嶉崼鏇熺厽闁靛ǹ鍎遍褔鏌熼煬鎻掆偓婵嬪箖瑜忔禒锔炬喆閿濆懍澹曢梺璺ㄥ櫐閹凤拷
|
||||
}
|
||||
})
|
||||
}
|
||||
function getRequest() {
|
||||
let server = localStorage.getItem('cid_server');
|
||||
let request1 = null;
|
||||
if (server === "tx.ljsea.top") {
|
||||
request1 = request;
|
||||
}else{
|
||||
request1 = request;
|
||||
}
|
||||
return request1;
|
||||
}
|
||||
|
||||
export const UploadFileService = (formData,token) => {
|
||||
//let request1 = getRequest();
|
||||
return request.post('/tool/upload', formData,{
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
'token': token,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const GetFileInfoByMd5Service = (Data) => {
|
||||
const params = new URLSearchParams();
|
||||
for (let key in Data) {
|
||||
params.append(key, Data[key])
|
||||
}
|
||||
//let request1 = getRequest();
|
||||
return request.post('/tool/file_list', params,{
|
||||
headers: {
|
||||
'token': Data.token,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -45,9 +45,6 @@
|
|||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<a href="https://github.com/lin-xin/vue-manage-system" target="_blank">
|
||||
<el-dropdown-item>项目仓库</el-dropdown-item>
|
||||
</a>
|
||||
<el-dropdown-item command="user">个人中心</el-dropdown-item>
|
||||
<el-dropdown-item divided command="loginout">退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
|
|
|
|||
|
|
@ -14,3 +14,39 @@ export interface Register {
|
|||
password: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* "ID": 1,
|
||||
"CreatedAt": "2024-08-30T14:35:15.556734+08:00",
|
||||
"UpdatedAt": "2025-03-11T15:13:27.972681+08:00",
|
||||
"DeletedAt": null,
|
||||
"Name": "lijun",
|
||||
"Age": 24,
|
||||
"Email": "lijun@ljsea.top",
|
||||
"Password": "",
|
||||
"Gender": "男",
|
||||
"Role": "admin",
|
||||
"Redis": true,
|
||||
"Run": true,
|
||||
"Upload": true,
|
||||
"VideoFunc": true,
|
||||
"DeviceFunc": true,
|
||||
"CIDFunc": true,
|
||||
"Avatar": "https://gep.ljsea.top/tool/file/d5a17d88-1641-4666-a9e1-53fbb04a6abf.jpg",
|
||||
"CreateTime": "",
|
||||
"UpdateTime": ""
|
||||
*/
|
||||
export interface UserInfo {
|
||||
ID: number;
|
||||
CreatedAt: string;
|
||||
UpdatedAt: string;
|
||||
DeletedAt: string;
|
||||
Name: string;
|
||||
Password: string;
|
||||
Age: number;
|
||||
Email: string;
|
||||
Gender: string;
|
||||
Role: string;
|
||||
Avatar: string;
|
||||
}
|
||||
|
|
@ -30,12 +30,26 @@
|
|||
</el-input>
|
||||
</el-form-item>
|
||||
<div class="pwd-tips">
|
||||
<el-checkbox class="pwd-checkbox" v-model="checked" label="记住密码" />
|
||||
<el-link type="primary" @click="$router.push('/reset-pwd')">忘记密码</el-link>
|
||||
<el-checkbox
|
||||
class="pwd-checkbox"
|
||||
v-model="checked"
|
||||
label="记住密码"
|
||||
/>
|
||||
<el-link type="primary" @click="$router.push('/reset-pwd')"
|
||||
>忘记密码</el-link
|
||||
>
|
||||
</div>
|
||||
<el-button class="login-btn" type="primary" size="large" @click="onLogin">登录</el-button>
|
||||
<el-button
|
||||
class="login-btn"
|
||||
type="primary"
|
||||
size="large"
|
||||
@click="onLogin"
|
||||
>登录</el-button
|
||||
>
|
||||
<p class="login-text">
|
||||
没有账号?<el-link type="primary" @click="$router.push('/register')">立即注册</el-link>
|
||||
没有账号?<el-link type="primary" @click="$router.push('/register')"
|
||||
>立即注册</el-link
|
||||
>
|
||||
</p>
|
||||
</el-form>
|
||||
</div>
|
||||
|
|
@ -43,16 +57,15 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive,inject } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import {loginService} from "@/api/user";
|
||||
import {GetUserInfoService} from "@/api/user";
|
||||
import { usePermissStore } from '@/store/permiss';
|
||||
|
||||
import { ref, reactive, inject } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { loginService } from "@/api/user";
|
||||
import { GetUserInfoService } from "@/api/user";
|
||||
import { usePermissStore } from "@/store/permiss";
|
||||
|
||||
// 从本地存储获取登录参数
|
||||
const lgStr = localStorage.getItem('login-param');
|
||||
const lgStr = localStorage.getItem("login-param");
|
||||
const defParam = lgStr ? JSON.parse(lgStr) : null;
|
||||
const globalData = inject("globalData");
|
||||
const permiss = usePermissStore();
|
||||
|
|
@ -62,8 +75,8 @@ const checked = ref(lgStr ? true : false);
|
|||
const router = useRouter();
|
||||
// 登录表单数据
|
||||
const param = reactive({
|
||||
username: defParam ? defParam.username : '',
|
||||
password: defParam ? defParam.password : ''
|
||||
username: defParam ? defParam.username : "",
|
||||
password: defParam ? defParam.password : "",
|
||||
});
|
||||
|
||||
// 表单验证规则
|
||||
|
|
@ -71,17 +84,17 @@ const rules = {
|
|||
username: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入用户名',
|
||||
trigger: 'blur'
|
||||
}
|
||||
message: "请输入用户名",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
password: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入密码',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
message: "请输入密码",
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
};
|
||||
// 表单引用
|
||||
const login = ref(null);
|
||||
|
|
@ -96,16 +109,16 @@ var loginData = ref({
|
|||
|
||||
//登录接口调用
|
||||
const onLogin = async () => {
|
||||
console.log("params:",param)
|
||||
console.log("params:", param);
|
||||
|
||||
loginData.value.username = param.username;
|
||||
loginData.value.password = param.password;
|
||||
loginData.value.username = param.username;
|
||||
loginData.value.password = param.password;
|
||||
let result = await loginService(loginData);
|
||||
console.log("login result:", result);
|
||||
if (result.code !== 0) {
|
||||
//alert(result.message);
|
||||
ElMessage.error("登录失败!用户名或密码错误");
|
||||
return
|
||||
return;
|
||||
}
|
||||
globalData.token = result.data;
|
||||
localStorage.setItem("token", result.data.token);
|
||||
|
|
@ -115,22 +128,16 @@ loginData.value.password = param.password;
|
|||
localStorage.setItem("end_time", now.setDate(now.getHours() + 12)); //过期时间
|
||||
await getMyUserInfo(result.data.id);
|
||||
//token.value= result.data;
|
||||
ElMessage.success('登录成功');
|
||||
localStorage.setItem('ms_username', result.data.username);
|
||||
const keys = permiss.defaultList[result.data.username == 'admin' ? 'admin' : 'user'];
|
||||
permiss.handleSet(keys);
|
||||
localStorage.setItem('ms_keys', JSON.stringify(keys));
|
||||
router.push("/");
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
const getMyUserInfo = async (id) => {
|
||||
let result = {};
|
||||
try {
|
||||
let tokenData ={
|
||||
let tokenData = {
|
||||
token: localStorage.getItem("token"),
|
||||
id: id,
|
||||
}
|
||||
};
|
||||
result = await GetUserInfoService(tokenData);
|
||||
if (result.code === 0) {
|
||||
//console.log("token data:",this.tokenData)
|
||||
|
|
@ -139,6 +146,14 @@ const getMyUserInfo = async (id) => {
|
|||
localStorage.setItem("cid_func", result.data.CIDFunc);
|
||||
localStorage.setItem("role", result.data.Role);
|
||||
|
||||
ElMessage.success("登录成功");
|
||||
localStorage.setItem("ms_username", result.data.Name);
|
||||
const keys =
|
||||
permiss.defaultList[result.data.Role == "admin" ? "admin" : "user"];
|
||||
permiss.handleSet(keys);
|
||||
localStorage.setItem("ms_keys", JSON.stringify(keys));
|
||||
router.push("/");
|
||||
|
||||
//alert("video_func:" + localStorage.getItem("video_func")+" type:" +typeof(localStorage.getItem("video_func")));
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
@ -147,7 +162,6 @@ const getMyUserInfo = async (id) => {
|
|||
};
|
||||
|
||||
// 获取标签存储并清空标签
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
|||
|
|
@ -105,6 +105,14 @@ const getMyUserInfo = async (id) => {
|
|||
localStorage.setItem("cid_func", result.data.CIDFunc);
|
||||
localStorage.setItem("role", result.data.Role);
|
||||
|
||||
ElMessage.success("注册成功");
|
||||
localStorage.setItem("ms_username", result.data.Name);
|
||||
const keys =
|
||||
permiss.defaultList[result.data.Role == "admin" ? "admin" : "user"];
|
||||
permiss.handleSet(keys);
|
||||
localStorage.setItem("ms_keys", JSON.stringify(keys));
|
||||
router.push("/");
|
||||
|
||||
//alert("video_func:" + localStorage.getItem("video_func")+" type:" +typeof(localStorage.getItem("video_func")));
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -8,28 +8,16 @@
|
|||
</div>
|
||||
<div class="user-info">
|
||||
<div class="info-name">{{ name }}</div>
|
||||
<div class="info-desc">
|
||||
<span>@lin-xin</span>
|
||||
<el-divider direction="vertical" />
|
||||
<el-link href="https://lin-xin.gitee.io" target="_blank">lin-xin.gitee.io</el-link>
|
||||
</div>
|
||||
<div class="info-desc">FE Developer</div>
|
||||
<div class="info-icon">
|
||||
<a href="https://github.com/lin-xin" target="_blank"> <i class="el-icon-lx-github-fill"></i></a>
|
||||
<i class="el-icon-lx-qq-fill"></i>
|
||||
<i class="el-icon-lx-facebook-fill"></i>
|
||||
<i class="el-icon-lx-twitter-fill"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-footer">
|
||||
<div class="user-footer-item">
|
||||
<el-statistic title="Follower" :value="1800" />
|
||||
<el-statistic title="提问数" :value="1800" />
|
||||
</div>
|
||||
<div class="user-footer-item">
|
||||
<el-statistic title="Following" :value="666" />
|
||||
<el-statistic title="会话数" :value="666" />
|
||||
</div>
|
||||
<div class="user-footer-item">
|
||||
<el-statistic title="Total Post" :value="888" />
|
||||
<el-statistic title="总计" :value="888" />
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
|
@ -39,9 +27,9 @@
|
|||
:body-style="{ padding: '20px 50px', height: '100%', boxSizing: 'border-box' }"
|
||||
>
|
||||
<el-tabs tab-position="left" v-model="activeName">
|
||||
<el-tab-pane name="label1" label="消息通知" class="user-tabpane">
|
||||
<!-- <el-tab-pane name="label1" label="消息通知" class="user-tabpane">
|
||||
<TabsComp />
|
||||
</el-tab-pane>
|
||||
</el-tab-pane> -->
|
||||
<el-tab-pane name="label2" label="我的头像" class="user-tabpane">
|
||||
<div class="crop-wrap" v-if="activeName === 'label2'">
|
||||
<vueCropper
|
||||
|
|
@ -72,24 +60,13 @@
|
|||
<el-input type="password" v-model="form.new1"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
||||
<el-button type="primary" @click="resetPassword ">保存</el-button>
|
||||
</el-form-item>
|
||||
<el-link type="primary" @click="reset_password()">忘记密码?使用验证码重置</el-link>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="label4" label="赞赏作者" class="user-tabpane">
|
||||
<div class="plugins-tips">
|
||||
如果该框架
|
||||
<el-link href="https://github.com/lin-xin/vue-manage-system" target="_blank"
|
||||
>vue-manage-system</el-link
|
||||
>
|
||||
对你有帮助,那就请作者喝杯饮料吧!<el-icon>
|
||||
<ColdDrink />
|
||||
</el-icon>
|
||||
加微信号 linxin_20 探讨问题。
|
||||
</div>
|
||||
<div>
|
||||
<img src="https://lin-xin.gitee.io/images/weixin.jpg" />
|
||||
</div>
|
||||
<el-tab-pane name="label4" v-if="isUserInfoLoaded" label="详细信息" class="user-tabpane">
|
||||
<TableEdit :form-data="userInfo" :options="options_edit" :edit="true" :update="updateUserInfo" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
|
|
@ -103,6 +80,15 @@ import { VueCropper } from 'vue-cropper';
|
|||
import 'vue-cropper/dist/index.css';
|
||||
import avatar from '@/assets/img/img.jpg';
|
||||
import TabsComp from '../element/tabs.vue';
|
||||
import {GetUserInfoService} from "@/api/user";
|
||||
import { UploadFileService } from "@/api/tool";
|
||||
import { UserInfo } from '@/types/user';
|
||||
import { FormOption, FormOptionList } from '@/types/form-option';
|
||||
import { avatarEmits, ElMessage } from 'element-plus';
|
||||
import TableEdit from '@/components/table-edit.vue';
|
||||
import {genResetPassword} from "@/api/user";
|
||||
import {updateUserInfoService} from "@/api/user";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
const name = localStorage.getItem('ms_username');
|
||||
const form = reactive({
|
||||
|
|
@ -111,17 +97,31 @@ const form = reactive({
|
|||
old: '',
|
||||
});
|
||||
const onSubmit = () => {};
|
||||
const userInfo = ref<UserInfo>({});
|
||||
const isUserInfoLoaded = ref(false);
|
||||
|
||||
const activeName = ref('label1');
|
||||
|
||||
const avatarImg = ref(avatar);
|
||||
const imgSrc = ref(avatar);
|
||||
const activeName = ref('label2');
|
||||
const router = useRouter();
|
||||
const avatarImg = ref('');
|
||||
const imgSrc = ref('');
|
||||
const cropImg = ref('');
|
||||
const cropper: any = ref();
|
||||
|
||||
const reset_password = () => {
|
||||
localStorage.removeItem("ms_username");
|
||||
router.push('/reset-pwd');
|
||||
};
|
||||
|
||||
const setImage = (e: any) => {
|
||||
const file = e.target.files[0];
|
||||
if (!file.type.includes('image/')) {
|
||||
ElMessage.error('请选择图片文件');
|
||||
return;
|
||||
}
|
||||
// 可选:检查文件大小
|
||||
const maxSize = 5 * 1024 * 1024; // 5MB
|
||||
if (file.size > maxSize) {
|
||||
console.error('文件大小超过限制');
|
||||
return;
|
||||
}
|
||||
const reader = new FileReader();
|
||||
|
|
@ -132,12 +132,147 @@ const setImage = (e: any) => {
|
|||
reader.readAsDataURL(file);
|
||||
};
|
||||
|
||||
const updateUserInfo = async (data: any) => {
|
||||
let result ={}
|
||||
try{
|
||||
let req={};
|
||||
req.token=localStorage.getItem("token");
|
||||
//修改后的数据
|
||||
req.id = data.ID;
|
||||
req.name = data.Name;
|
||||
req.age = data.Age;
|
||||
req.gender = data.Gender;
|
||||
req.password = data.Password;
|
||||
req.email = data.Email;
|
||||
req.avatar = data.Avatar;
|
||||
req.Role = data.Role;
|
||||
result = await updateUserInfoService(req)
|
||||
if (result.code === 0) {
|
||||
ElMessage.success("更新成功");
|
||||
this.updateDialogVisible = false;
|
||||
} else {
|
||||
ElMessage.error("更新失败");
|
||||
}
|
||||
|
||||
}catch(e){
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
const resetPassword = async () =>{
|
||||
let req={
|
||||
old_password: form.old,
|
||||
new_password: form.new1,
|
||||
email: userInfo.value.Email,
|
||||
type:1
|
||||
}
|
||||
try{
|
||||
let result = await genResetPassword(req);
|
||||
if (result.code === 0) {
|
||||
//重置成功,返回新token
|
||||
if (result.data.token) {
|
||||
localStorage.setItem('token', result.data.token);
|
||||
globalData.token = result.data.token;
|
||||
ElMessage.success('重置密码成功');
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(result.msg);
|
||||
}
|
||||
}catch(e){
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//编辑弹窗
|
||||
let options_edit = ref<FormOption>({
|
||||
labelWidth: '100px',
|
||||
span: 12,
|
||||
list: [
|
||||
// {prop: 'Avatar',label: '头像', type: 'input', required: false},
|
||||
{ type: 'input', label: '用户ID', prop: 'ID', required: true,disabled:true },
|
||||
{ type: 'input', label: '用户名', prop: 'Name', required: true },
|
||||
{ type: 'input', label: '年龄', prop: 'Age', required: false },
|
||||
{ type: 'input', label: '密码', prop: 'Password', required: false,disabled:true },
|
||||
{ type: 'input', label: '邮箱', prop: 'Email', required: true,disabled:true },
|
||||
{ type: 'input', label: '性别', prop: 'Gender', required: false },
|
||||
//select 选择框,可选择admin与user两种角色
|
||||
{ type: 'select', label: '角色', prop: 'Role', opts: [{label:"管理员",value:"admin"},{label:"普通用户",value:"user"}], required: false,disabled:true },
|
||||
|
||||
{ type: 'input', label: '注册时间', prop: 'CreatedAt', required: false,disabled:true },
|
||||
{ type: 'input', label: '上次修改时间', prop: 'UpdatedAt', required: false,disabled:true },
|
||||
]
|
||||
})
|
||||
|
||||
const GetMyUserInfo = async () => {
|
||||
let req = {
|
||||
token: localStorage.getItem('token'),
|
||||
id: localStorage.getItem('userId')
|
||||
};
|
||||
try{
|
||||
let result = await GetUserInfoService(req);
|
||||
if (result.code == 0) {
|
||||
avatarImg.value = result.data.Avatar == '' ? avatar : result.data.Avatar;
|
||||
imgSrc.value = avatarImg.value;
|
||||
userInfo.value = result.data;
|
||||
userInfo.value.Password = '**********';
|
||||
}else{
|
||||
ElMessage.error(result.msg);
|
||||
}
|
||||
isUserInfoLoaded.value = true;
|
||||
}catch(e){
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
GetMyUserInfo();
|
||||
|
||||
const cropImage = () => {
|
||||
cropImg.value = cropper.value?.getCroppedCanvas().toDataURL();
|
||||
};
|
||||
|
||||
const saveAvatar = () => {
|
||||
// Data URL 转 File 对象的函数
|
||||
const dataURLtoFile = (dataurl, filename) => {
|
||||
const arr = dataurl.split(',');
|
||||
const mime = arr[0].match(/:(.*?);/)?.[1];
|
||||
const bstr = atob(arr[1]);
|
||||
let n = bstr.length;
|
||||
const u8arr = new Uint8Array(n);
|
||||
while (n--) {
|
||||
u8arr[n] = bstr.charCodeAt(n);
|
||||
}
|
||||
return new File([u8arr], filename, { type: mime });
|
||||
};
|
||||
|
||||
|
||||
const saveAvatar =async () => {
|
||||
let token = localStorage.getItem('token');
|
||||
avatarImg.value = cropImg.value;
|
||||
let formData = new FormData();
|
||||
//文件
|
||||
let file= dataURLtoFile(imgSrc.value, 'avatar.jpg');
|
||||
|
||||
formData.append('file', file);
|
||||
//console.log("add file: " + this.file);
|
||||
formData.append('upload_type', "1");
|
||||
formData.append('md5', "");
|
||||
formData.append('auth_type', "public");
|
||||
//console.log("formData:",formData);
|
||||
|
||||
|
||||
let result = await UploadFileService(formData, token);
|
||||
if (result.code !== 0) {
|
||||
ElMessage.error('上传文件失败,请稍后再试');
|
||||
return;
|
||||
}
|
||||
let resp_data = result.data;
|
||||
|
||||
//console.log("resp:",resp_data);
|
||||
let url = "https://tx.ljsea.top/tool/file/"+resp_data.FileStoreName;
|
||||
|
||||
userInfo.value.Avatar = url;
|
||||
avatarImg.value = url;
|
||||
//更新用户信息
|
||||
await updateUserInfo(userInfo.value);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,253 +0,0 @@
|
|||
<template>
|
||||
<div class="user-container">
|
||||
<el-card class="user-profile mgb20" shadow="hover" :body-style="{ padding: '0px' }">
|
||||
<div class="user-profile-bg"></div>
|
||||
<div class="user-avatar-wrap">
|
||||
<el-avatar class="user-avatar" :size="120" :src="avatarImg" />
|
||||
</div>
|
||||
<div class="user-info">
|
||||
<div class="info-name">{{ name }}</div>
|
||||
<div class="info-desc">
|
||||
<!-- <span>{{ name }}</span>
|
||||
<el-divider direction="vertical" /> -->
|
||||
<span>FE Developer</span>
|
||||
<el-divider direction="vertical" />
|
||||
<el-link href="https://lin-xin.gitee.io" target="_blank">lin-xin.gitee.io</el-link>
|
||||
</div>
|
||||
<!-- <div class="info-icon">
|
||||
<a href="https://github.com/lin-xin" target="_blank"> <i class="el-icon-lx-github-fill"></i></a>
|
||||
<i class="el-icon-lx-qq-fill"></i>
|
||||
<i class="el-icon-lx-facebook-fill"></i>
|
||||
<i class="el-icon-lx-twitter-fill"></i>
|
||||
</div> -->
|
||||
</div>
|
||||
<!-- <div class="user-footer">
|
||||
<div class="user-footer-item">
|
||||
<el-statistic title="Follower" value="18K" />
|
||||
</div>
|
||||
<div class="user-footer-item">
|
||||
<el-statistic title="Following" :value="666" />
|
||||
</div>
|
||||
<div class="user-footer-item">
|
||||
<el-statistic title="Total Post" :value="888" />
|
||||
</div>
|
||||
</div> -->
|
||||
</el-card>
|
||||
<el-card class="user-content" shadow="hover"
|
||||
:body-style="{ padding: '20px 50px', height: '100%', boxSizing: 'border-box' }">
|
||||
<el-tabs v-model="activeName">
|
||||
|
||||
<el-tab-pane name="label1" label="消息通知" class="user-tabpane">
|
||||
<TabsComp />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="label2" label="我的头像" class="user-tabpane">
|
||||
<div class="crop-wrap" v-if="activeName === 'label2'">
|
||||
<vueCropper ref="cropper" :img="imgSrc" :autoCrop="true" :centerBox="true" :full="true"
|
||||
mode="contain">
|
||||
</vueCropper>
|
||||
</div>
|
||||
<el-button class="crop-demo-btn" type="primary">选择图片
|
||||
<input class="crop-input" type="file" name="image" accept="image/*" @change="setImage" />
|
||||
</el-button>
|
||||
<el-button type="success" @click="saveAvatar">上传并保存</el-button>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="label3" label="修改密码" class="user-tabpane">
|
||||
<el-form class="w500" label-position="top">
|
||||
<el-form-item label="旧密码:">
|
||||
<el-input type="password" v-model="form.old"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="新密码:">
|
||||
<el-input type="password" v-model="form.new"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="确认新密码:">
|
||||
<el-input type="password" v-model="form.new1"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="label4" label="赞赏作者" class="user-tabpane">
|
||||
<div class="plugins-tips">
|
||||
如果该框架 <el-link href="https://github.com/lin-xin/vue-manage-system"
|
||||
target="_blank">vue-manage-system</el-link> 对你有帮助,那就请作者喝杯饮料吧!<el-icon>
|
||||
<ColdDrink />
|
||||
</el-icon> 加微信号 linxin_20 探讨问题。
|
||||
</div>
|
||||
<div>
|
||||
<img src="https://lin-xin.gitee.io/images/weixin.jpg" />
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="ucenter">
|
||||
import { reactive, ref } from 'vue';
|
||||
import { VueCropper } from "vue-cropper"
|
||||
import 'vue-cropper/dist/index.css'
|
||||
import avatar from '@/assets/img/img.jpg';
|
||||
import TabsComp from '../element/tabs.vue';
|
||||
|
||||
const name = localStorage.getItem('ms_username');
|
||||
const form = reactive({
|
||||
new1: '',
|
||||
new: '',
|
||||
old: ''
|
||||
});
|
||||
const onSubmit = () => { };
|
||||
|
||||
const activeName = ref('label1');
|
||||
|
||||
const avatarImg = ref(avatar);
|
||||
const imgSrc = ref(avatar);
|
||||
const cropImg = ref('');
|
||||
const cropper: any = ref();
|
||||
|
||||
const setImage = (e: any) => {
|
||||
const file = e.target.files[0];
|
||||
if (!file.type.includes('image/')) {
|
||||
return;
|
||||
}
|
||||
const reader = new FileReader();
|
||||
reader.onload = (event: any) => {
|
||||
imgSrc.value = event.target.result;
|
||||
cropper.value && cropper.value.replace(event.target.result);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
};
|
||||
|
||||
const cropImage = () => {
|
||||
cropImg.value = cropper.value?.getCroppedCanvas().toDataURL();
|
||||
};
|
||||
|
||||
const saveAvatar = () => {
|
||||
avatarImg.value = cropImg.value;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* .user-container {
|
||||
display: flex;
|
||||
} */
|
||||
|
||||
.user-profile-bg {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
background-image: url('../../assets/img/bahnhofsidylle.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.user-profile {
|
||||
position: relative;
|
||||
/* width: 500px; */
|
||||
/* margin-right: 20px; */
|
||||
/* flex: 0 0 auto;
|
||||
align-self: flex-start;
|
||||
} */
|
||||
}
|
||||
|
||||
.user-avatar-wrap {
|
||||
position: absolute;
|
||||
top: 90px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
border: 5px solid #fff;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 7px 12px 0 rgba(62, 57, 107, .16)
|
||||
}
|
||||
|
||||
.user-info {
|
||||
text-align: center;
|
||||
padding: 70px 0 20px;
|
||||
}
|
||||
|
||||
.info-name {
|
||||
margin: 0 0 10px;
|
||||
font-size: 22px;
|
||||
font-weight: 500;
|
||||
color: #373a3c;
|
||||
}
|
||||
|
||||
.info-desc {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.info-desc,
|
||||
.info-desc a {
|
||||
font-size: 18px;
|
||||
color: #55595c;
|
||||
}
|
||||
|
||||
.info-icon {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.info-icon i {
|
||||
font-size: 30px;
|
||||
margin: 0 10px;
|
||||
color: #343434;
|
||||
}
|
||||
|
||||
.user-content {
|
||||
flex: 1
|
||||
}
|
||||
|
||||
.user-tabpane {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
|
||||
.crop-wrap {
|
||||
width: 600px;
|
||||
height: 350px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.crop-demo-btn {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.crop-input {
|
||||
position: absolute;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.w500 {
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
.user-footer {
|
||||
display: flex;
|
||||
border-top: 1px solid rgba(83, 70, 134, 0.1);
|
||||
}
|
||||
|
||||
.user-footer-item {
|
||||
padding: 20px 0;
|
||||
width: 33.3333333333%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.user-footer>div+div {
|
||||
border-left: 1px solid rgba(83, 70, 134, 0.1);
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.el-tabs.el-tabs--left {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -5,14 +5,18 @@
|
|||
<TableCustom :columns="columns" :tableData="tableData" :total="page.total" :viewFunc="handleView"
|
||||
:delFunc="handleDelete" :page-change="changePage" :editFunc="handleEdit">
|
||||
<template #toolbarBtn>
|
||||
<el-button type="warning" :icon="CirclePlusFilled" @click="visible = true">新增</el-button>
|
||||
<el-button type="warning" :icon="CirclePlusFilled" @click="visible_add = true">新增</el-button>
|
||||
</template>
|
||||
</TableCustom>
|
||||
|
||||
</div>
|
||||
<el-dialog :title="isEdit ? '编辑' : '新增'" v-model="visible" width="700px" destroy-on-close
|
||||
<el-dialog :title="isEdit ? '编辑': '编辑'" v-model="visible" width="700px" destroy-on-close
|
||||
:close-on-click-modal="false" @close="closeDialog">
|
||||
<TableEdit :form-data="rowData" :options="options" :edit="isEdit" :update="updateData" />
|
||||
<TableEdit :form-data="rowData" :options="options_edit" :edit="isEdit" :update="updateData" />
|
||||
</el-dialog>
|
||||
<el-dialog :title="isAdd ? '新增' : '新增'" v-model="visible_add" width="700px" destroy-on-close
|
||||
:close-on-click-modal="false" @close="closeDialog">
|
||||
<TableEdit :form-data="rowData" :options="options" :edit="isAdd" :update="addData" />
|
||||
</el-dialog>
|
||||
<el-dialog title="查看详情" v-model="visible1" width="700px" destroy-on-close>
|
||||
<TableDetail :data="viewData"></TableDetail>
|
||||
|
|
@ -24,8 +28,11 @@
|
|||
import { ref, reactive } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { CirclePlusFilled } from '@element-plus/icons-vue';
|
||||
import { User } from '@/types/user';
|
||||
import { UserInfo } from '@/types/user';
|
||||
import { fetchUserData } from '@/api';
|
||||
import { SearchUserService } from "@/api/user";
|
||||
import {GetUserInfoService} from "@/api/user";
|
||||
import {updateUserInfoService} from "@/api/user";
|
||||
import TableCustom from '@/components/table-custom.vue';
|
||||
import TableDetail from '@/components/table-detail.vue';
|
||||
import TableSearch from '@/components/table-search.vue';
|
||||
|
|
@ -36,30 +43,59 @@ const query = reactive({
|
|||
name: '',
|
||||
});
|
||||
const searchOpt = ref<FormOptionList[]>([
|
||||
{ type: 'input', label: '用户名:', prop: 'name' }
|
||||
{ type: 'input', label: '用户名或ID:', prop: 'name' }
|
||||
])
|
||||
const handleSearch = () => {
|
||||
changePage(1);
|
||||
const handleSearch = async () => {
|
||||
let search_id= -1;
|
||||
let keyword_ = "";
|
||||
//判断search_id是字符串还是数字
|
||||
if(isNaN(query.name)){
|
||||
//是字符串,说明是关键字
|
||||
keyword_ = query.name;
|
||||
}else if(isFinite(query.name)){
|
||||
//是数字,说明是ID
|
||||
search_id = parseInt(query.name);
|
||||
}else{
|
||||
//不是数字也不是字符串
|
||||
ElMessage.error("输入错误,请输入数字或者关键字");
|
||||
return;
|
||||
}
|
||||
let req={
|
||||
token: localStorage.getItem('token'),
|
||||
id: search_id,
|
||||
keyword: keyword_,
|
||||
}
|
||||
let result = await SearchUserService(req);
|
||||
tableData.value = result.data;
|
||||
page.total = result.data.length;
|
||||
};
|
||||
|
||||
// 表格相关
|
||||
let columns = ref([
|
||||
{ type: 'index', label: '序号', width: 55, align: 'center' },
|
||||
{ prop: 'name', label: '用户名' },
|
||||
{ prop: 'phone', label: '手机号' },
|
||||
{ prop: 'role', label: '角色' },
|
||||
{ prop: 'ID', label: '用户ID' },
|
||||
{ prop: 'Name', label: '用户名' },
|
||||
{ prop: 'Age', label: '年龄'},
|
||||
{ prop: 'Role', label: '角色' },
|
||||
{ prop: 'CreatedAt', label: '创建时间',type: 'date' },
|
||||
{ prop: 'Email', label: '邮箱' },
|
||||
{ prop: 'operator', label: '操作', width: 250 },
|
||||
])
|
||||
const page = reactive({
|
||||
index: 1,
|
||||
size: 10,
|
||||
total: 0,
|
||||
total: 122,
|
||||
})
|
||||
const tableData = ref<User[]>([]);
|
||||
const tableData = ref<UserInfo[]>([]);
|
||||
const getData = async () => {
|
||||
const res = await fetchUserData()
|
||||
tableData.value = res.data.list;
|
||||
page.total = res.data.pageTotal;
|
||||
let req={
|
||||
token: localStorage.getItem('token'),
|
||||
id: -1,
|
||||
keyword: "_121",
|
||||
}
|
||||
let result = await SearchUserService(req);
|
||||
tableData.value = result.data;
|
||||
page.total = result.data.length;
|
||||
};
|
||||
getData();
|
||||
|
||||
|
|
@ -68,33 +104,100 @@ const changePage = (val: number) => {
|
|||
getData();
|
||||
};
|
||||
|
||||
// 新增/编辑弹窗相关
|
||||
// 新增弹窗
|
||||
let options = ref<FormOption>({
|
||||
labelWidth: '100px',
|
||||
span: 12,
|
||||
list: [
|
||||
{ type: 'input', label: '用户名', prop: 'name', required: true },
|
||||
{ type: 'input', label: '手机号', prop: 'phone', required: true },
|
||||
{ type: 'input', label: '密码', prop: 'password', required: true },
|
||||
{ type: 'input', label: '邮箱', prop: 'email', required: true },
|
||||
{ type: 'input', label: '角色', prop: 'role', required: true },
|
||||
{ type: 'input', label: '用户名', prop: 'Name', required: true },
|
||||
{ type: 'input', label: '密码', prop: 'Password', required: true },
|
||||
{ type: 'input', label: '邮箱', prop: 'Email', required: true },
|
||||
{ type: 'input', label: '角色', prop: 'Role', required: true },
|
||||
]
|
||||
})
|
||||
|
||||
//编辑弹窗
|
||||
let options_edit = ref<FormOption>({
|
||||
labelWidth: '100px',
|
||||
span: 12,
|
||||
list: [
|
||||
{prop: 'Avatar',label: '头像', type: 'input', required: false},
|
||||
{ type: 'input', label: '用户名', prop: 'Name', required: true },
|
||||
{ type: 'input', label: '年龄', prop: 'Age', required: false },
|
||||
{ type: 'input', label: '密码', prop: 'Password', required: false },
|
||||
{ type: 'input', label: '邮箱', prop: 'Email', required: true },
|
||||
{ type: 'input', label: '性别', prop: 'Gender', required: false },
|
||||
//select 选择框,可选择admin与user两种角色
|
||||
{ type: 'select', label: '角色', prop: 'Role', opts: [{label:"管理员",value:"admin"},{label:"普通用户",value:"user"}],required: false },
|
||||
|
||||
]
|
||||
})
|
||||
|
||||
const visible = ref(false);
|
||||
const visible_add = ref(false);
|
||||
const isEdit = ref(false);
|
||||
const isAdd = ref(false);
|
||||
const rowData = ref({});
|
||||
const handleEdit = (row: User) => {
|
||||
rowData.value = { ...row };
|
||||
const handleEdit = async (row: UserInfo) => {
|
||||
let data = await getUserInfo(row.ID);
|
||||
|
||||
rowData.value = data;
|
||||
isEdit.value = true;
|
||||
visible.value = true;
|
||||
};
|
||||
const updateData = () => {
|
||||
const updateData = async (data) => {
|
||||
let result ={}
|
||||
try{
|
||||
let req={};
|
||||
req.token=localStorage.getItem("token");
|
||||
//console.log(rowData.value);
|
||||
|
||||
//修改后的数据
|
||||
req.id = data.ID;
|
||||
req.name = data.Name;
|
||||
req.age = data.Age;
|
||||
req.gender = data.Gender;
|
||||
req.password = data.Password;
|
||||
req.email = data.Email;
|
||||
req.avatar = data.Avatar;
|
||||
req.Role = data.Role;
|
||||
|
||||
result = await updateUserInfoService(req)
|
||||
if (result.code === 0) {
|
||||
ElMessage.success("更新成功");
|
||||
this.updateDialogVisible = false;
|
||||
} else {
|
||||
ElMessage.error("更新失败");
|
||||
}
|
||||
|
||||
}catch(e){
|
||||
console.log(e);
|
||||
}
|
||||
closeDialog();
|
||||
getData();
|
||||
handleSearch();
|
||||
};
|
||||
|
||||
const getUserInfo = async (id) => {
|
||||
let result = {};
|
||||
try{
|
||||
//获取用户信息
|
||||
let req={
|
||||
token: localStorage.getItem('token'),
|
||||
id: id,
|
||||
};
|
||||
result = await GetUserInfoService(req)
|
||||
if(result.code===0){
|
||||
return result.data;
|
||||
}
|
||||
}catch(e){
|
||||
console.log(e);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
const closeDialog = () => {
|
||||
visible.value = false;
|
||||
visible_add.value = false;
|
||||
isEdit.value = false;
|
||||
};
|
||||
|
||||
|
|
@ -104,43 +207,47 @@ const viewData = ref({
|
|||
row: {},
|
||||
list: []
|
||||
});
|
||||
const handleView = (row: User) => {
|
||||
viewData.value.row = { ...row }
|
||||
const handleView =async (row: UserInfo) => {
|
||||
let data = await getUserInfo(row.ID);
|
||||
viewData.value.row = data;
|
||||
viewData.value.list = [
|
||||
{
|
||||
prop: 'id',
|
||||
prop: 'Avatar',
|
||||
label: '头像', //显示头像
|
||||
type: 'image',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
prop: 'ID',
|
||||
label: '用户ID',
|
||||
},
|
||||
{
|
||||
prop: 'name',
|
||||
prop: 'Name',
|
||||
label: '用户名',
|
||||
},
|
||||
{
|
||||
prop: 'password',
|
||||
label: '密码',
|
||||
},
|
||||
{
|
||||
prop: 'email',
|
||||
prop: 'Email',
|
||||
label: '邮箱',
|
||||
},
|
||||
{
|
||||
prop: 'phone',
|
||||
label: '电话',
|
||||
prop: 'Gender',
|
||||
label: '性别',
|
||||
},
|
||||
{
|
||||
prop: 'role',
|
||||
prop: 'Role',
|
||||
label: '角色',
|
||||
},
|
||||
{
|
||||
prop: 'date',
|
||||
prop: 'CreatedAt',
|
||||
label: '注册日期',
|
||||
type: 'date',
|
||||
},
|
||||
]
|
||||
visible1.value = true;
|
||||
};
|
||||
|
||||
// 删除相关
|
||||
const handleDelete = (row: User) => {
|
||||
const handleDelete = (row: UserInfo) => {
|
||||
ElMessage.success('删除成功');
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
121
yarn.lock
121
yarn.lock
|
|
@ -19,6 +19,105 @@
|
|||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@cropper/element-canvas@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/@cropper/element-canvas/-/element-canvas-2.0.0.tgz"
|
||||
integrity sha512-GPtGJgSm92crJhhhwUsaMw3rz2KfJWWSz7kRAlufFEV/EHTP5+6r6/Z1BCGRna830i+Avqbm435XLOtA7PVJwA==
|
||||
dependencies:
|
||||
"@cropper/element" "^2.0.0"
|
||||
"@cropper/utils" "^2.0.0"
|
||||
|
||||
"@cropper/element-crosshair@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/@cropper/element-crosshair/-/element-crosshair-2.0.0.tgz"
|
||||
integrity sha512-KfPfyrdeFvUC31Ws7ATtcalWWSaMtrC6bMoCipZhqbUOE7wZoL4ecDSL6BUOZxPa74awZUqfzirCDjHvheBfyw==
|
||||
dependencies:
|
||||
"@cropper/element" "^2.0.0"
|
||||
"@cropper/utils" "^2.0.0"
|
||||
|
||||
"@cropper/element-grid@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/@cropper/element-grid/-/element-grid-2.0.0.tgz"
|
||||
integrity sha512-i78SQ0IJTLFveKX6P7svkfMYVdgHrQ8ZmmEw8keFy9n1ZVbK+SK0UHK5FNMRNI/gtVhKJOGEnK/zeyjUdj4Iyw==
|
||||
dependencies:
|
||||
"@cropper/element" "^2.0.0"
|
||||
"@cropper/utils" "^2.0.0"
|
||||
|
||||
"@cropper/element-handle@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/@cropper/element-handle/-/element-handle-2.0.0.tgz"
|
||||
integrity sha512-ZJvW+0MkK9E8xYymGdoruaQn2kwjSHFpNSWinjyq6csuVQiCPxlX5ovAEDldmZ9MWePPtWEi3vLKQOo2Yb0T8g==
|
||||
dependencies:
|
||||
"@cropper/element" "^2.0.0"
|
||||
"@cropper/utils" "^2.0.0"
|
||||
|
||||
"@cropper/element-image@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/@cropper/element-image/-/element-image-2.0.0.tgz"
|
||||
integrity sha512-9BxiTS/aHRmrjopaFQb9mQQXmx4ruhYHGkDZMVz24AXpMFjUY6OpqrWse/WjzD9tfhMFvEdu17b3VAekcAgpeg==
|
||||
dependencies:
|
||||
"@cropper/element" "^2.0.0"
|
||||
"@cropper/element-canvas" "^2.0.0"
|
||||
"@cropper/utils" "^2.0.0"
|
||||
|
||||
"@cropper/element-selection@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/@cropper/element-selection/-/element-selection-2.0.0.tgz"
|
||||
integrity sha512-ensNnbIfJsJ8bhbJTH/RXtk2URFvTOO4TvfRk461n2FPEC588D7rwBmUJxQg74IiTi4y1JbCI+6j+4LyzYBLCQ==
|
||||
dependencies:
|
||||
"@cropper/element" "^2.0.0"
|
||||
"@cropper/element-canvas" "^2.0.0"
|
||||
"@cropper/element-image" "^2.0.0"
|
||||
"@cropper/utils" "^2.0.0"
|
||||
|
||||
"@cropper/element-shade@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/@cropper/element-shade/-/element-shade-2.0.0.tgz"
|
||||
integrity sha512-jv/2bbNZnhU4W+T4G0c8ADocLIZvQFTXgCf2RFDNhI5UVxurzWBnDdb8Mx8LnVplnkTqO+xUmHZYve0CwgWo+Q==
|
||||
dependencies:
|
||||
"@cropper/element" "^2.0.0"
|
||||
"@cropper/element-canvas" "^2.0.0"
|
||||
"@cropper/element-selection" "^2.0.0"
|
||||
"@cropper/utils" "^2.0.0"
|
||||
|
||||
"@cropper/element-viewer@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/@cropper/element-viewer/-/element-viewer-2.0.0.tgz"
|
||||
integrity sha512-zY+3VRN5TvpM8twlphYtXw0tzJL2VgzeK7ufhL1BixVqOdRxwP13TprYIhqwGt9EW/SyJZUiaIu396T89kRX8A==
|
||||
dependencies:
|
||||
"@cropper/element" "^2.0.0"
|
||||
"@cropper/element-canvas" "^2.0.0"
|
||||
"@cropper/element-image" "^2.0.0"
|
||||
"@cropper/element-selection" "^2.0.0"
|
||||
"@cropper/utils" "^2.0.0"
|
||||
|
||||
"@cropper/element@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/@cropper/element/-/element-2.0.0.tgz"
|
||||
integrity sha512-lsthn0nQq73GExUE7Mg/ss6Q3RXADGDv055hxoLFwvl/wGHgy6ZkYlfLZ/VmgBHC6jDK5IgPBFnqrPqlXWSGBA==
|
||||
dependencies:
|
||||
"@cropper/utils" "^2.0.0"
|
||||
|
||||
"@cropper/elements@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/@cropper/elements/-/elements-2.0.0.tgz"
|
||||
integrity sha512-PQkPo1nUjxLFUQuHYu+6atfHxpX9B41Xribao6wpvmvmNIFML6LQdNqqWYb6LyM7ujsu71CZdBiMT5oetjJVoQ==
|
||||
dependencies:
|
||||
"@cropper/element" "^2.0.0"
|
||||
"@cropper/element-canvas" "^2.0.0"
|
||||
"@cropper/element-crosshair" "^2.0.0"
|
||||
"@cropper/element-grid" "^2.0.0"
|
||||
"@cropper/element-handle" "^2.0.0"
|
||||
"@cropper/element-image" "^2.0.0"
|
||||
"@cropper/element-selection" "^2.0.0"
|
||||
"@cropper/element-shade" "^2.0.0"
|
||||
"@cropper/element-viewer" "^2.0.0"
|
||||
|
||||
"@cropper/utils@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/@cropper/utils/-/utils-2.0.0.tgz"
|
||||
integrity sha512-cprLYr+7kK3faGgoOsTW9gIn5sefDr2KwOmgyjzIXk+8PLpW8FgFKEg5FoWfRD5zMAmkCBuX6rGKDK3VdUEGrg==
|
||||
|
||||
"@ctrl/tinycolor@^3.4.1":
|
||||
version "3.6.1"
|
||||
resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz"
|
||||
|
|
@ -498,6 +597,19 @@ crc-32@~1.2.0, crc-32@~1.2.1:
|
|||
resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz"
|
||||
integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==
|
||||
|
||||
cropperjs@^1.5.6:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.npmjs.org/cropperjs/-/cropperjs-1.6.2.tgz"
|
||||
integrity sha512-nhymn9GdnV3CqiEHJVai54TULFAE3VshJTXSqSJKa8yXAKyBKDWdhHarnlIPrshJ0WMFTGuFvG02YjLXfPiuOA==
|
||||
|
||||
cropperjs@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/cropperjs/-/cropperjs-2.0.0.tgz"
|
||||
integrity sha512-TO2j0Qre01kPHbow4FuTrbdEB4jTmGRySxW49jyEIqlJZuEBfrvCTT0vC3eRB2WBXudDfKi1Onako6DKWKxeAQ==
|
||||
dependencies:
|
||||
"@cropper/elements" "^2.0.0"
|
||||
"@cropper/utils" "^2.0.0"
|
||||
|
||||
csstype@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
|
||||
|
|
@ -1282,6 +1394,13 @@ vue-cropper@1.1.1:
|
|||
resolved "https://registry.npmjs.org/vue-cropper/-/vue-cropper-1.1.1.tgz"
|
||||
integrity sha512-WsqKMpaBf9Osi1LQlE/5AKdD0nHWOy1asLXocaG8NomOWO07jiZi968+/PbMmnD0QbPJOumDQaGuGa13qys85A==
|
||||
|
||||
vue-cropperjs@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.npmjs.org/vue-cropperjs/-/vue-cropperjs-5.0.0.tgz"
|
||||
integrity sha512-RhnC8O33uRZNkn74aiHZwNHnBJOXWlS4P6gsRI0lw4cZlWjKSCywZI9oSI9POlIPI6OYv30jvnHMXGch85tw7w==
|
||||
dependencies:
|
||||
cropperjs "^1.5.6"
|
||||
|
||||
vue-demi@*:
|
||||
version "0.14.7"
|
||||
resolved "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz"
|
||||
|
|
@ -1326,7 +1445,7 @@ vue-tsc@^0.38.4:
|
|||
dependencies:
|
||||
"@volar/vue-typescript" "0.38.9"
|
||||
|
||||
"vue@^2.6.12 || ^3.1.1", "vue@^2.6.14 || ^3.3.0", "vue@^3.0.0-0 || ^2.6.0", vue@^3.0.5, vue@^3.2.0, vue@^3.2.25, vue@^3.2.47, vue@^3.4.5, "vue@2 || 3", vue@3.4.21:
|
||||
"vue@^2.6.12 || ^3.1.1", "vue@^2.6.14 || ^3.3.0", "vue@^3.0.0-0 || ^2.6.0", vue@^3.0.5, vue@^3.2.0, vue@^3.2.25, vue@^3.2.47, vue@^3.4.5, vue@>=3.0.0, "vue@2 || 3", vue@3.4.21:
|
||||
version "3.4.21"
|
||||
resolved "https://registry.npmjs.org/vue/-/vue-3.4.21.tgz"
|
||||
integrity sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==
|
||||
|
|
|
|||
Loading…
Reference in New Issue