parent
f70c93715b
commit
c8cae1b200
|
@ -15,6 +15,8 @@ declare module '@vue/runtime-core' {
|
||||||
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
|
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
|
||||||
ElCol: typeof import('element-plus/es')['ElCol']
|
ElCol: typeof import('element-plus/es')['ElCol']
|
||||||
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
||||||
|
ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
|
||||||
|
ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
|
||||||
ElDialog: typeof import('element-plus/es')['ElDialog']
|
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||||
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
||||||
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
||||||
|
@ -48,6 +50,8 @@ declare module '@vue/runtime-core' {
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
Sidebar: typeof import('./src/components/sidebar.vue')['default']
|
Sidebar: typeof import('./src/components/sidebar.vue')['default']
|
||||||
|
TableDetail: typeof import('./src/components/table-detail.vue')['default']
|
||||||
|
TableEdit: typeof import('./src/components/table-edit.vue')['default']
|
||||||
Tags: typeof import('./src/components/tags.vue')['default']
|
Tags: typeof import('./src/components/tags.vue')['default']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
<title>vue-manage-system</title>
|
<title>vue-manage-system后台管理系统</title>
|
||||||
<link rel="stylesheet" href="https://at.alicdn.com/t/font_830376_qzecyukz0s.css">
|
<link rel="stylesheet" href="https://at.alicdn.com/t/font_830376_qzecyukz0s.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
20
package.json
20
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "vue-manage-system",
|
"name": "vue-manage-system",
|
||||||
"version": "5.3.0",
|
"version": "5.3.5",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
@ -8,16 +8,18 @@
|
||||||
"serve": "vite preview"
|
"serve": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@element-plus/icons-vue": "^2.0.9",
|
"@element-plus/icons-vue": "*",
|
||||||
"axios": "^0.27.2",
|
"@wangeditor/editor": "^5.1.23",
|
||||||
"element-plus": "^2.2.14",
|
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||||
"md-editor-v3": "^2.2.1",
|
"axios": "^1.6.3",
|
||||||
"pinia": "^2.0.20",
|
"element-plus": "^2.4.4",
|
||||||
"vue": "^3.2.37",
|
"md-editor-v3": "^2.11.2",
|
||||||
|
"nprogress": "^0.2.0",
|
||||||
|
"pinia": "^2.1.7",
|
||||||
|
"vue": "^3.3.0",
|
||||||
"vue-cropperjs": "^5.0.0",
|
"vue-cropperjs": "^5.0.0",
|
||||||
"vue-router": "^4.1.3",
|
"vue-router": "^4.2.5",
|
||||||
"vue-schart": "^2.0.0",
|
"vue-schart": "^2.0.0",
|
||||||
"wangeditor": "^4.7.15",
|
|
||||||
"xlsx": "^0.18.5"
|
"xlsx": "^0.18.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -10,5 +10,5 @@ import zhCn from 'element-plus/es/locale/lang/zh-cn';
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
@import './assets/css/main.css';
|
@import './assets/css/main.css';
|
||||||
@import './assets/css/color-dark.css';
|
@import './assets/css/color-dark.scss';
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -2,7 +2,7 @@ import request from '../utils/request';
|
||||||
|
|
||||||
export const fetchData = () => {
|
export const fetchData = () => {
|
||||||
return request({
|
return request({
|
||||||
url: './table.json',
|
url: 'https://www.fastmock.site/mock/dc695d037038802def4b989ba4650c3f/vms/getUser',
|
||||||
method: 'get'
|
method: 'post'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,15 +8,15 @@
|
||||||
background: #eef1f6;
|
background: #eef1f6;
|
||||||
}
|
}
|
||||||
.plugins-tips a{
|
.plugins-tips a{
|
||||||
color: #20a0ff;
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tags-li.active {
|
.tags-li.active {
|
||||||
border: 1px solid #409EFF;
|
border: 1px solid var(--el-color-primary);
|
||||||
background-color: #409EFF;
|
background-color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.message-title{
|
.message-title{
|
||||||
color: #20a0ff;
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.collapse-btn:hover{
|
.collapse-btn:hover{
|
||||||
background: rgb(40,52,70);
|
background: rgb(40,52,70);
|
|
@ -74,10 +74,6 @@ a {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-table tr:hover {
|
|
||||||
background: #f6faff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mgb20 {
|
.mgb20 {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
@ -113,7 +109,6 @@ a {
|
||||||
|
|
||||||
|
|
||||||
[class*=" el-icon-"], [class^=el-icon-] {
|
[class*=" el-icon-"], [class^=el-icon-] {
|
||||||
speak: none;
|
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-variant: normal;
|
font-variant: normal;
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
<template>
|
||||||
|
<el-descriptions title="" :column="2" border>
|
||||||
|
<el-descriptions-item>
|
||||||
|
<template #label> 用户ID </template>
|
||||||
|
{{ data.id }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item>
|
||||||
|
<template #label> 用户名 </template>
|
||||||
|
{{ data.name }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item>
|
||||||
|
<template #label> 账户余额 </template>
|
||||||
|
{{ data.money }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item>
|
||||||
|
<template #label> 账户状态 </template>
|
||||||
|
{{ data.state ? '正常' : '异常' }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :span="2">
|
||||||
|
<template #label> 地址 </template>
|
||||||
|
{{ data.address }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item>
|
||||||
|
<template #label> 日期 </template>
|
||||||
|
{{ data.date }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item>
|
||||||
|
<template #label> 头像 </template>
|
||||||
|
<img :src="data.thumb" style="width: 120px" alt="" />
|
||||||
|
</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,123 @@
|
||||||
|
<template>
|
||||||
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
|
||||||
|
<el-form-item label="用户名" prop="name">
|
||||||
|
<el-input v-model="form.name"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="账户余额" prop="money">
|
||||||
|
<el-input v-model.number="form.money"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="地址" prop="address">
|
||||||
|
<el-input v-model="form.address"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="账户状态" prop="state">
|
||||||
|
<el-switch
|
||||||
|
v-model="form.state"
|
||||||
|
:active-value="1"
|
||||||
|
:inactive-value="0"
|
||||||
|
active-text="正常"
|
||||||
|
inactive-text="异常"
|
||||||
|
></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="注册日期" prop="date">
|
||||||
|
<el-date-picker type="date" v-model="form.date" value-format="YYYY-MM-DD"></el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="上传头像" prop="thumb">
|
||||||
|
<el-upload
|
||||||
|
class="avatar-uploader"
|
||||||
|
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
|
||||||
|
:show-file-list="false"
|
||||||
|
:on-success="handleAvatarSuccess"
|
||||||
|
:before-upload="beforeAvatarUpload"
|
||||||
|
>
|
||||||
|
<img v-if="form.thumb" :src="form.thumb" class="avatar" />
|
||||||
|
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
|
||||||
|
</el-upload>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="saveEdit(formRef)">保 存</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ElMessage, FormInstance, FormRules, UploadProps } from 'element-plus';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
edit: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
type: Function,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const defaultData = {
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
address: '',
|
||||||
|
thumb: '',
|
||||||
|
money: 0,
|
||||||
|
state: 0,
|
||||||
|
date: new Date()
|
||||||
|
};
|
||||||
|
|
||||||
|
const form = ref({ ...(props.edit ? props.data : defaultData) });
|
||||||
|
|
||||||
|
const rules: FormRules = {
|
||||||
|
name: [{ required: true, message: '用户名', trigger: 'blur' }]
|
||||||
|
};
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
const saveEdit = (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return;
|
||||||
|
formEl.validate(valid => {
|
||||||
|
if (!valid) return false;
|
||||||
|
props.update(form.value);
|
||||||
|
ElMessage.success('保存成功!');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
|
||||||
|
form.value.thumb = URL.createObjectURL(uploadFile.raw!);
|
||||||
|
};
|
||||||
|
|
||||||
|
const beforeAvatarUpload: UploadProps['beforeUpload'] = rawFile => {
|
||||||
|
if (rawFile.type !== 'image/jpeg') {
|
||||||
|
ElMessage.error('Avatar picture must be JPG format!');
|
||||||
|
return false;
|
||||||
|
} else if (rawFile.size / 1024 / 1024 > 2) {
|
||||||
|
ElMessage.error('Avatar picture size can not exceed 2MB!');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.avatar-uploader .el-upload {
|
||||||
|
border: 1px dashed var(--el-border-color);
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: var(--el-transition-duration-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar-uploader .el-upload:hover {
|
||||||
|
border-color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon.avatar-uploader-icon {
|
||||||
|
font-size: 28px;
|
||||||
|
color: #8c939d;
|
||||||
|
width: 178px;
|
||||||
|
height: 178px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,6 +1,8 @@
|
||||||
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
|
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
|
||||||
import { usePermissStore } from '../store/permiss';
|
import { usePermissStore } from '../store/permiss';
|
||||||
import Home from '../views/home.vue';
|
import Home from '../views/home.vue';
|
||||||
|
import NProgress from 'nprogress'
|
||||||
|
import 'nprogress/nprogress.css'
|
||||||
|
|
||||||
const routes: RouteRecordRaw[] = [
|
const routes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
|
@ -163,7 +165,7 @@ const router = createRouter({
|
||||||
});
|
});
|
||||||
|
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
document.title = `${to.meta.title} | vue-manage-system`;
|
NProgress.start();
|
||||||
const role = localStorage.getItem('ms_username');
|
const role = localStorage.getItem('ms_username');
|
||||||
const permiss = usePermissStore();
|
const permiss = usePermissStore();
|
||||||
if (!role && to.path !== '/login') {
|
if (!role && to.path !== '/login') {
|
||||||
|
@ -176,4 +178,8 @@ router.beforeEach((to, from, next) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.afterEach(() => {
|
||||||
|
NProgress.done()
|
||||||
|
})
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import axios, {AxiosInstance, AxiosError, AxiosResponse, AxiosRequestConfig} from 'axios';
|
import axios, { AxiosInstance, AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios';
|
||||||
|
|
||||||
const service:AxiosInstance = axios.create({
|
const service: AxiosInstance = axios.create({
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
});
|
});
|
||||||
|
|
||||||
service.interceptors.request.use(
|
service.interceptors.request.use(
|
||||||
(config: AxiosRequestConfig) => {
|
(config: InternalAxiosRequestConfig) => {
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
(error: AxiosError) => {
|
(error: AxiosError) => {
|
||||||
|
|
|
@ -4,33 +4,51 @@
|
||||||
wangEditor:轻量级 web 富文本编辑器,配置方便,使用简单。 访问地址:
|
wangEditor:轻量级 web 富文本编辑器,配置方便,使用简单。 访问地址:
|
||||||
<a href="https://www.wangeditor.com/doc/" target="_blank">wangEditor</a>
|
<a href="https://www.wangeditor.com/doc/" target="_blank">wangEditor</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="mgb20" ref="editor"></div>
|
<div style="border: 1px solid #ccc; margin-bottom: 10px">
|
||||||
|
<Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :defaultConfig="toolbarConfig" />
|
||||||
|
<Editor
|
||||||
|
style="height: 500px; overflow-y: hidden"
|
||||||
|
v-model="valueHtml"
|
||||||
|
:defaultConfig="editorConfig"
|
||||||
|
@onCreated="handleCreated"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<el-button type="primary" @click="syncHTML">提交</el-button>
|
<el-button type="primary" @click="syncHTML">提交</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts" name="editor">
|
<script setup lang="ts" name="editor">
|
||||||
import WangEditor from 'wangeditor';
|
import '@wangeditor/editor/dist/css/style.css'; // 引入 css
|
||||||
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
|
import { onBeforeUnmount, ref, reactive, shallowRef, onMounted } from 'vue';
|
||||||
|
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
|
||||||
|
// 编辑器实例,必须用 shallowRef
|
||||||
|
const editorRef = shallowRef();
|
||||||
|
|
||||||
const editor = ref(null);
|
// 内容 HTML
|
||||||
const content = reactive({
|
const valueHtml = ref('<p>hello</p>');
|
||||||
html: '',
|
|
||||||
text: ''
|
// 模拟 ajax 异步获取内容
|
||||||
});
|
|
||||||
let instance: any;
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
instance = new WangEditor(editor.value);
|
setTimeout(() => {
|
||||||
instance.config.zIndex = 1;
|
valueHtml.value = '<p>模拟 Ajax 异步设置内容</p>';
|
||||||
instance.create();
|
}, 1500);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const toolbarConfig = {};
|
||||||
|
const editorConfig = { placeholder: '请输入内容...' };
|
||||||
|
|
||||||
|
// 组件销毁时,也及时销毁编辑器
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
instance.destroy();
|
const editor = editorRef.value;
|
||||||
instance = null;
|
if (editor == null) return;
|
||||||
|
editor.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const handleCreated = (editor: any) => {
|
||||||
|
editorRef.value = editor; // 记录 editor 实例,重要!
|
||||||
|
};
|
||||||
const syncHTML = () => {
|
const syncHTML = () => {
|
||||||
content.html = instance.txt.html();
|
console.log(valueHtml.value);
|
||||||
console.log(content.html);
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
<div class="login-btn">
|
<div class="login-btn">
|
||||||
<el-button type="primary" @click="submitForm(login)">登录</el-button>
|
<el-button type="primary" @click="submitForm(login)">登录</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
<el-checkbox class="login-tips" v-model="checked" label="记住密码" size="large" />
|
||||||
<p class="login-tips">Tips : 用户名和密码随便填。</p>
|
<p class="login-tips">Tips : 用户名和密码随便填。</p>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -45,10 +46,14 @@ interface LoginInfo {
|
||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lgStr = localStorage.getItem('login-param');
|
||||||
|
const defParam = lgStr ? JSON.parse(lgStr) : null;
|
||||||
|
const checked = ref(lgStr ? true : false);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const param = reactive<LoginInfo>({
|
const param = reactive<LoginInfo>({
|
||||||
username: 'admin',
|
username: defParam ? defParam.username : '',
|
||||||
password: '123123'
|
password: defParam ? defParam.password : '',
|
||||||
});
|
});
|
||||||
|
|
||||||
const rules: FormRules = {
|
const rules: FormRules = {
|
||||||
|
@ -56,10 +61,10 @@ const rules: FormRules = {
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入用户名',
|
message: '请输入用户名',
|
||||||
trigger: 'blur'
|
trigger: 'blur',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
|
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
|
||||||
};
|
};
|
||||||
const permiss = usePermissStore();
|
const permiss = usePermissStore();
|
||||||
const login = ref<FormInstance>();
|
const login = ref<FormInstance>();
|
||||||
|
@ -73,8 +78,13 @@ const submitForm = (formEl: FormInstance | undefined) => {
|
||||||
permiss.handleSet(keys);
|
permiss.handleSet(keys);
|
||||||
localStorage.setItem('ms_keys', JSON.stringify(keys));
|
localStorage.setItem('ms_keys', JSON.stringify(keys));
|
||||||
router.push('/');
|
router.push('/');
|
||||||
|
if (checked.value) {
|
||||||
|
localStorage.setItem('login-param', JSON.stringify(param));
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error('登录成功');
|
localStorage.removeItem('login-param');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ElMessage.error('登录失败');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -86,32 +96,29 @@ tags.clearTags();
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.login-wrap {
|
.login-wrap {
|
||||||
position: relative;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-image: url(../assets/img/login-bg.jpg);
|
background-image: url(../assets/img/login-bg.jpg);
|
||||||
background-size: 100%;
|
background-size: 100%;
|
||||||
}
|
}
|
||||||
.ms-title {
|
.ms-title {
|
||||||
width: 100%;
|
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
color: #fff;
|
color: #333;
|
||||||
border-bottom: 1px solid #ddd;
|
font-weight: bold;
|
||||||
|
padding-top: 10px;
|
||||||
}
|
}
|
||||||
.ms-login {
|
.ms-login {
|
||||||
position: absolute;
|
|
||||||
left: 50%;
|
|
||||||
top: 50%;
|
|
||||||
width: 350px;
|
width: 350px;
|
||||||
margin: -190px 0 0 -175px;
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background: rgba(255, 255, 255, 0.3);
|
background: #fff;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
.ms-content {
|
.ms-content {
|
||||||
padding: 30px 30px;
|
padding: 10px 30px 30px;
|
||||||
}
|
}
|
||||||
.login-btn {
|
.login-btn {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -124,6 +131,6 @@ tags.clearTags();
|
||||||
.login-tips {
|
.login-tips {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
color: #fff;
|
color: #333;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,19 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="handle-box">
|
<div class="search-box">
|
||||||
<el-select v-model="query.address" placeholder="地址" class="handle-select mr10">
|
<el-input v-model="query.name" placeholder="用户名" class="search-input mr10" clearable></el-input>
|
||||||
<el-option key="1" label="广东省" value="广东省"></el-option>
|
|
||||||
<el-option key="2" label="湖南省" value="湖南省"></el-option>
|
|
||||||
</el-select>
|
|
||||||
<el-input v-model="query.name" placeholder="用户名" class="handle-input mr10"></el-input>
|
|
||||||
<el-button type="primary" :icon="Search" @click="handleSearch">搜索</el-button>
|
<el-button type="primary" :icon="Search" @click="handleSearch">搜索</el-button>
|
||||||
<el-button type="primary" :icon="Plus">新增</el-button>
|
<el-button type="warning" :icon="CirclePlusFilled" @click="visible = true">新增</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="tableData" border class="table" ref="multipleTable" header-cell-class-name="table-header">
|
<el-table :data="tableData" border class="table" ref="multipleTable" header-cell-class-name="table-header">
|
||||||
<el-table-column prop="id" label="ID" width="55" align="center"></el-table-column>
|
<el-table-column prop="id" label="ID" width="55" align="center"></el-table-column>
|
||||||
<el-table-column prop="name" label="用户名"></el-table-column>
|
<el-table-column prop="name" label="用户名" align="center"></el-table-column>
|
||||||
<el-table-column label="账户余额">
|
<el-table-column label="账户余额" align="center">
|
||||||
<template #default="scope">¥{{ scope.row.money }}</template>
|
<template #default="scope">¥{{ scope.row.money }}</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="头像(查看大图)" align="center">
|
<el-table-column label="头像(查看大图)" align="center">
|
||||||
|
@ -28,24 +24,37 @@
|
||||||
</el-image>
|
</el-image>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="address" label="地址"></el-table-column>
|
<el-table-column prop="address" label="地址" align="center"></el-table-column>
|
||||||
<el-table-column label="状态" align="center">
|
<el-table-column label="账户状态" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag
|
<el-tag :type="scope.row.state ? 'success' : 'danger'">
|
||||||
:type="scope.row.state === '成功' ? 'success' : scope.row.state === '失败' ? 'danger' : ''"
|
{{ scope.row.state ? '正常' : '异常' }}
|
||||||
>
|
|
||||||
{{ scope.row.state }}
|
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column prop="date" label="注册时间"></el-table-column>
|
<el-table-column prop="date" label="注册时间" align="center"></el-table-column>
|
||||||
<el-table-column label="操作" width="220" align="center">
|
<el-table-column label="操作" width="280" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button text :icon="Edit" @click="handleEdit(scope.$index, scope.row)" v-permiss="15">
|
<el-button type="warning" size="small" :icon="View" @click="handleView(scope.row)">
|
||||||
|
查看
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
:icon="Edit"
|
||||||
|
@click="handleEdit(scope.$index, scope.row)"
|
||||||
|
v-permiss="15"
|
||||||
|
>
|
||||||
编辑
|
编辑
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button text :icon="Delete" class="red" @click="handleDelete(scope.$index)" v-permiss="16">
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
size="small"
|
||||||
|
:icon="Delete"
|
||||||
|
@click="handleDelete(scope.$index)"
|
||||||
|
v-permiss="16"
|
||||||
|
>
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
@ -62,23 +71,18 @@
|
||||||
></el-pagination>
|
></el-pagination>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<el-dialog
|
||||||
<!-- 编辑弹出框 -->
|
:title="idEdit ? '编辑用户' : '新增用户'"
|
||||||
<el-dialog title="编辑" v-model="editVisible" width="30%">
|
v-model="visible"
|
||||||
<el-form label-width="70px">
|
width="500px"
|
||||||
<el-form-item label="用户名">
|
destroy-on-close
|
||||||
<el-input v-model="form.name"></el-input>
|
:close-on-click-modal="false"
|
||||||
</el-form-item>
|
@close="closeDialog"
|
||||||
<el-form-item label="地址">
|
>
|
||||||
<el-input v-model="form.address"></el-input>
|
<TableEdit :data="rowData" :edit="idEdit" :update="updateData" />
|
||||||
</el-form-item>
|
</el-dialog>
|
||||||
</el-form>
|
<el-dialog title="查看用户详情" v-model="visible1" width="700px" destroy-on-close>
|
||||||
<template #footer>
|
<TableDetail :data="rowData" />
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="editVisible = false">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="saveEdit">确 定</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -86,13 +90,16 @@
|
||||||
<script setup lang="ts" name="basetable">
|
<script setup lang="ts" name="basetable">
|
||||||
import { ref, reactive } from 'vue';
|
import { ref, reactive } from 'vue';
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
import { Delete, Edit, Search, Plus } from '@element-plus/icons-vue';
|
import { Delete, Edit, Search, CirclePlusFilled, View } from '@element-plus/icons-vue';
|
||||||
import { fetchData } from '../api/index';
|
import { fetchData } from '../api/index';
|
||||||
|
import TableEdit from '../components/table-edit.vue';
|
||||||
|
import TableDetail from '../components/table-detail.vue';
|
||||||
|
|
||||||
interface TableItem {
|
interface TableItem {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
money: string;
|
thumb: string;
|
||||||
|
money: number;
|
||||||
state: string;
|
state: string;
|
||||||
date: string;
|
date: string;
|
||||||
address: string;
|
address: string;
|
||||||
|
@ -107,11 +114,10 @@ const query = reactive({
|
||||||
const tableData = ref<TableItem[]>([]);
|
const tableData = ref<TableItem[]>([]);
|
||||||
const pageTotal = ref(0);
|
const pageTotal = ref(0);
|
||||||
// 获取表格数据
|
// 获取表格数据
|
||||||
const getData = () => {
|
const getData = async () => {
|
||||||
fetchData().then(res => {
|
const res = await fetchData();
|
||||||
tableData.value = res.data.list;
|
tableData.value = res.data.list;
|
||||||
pageTotal.value = res.data.pageTotal || 50;
|
pageTotal.value = res.data.pageTotal || 50;
|
||||||
});
|
|
||||||
};
|
};
|
||||||
getData();
|
getData();
|
||||||
|
|
||||||
|
@ -139,46 +145,43 @@ const handleDelete = (index: number) => {
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 表格编辑时弹窗和保存
|
const visible = ref(false);
|
||||||
const editVisible = ref(false);
|
|
||||||
let form = reactive({
|
|
||||||
name: '',
|
|
||||||
address: ''
|
|
||||||
});
|
|
||||||
let idx: number = -1;
|
let idx: number = -1;
|
||||||
const handleEdit = (index: number, row: any) => {
|
const idEdit = ref(false);
|
||||||
|
const rowData = ref({});
|
||||||
|
const handleEdit = (index: number, row: TableItem) => {
|
||||||
idx = index;
|
idx = index;
|
||||||
form.name = row.name;
|
rowData.value = row;
|
||||||
form.address = row.address;
|
idEdit.value = true;
|
||||||
editVisible.value = true;
|
visible.value = true;
|
||||||
};
|
};
|
||||||
const saveEdit = () => {
|
const updateData = (row: TableItem) => {
|
||||||
editVisible.value = false;
|
idEdit.value ? (tableData.value[idx] = row) : tableData.value.unshift(row);
|
||||||
ElMessage.success(`修改第 ${idx + 1} 行成功`);
|
console.log(tableData.value);
|
||||||
tableData.value[idx].name = form.name;
|
closeDialog();
|
||||||
tableData.value[idx].address = form.address;
|
};
|
||||||
|
|
||||||
|
const closeDialog = () => {
|
||||||
|
visible.value = false;
|
||||||
|
idEdit.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visible1 = ref(false);
|
||||||
|
const handleView = (row: TableItem) => {
|
||||||
|
rowData.value = row;
|
||||||
|
visible1.value = true;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.handle-box {
|
.search-box {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.handle-select {
|
.search-input {
|
||||||
width: 120px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.handle-input {
|
|
||||||
width: 300px;
|
|
||||||
}
|
|
||||||
.table {
|
|
||||||
width: 100%;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
.red {
|
|
||||||
color: #F56C6C;
|
|
||||||
}
|
|
||||||
.mr10 {
|
.mr10 {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,10 @@
|
||||||
<span class="message-title">{{ scope.row.title }}</span>
|
<span class="message-title">{{ scope.row.title }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="date" width="150"></el-table-column>
|
<el-table-column prop="date" width="180"></el-table-column>
|
||||||
<el-table-column width="120">
|
<el-table-column width="120">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button type="danger" @click="handleDel(scope.$index)">删除</el-button>
|
<el-button type="danger" size="small" @click="handleDel(scope.$index)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
@ -47,10 +47,10 @@
|
||||||
<span class="message-title">{{ scope.row.title }}</span>
|
<span class="message-title">{{ scope.row.title }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="date" width="150"></el-table-column>
|
<el-table-column prop="date" width="180"></el-table-column>
|
||||||
<el-table-column width="120">
|
<el-table-column width="120">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button @click="handleRestore(scope.$index)">还原</el-button>
|
<el-button size="small" @click="handleRestore(scope.$index)">还原</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"useDefineForClassFields": true,
|
"useDefineForClassFields": true,
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "Node",
|
"moduleResolution": "Node",
|
||||||
"strict": true,
|
"strict": false,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
|
|
Loading…
Reference in New Issue