parent
f70c93715b
commit
c8cae1b200
|
@ -15,6 +15,8 @@ declare module '@vue/runtime-core' {
|
|||
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
|
||||
ElCol: typeof import('element-plus/es')['ElCol']
|
||||
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']
|
||||
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
||||
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
||||
|
@ -48,6 +50,8 @@ declare module '@vue/runtime-core' {
|
|||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
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']
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<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">
|
||||
</head>
|
||||
|
||||
|
|
20
package.json
20
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "vue-manage-system",
|
||||
"version": "5.3.0",
|
||||
"version": "5.3.5",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
@ -8,16 +8,18 @@
|
|||
"serve": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.0.9",
|
||||
"axios": "^0.27.2",
|
||||
"element-plus": "^2.2.14",
|
||||
"md-editor-v3": "^2.2.1",
|
||||
"pinia": "^2.0.20",
|
||||
"vue": "^3.2.37",
|
||||
"@element-plus/icons-vue": "*",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
||||
"axios": "^1.6.3",
|
||||
"element-plus": "^2.4.4",
|
||||
"md-editor-v3": "^2.11.2",
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.1.7",
|
||||
"vue": "^3.3.0",
|
||||
"vue-cropperjs": "^5.0.0",
|
||||
"vue-router": "^4.1.3",
|
||||
"vue-router": "^4.2.5",
|
||||
"vue-schart": "^2.0.0",
|
||||
"wangeditor": "^4.7.15",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<el-config-provider :locale="zhCn">
|
||||
<router-view />
|
||||
</el-config-provider>
|
||||
<el-config-provider :locale="zhCn">
|
||||
<router-view />
|
||||
</el-config-provider>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -10,5 +10,5 @@ import zhCn from 'element-plus/es/locale/lang/zh-cn';
|
|||
</script>
|
||||
<style>
|
||||
@import './assets/css/main.css';
|
||||
@import './assets/css/color-dark.css';
|
||||
@import './assets/css/color-dark.scss';
|
||||
</style>
|
||||
|
|
|
@ -2,7 +2,7 @@ import request from '../utils/request';
|
|||
|
||||
export const fetchData = () => {
|
||||
return request({
|
||||
url: './table.json',
|
||||
method: 'get'
|
||||
url: 'https://www.fastmock.site/mock/dc695d037038802def4b989ba4650c3f/vms/getUser',
|
||||
method: 'post'
|
||||
});
|
||||
};
|
||||
|
|
|
@ -8,15 +8,15 @@
|
|||
background: #eef1f6;
|
||||
}
|
||||
.plugins-tips a{
|
||||
color: #20a0ff;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
.tags-li.active {
|
||||
border: 1px solid #409EFF;
|
||||
background-color: #409EFF;
|
||||
border: 1px solid var(--el-color-primary);
|
||||
background-color: var(--el-color-primary);
|
||||
}
|
||||
.message-title{
|
||||
color: #20a0ff;
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
.collapse-btn:hover{
|
||||
background: rgb(40,52,70);
|
|
@ -74,10 +74,6 @@ a {
|
|||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.el-table tr:hover {
|
||||
background: #f6faff;
|
||||
}
|
||||
|
||||
.mgb20 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
@ -113,7 +109,6 @@ a {
|
|||
|
||||
|
||||
[class*=" el-icon-"], [class^=el-icon-] {
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
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 { usePermissStore } from '../store/permiss';
|
||||
import Home from '../views/home.vue';
|
||||
import NProgress from 'nprogress'
|
||||
import 'nprogress/nprogress.css'
|
||||
|
||||
const routes: RouteRecordRaw[] = [
|
||||
{
|
||||
|
@ -163,7 +165,7 @@ const router = createRouter({
|
|||
});
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
document.title = `${to.meta.title} | vue-manage-system`;
|
||||
NProgress.start();
|
||||
const role = localStorage.getItem('ms_username');
|
||||
const permiss = usePermissStore();
|
||||
if (!role && to.path !== '/login') {
|
||||
|
@ -176,4 +178,8 @@ router.beforeEach((to, from, next) => {
|
|||
}
|
||||
});
|
||||
|
||||
router.afterEach(() => {
|
||||
NProgress.done()
|
||||
})
|
||||
|
||||
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
|
||||
});
|
||||
|
||||
service.interceptors.request.use(
|
||||
(config: AxiosRequestConfig) => {
|
||||
(config: InternalAxiosRequestConfig) => {
|
||||
return config;
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
|
|
|
@ -1,36 +1,54 @@
|
|||
<template>
|
||||
<div class="container">
|
||||
<div class="plugins-tips">
|
||||
wangEditor:轻量级 web 富文本编辑器,配置方便,使用简单。 访问地址:
|
||||
<a href="https://www.wangeditor.com/doc/" target="_blank">wangEditor</a>
|
||||
</div>
|
||||
<div class="mgb20" ref="editor"></div>
|
||||
<el-button type="primary" @click="syncHTML">提交</el-button>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="plugins-tips">
|
||||
wangEditor:轻量级 web 富文本编辑器,配置方便,使用简单。 访问地址:
|
||||
<a href="https://www.wangeditor.com/doc/" target="_blank">wangEditor</a>
|
||||
</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>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="editor">
|
||||
import WangEditor from 'wangeditor';
|
||||
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
|
||||
import '@wangeditor/editor/dist/css/style.css'; // 引入 css
|
||||
import { onBeforeUnmount, ref, reactive, shallowRef, onMounted } from 'vue';
|
||||
import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
|
||||
// 编辑器实例,必须用 shallowRef
|
||||
const editorRef = shallowRef();
|
||||
|
||||
const editor = ref(null);
|
||||
const content = reactive({
|
||||
html: '',
|
||||
text: ''
|
||||
});
|
||||
let instance: any;
|
||||
// 内容 HTML
|
||||
const valueHtml = ref('<p>hello</p>');
|
||||
|
||||
// 模拟 ajax 异步获取内容
|
||||
onMounted(() => {
|
||||
instance = new WangEditor(editor.value);
|
||||
instance.config.zIndex = 1;
|
||||
instance.create();
|
||||
setTimeout(() => {
|
||||
valueHtml.value = '<p>模拟 Ajax 异步设置内容</p>';
|
||||
}, 1500);
|
||||
});
|
||||
|
||||
const toolbarConfig = {};
|
||||
const editorConfig = { placeholder: '请输入内容...' };
|
||||
|
||||
// 组件销毁时,也及时销毁编辑器
|
||||
onBeforeUnmount(() => {
|
||||
instance.destroy();
|
||||
instance = null;
|
||||
const editor = editorRef.value;
|
||||
if (editor == null) return;
|
||||
editor.destroy();
|
||||
});
|
||||
|
||||
const handleCreated = (editor: any) => {
|
||||
editorRef.value = editor; // 记录 editor 实例,重要!
|
||||
};
|
||||
const syncHTML = () => {
|
||||
content.html = instance.txt.html();
|
||||
console.log(content.html);
|
||||
console.log(valueHtml.value);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,34 +1,35 @@
|
|||
<template>
|
||||
<div class="login-wrap">
|
||||
<div class="ms-login">
|
||||
<div class="ms-title">后台管理系统</div>
|
||||
<el-form :model="param" :rules="rules" ref="login" label-width="0px" class="ms-content">
|
||||
<el-form-item prop="username">
|
||||
<el-input v-model="param.username" placeholder="username">
|
||||
<template #prepend>
|
||||
<el-button :icon="User"></el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input
|
||||
type="password"
|
||||
placeholder="password"
|
||||
v-model="param.password"
|
||||
@keyup.enter="submitForm(login)"
|
||||
>
|
||||
<template #prepend>
|
||||
<el-button :icon="Lock"></el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<div class="login-btn">
|
||||
<el-button type="primary" @click="submitForm(login)">登录</el-button>
|
||||
</div>
|
||||
<p class="login-tips">Tips : 用户名和密码随便填。</p>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="login-wrap">
|
||||
<div class="ms-login">
|
||||
<div class="ms-title">后台管理系统</div>
|
||||
<el-form :model="param" :rules="rules" ref="login" label-width="0px" class="ms-content">
|
||||
<el-form-item prop="username">
|
||||
<el-input v-model="param.username" placeholder="username">
|
||||
<template #prepend>
|
||||
<el-button :icon="User"></el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input
|
||||
type="password"
|
||||
placeholder="password"
|
||||
v-model="param.password"
|
||||
@keyup.enter="submitForm(login)"
|
||||
>
|
||||
<template #prepend>
|
||||
<el-button :icon="Lock"></el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<div class="login-btn">
|
||||
<el-button type="primary" @click="submitForm(login)">登录</el-button>
|
||||
</div>
|
||||
<el-checkbox class="login-tips" v-model="checked" label="记住密码" size="large" />
|
||||
<p class="login-tips">Tips : 用户名和密码随便填。</p>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -41,43 +42,52 @@ import type { FormInstance, FormRules } from 'element-plus';
|
|||
import { Lock, User } from '@element-plus/icons-vue';
|
||||
|
||||
interface LoginInfo {
|
||||
username: string;
|
||||
password: string;
|
||||
username: 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 param = reactive<LoginInfo>({
|
||||
username: 'admin',
|
||||
password: '123123'
|
||||
username: defParam ? defParam.username : '',
|
||||
password: defParam ? defParam.password : '',
|
||||
});
|
||||
|
||||
const rules: FormRules = {
|
||||
username: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入用户名',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
|
||||
username: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入用户名',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
|
||||
};
|
||||
const permiss = usePermissStore();
|
||||
const login = ref<FormInstance>();
|
||||
const submitForm = (formEl: FormInstance | undefined) => {
|
||||
if (!formEl) return;
|
||||
formEl.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
ElMessage.success('登录成功');
|
||||
localStorage.setItem('ms_username', param.username);
|
||||
const keys = permiss.defaultList[param.username == 'admin' ? 'admin' : 'user'];
|
||||
permiss.handleSet(keys);
|
||||
localStorage.setItem('ms_keys', JSON.stringify(keys));
|
||||
router.push('/');
|
||||
} else {
|
||||
ElMessage.error('登录成功');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (!formEl) return;
|
||||
formEl.validate((valid: boolean) => {
|
||||
if (valid) {
|
||||
ElMessage.success('登录成功');
|
||||
localStorage.setItem('ms_username', param.username);
|
||||
const keys = permiss.defaultList[param.username == 'admin' ? 'admin' : 'user'];
|
||||
permiss.handleSet(keys);
|
||||
localStorage.setItem('ms_keys', JSON.stringify(keys));
|
||||
router.push('/');
|
||||
if (checked.value) {
|
||||
localStorage.setItem('login-param', JSON.stringify(param));
|
||||
} else {
|
||||
localStorage.removeItem('login-param');
|
||||
}
|
||||
} else {
|
||||
ElMessage.error('登录失败');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const tags = useTagsStore();
|
||||
|
@ -86,44 +96,41 @@ tags.clearTags();
|
|||
|
||||
<style scoped>
|
||||
.login-wrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url(../assets/img/login-bg.jpg);
|
||||
background-size: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url(../assets/img/login-bg.jpg);
|
||||
background-size: 100%;
|
||||
}
|
||||
.ms-title {
|
||||
width: 100%;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
border-bottom: 1px solid #ddd;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
padding-top: 10px;
|
||||
}
|
||||
.ms-login {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 350px;
|
||||
margin: -190px 0 0 -175px;
|
||||
border-radius: 5px;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
overflow: hidden;
|
||||
width: 350px;
|
||||
border-radius: 5px;
|
||||
background: #fff;
|
||||
}
|
||||
.ms-content {
|
||||
padding: 30px 30px;
|
||||
padding: 10px 30px 30px;
|
||||
}
|
||||
.login-btn {
|
||||
text-align: center;
|
||||
text-align: center;
|
||||
}
|
||||
.login-btn button {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.login-tips {
|
||||
font-size: 12px;
|
||||
line-height: 30px;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
line-height: 30px;
|
||||
color: #333;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,19 +1,15 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="container">
|
||||
<div class="handle-box">
|
||||
<el-select v-model="query.address" placeholder="地址" class="handle-select mr10">
|
||||
<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>
|
||||
<div class="search-box">
|
||||
<el-input v-model="query.name" placeholder="用户名" class="search-input mr10" clearable></el-input>
|
||||
<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>
|
||||
<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="name" label="用户名"></el-table-column>
|
||||
<el-table-column label="账户余额">
|
||||
<el-table-column prop="name" label="用户名" align="center"></el-table-column>
|
||||
<el-table-column label="账户余额" align="center">
|
||||
<template #default="scope">¥{{ scope.row.money }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="头像(查看大图)" align="center">
|
||||
|
@ -28,24 +24,37 @@
|
|||
</el-image>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="address" label="地址"></el-table-column>
|
||||
<el-table-column label="状态" align="center">
|
||||
<el-table-column prop="address" label="地址" align="center"></el-table-column>
|
||||
<el-table-column label="账户状态" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag
|
||||
:type="scope.row.state === '成功' ? 'success' : scope.row.state === '失败' ? 'danger' : ''"
|
||||
>
|
||||
{{ scope.row.state }}
|
||||
<el-tag :type="scope.row.state ? 'success' : 'danger'">
|
||||
{{ scope.row.state ? '正常' : '异常' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="date" label="注册时间"></el-table-column>
|
||||
<el-table-column label="操作" width="220" align="center">
|
||||
<el-table-column prop="date" label="注册时间" align="center"></el-table-column>
|
||||
<el-table-column label="操作" width="280" align="center">
|
||||
<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 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>
|
||||
</template>
|
||||
|
@ -62,23 +71,18 @@
|
|||
></el-pagination>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 编辑弹出框 -->
|
||||
<el-dialog title="编辑" v-model="editVisible" width="30%">
|
||||
<el-form label-width="70px">
|
||||
<el-form-item label="用户名">
|
||||
<el-input v-model="form.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="地址">
|
||||
<el-input v-model="form.address"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="editVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="saveEdit">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
<el-dialog
|
||||
:title="idEdit ? '编辑用户' : '新增用户'"
|
||||
v-model="visible"
|
||||
width="500px"
|
||||
destroy-on-close
|
||||
:close-on-click-modal="false"
|
||||
@close="closeDialog"
|
||||
>
|
||||
<TableEdit :data="rowData" :edit="idEdit" :update="updateData" />
|
||||
</el-dialog>
|
||||
<el-dialog title="查看用户详情" v-model="visible1" width="700px" destroy-on-close>
|
||||
<TableDetail :data="rowData" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -86,13 +90,16 @@
|
|||
<script setup lang="ts" name="basetable">
|
||||
import { ref, reactive } from 'vue';
|
||||
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 TableEdit from '../components/table-edit.vue';
|
||||
import TableDetail from '../components/table-detail.vue';
|
||||
|
||||
interface TableItem {
|
||||
id: number;
|
||||
name: string;
|
||||
money: string;
|
||||
thumb: string;
|
||||
money: number;
|
||||
state: string;
|
||||
date: string;
|
||||
address: string;
|
||||
|
@ -107,11 +114,10 @@ const query = reactive({
|
|||
const tableData = ref<TableItem[]>([]);
|
||||
const pageTotal = ref(0);
|
||||
// 获取表格数据
|
||||
const getData = () => {
|
||||
fetchData().then(res => {
|
||||
tableData.value = res.data.list;
|
||||
pageTotal.value = res.data.pageTotal || 50;
|
||||
});
|
||||
const getData = async () => {
|
||||
const res = await fetchData();
|
||||
tableData.value = res.data.list;
|
||||
pageTotal.value = res.data.pageTotal || 50;
|
||||
};
|
||||
getData();
|
||||
|
||||
|
@ -139,46 +145,43 @@ const handleDelete = (index: number) => {
|
|||
.catch(() => {});
|
||||
};
|
||||
|
||||
// 表格编辑时弹窗和保存
|
||||
const editVisible = ref(false);
|
||||
let form = reactive({
|
||||
name: '',
|
||||
address: ''
|
||||
});
|
||||
const visible = ref(false);
|
||||
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;
|
||||
form.name = row.name;
|
||||
form.address = row.address;
|
||||
editVisible.value = true;
|
||||
rowData.value = row;
|
||||
idEdit.value = true;
|
||||
visible.value = true;
|
||||
};
|
||||
const saveEdit = () => {
|
||||
editVisible.value = false;
|
||||
ElMessage.success(`修改第 ${idx + 1} 行成功`);
|
||||
tableData.value[idx].name = form.name;
|
||||
tableData.value[idx].address = form.address;
|
||||
const updateData = (row: TableItem) => {
|
||||
idEdit.value ? (tableData.value[idx] = row) : tableData.value.unshift(row);
|
||||
console.log(tableData.value);
|
||||
closeDialog();
|
||||
};
|
||||
|
||||
const closeDialog = () => {
|
||||
visible.value = false;
|
||||
idEdit.value = false;
|
||||
};
|
||||
|
||||
const visible1 = ref(false);
|
||||
const handleView = (row: TableItem) => {
|
||||
rowData.value = row;
|
||||
visible1.value = true;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.handle-box {
|
||||
.search-box {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.handle-select {
|
||||
width: 120px;
|
||||
.search-input {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.handle-input {
|
||||
width: 300px;
|
||||
}
|
||||
.table {
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
}
|
||||
.red {
|
||||
color: #F56C6C;
|
||||
}
|
||||
.mr10 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
|
|
@ -27,10 +27,10 @@
|
|||
<span class="message-title">{{ scope.row.title }}</span>
|
||||
</template>
|
||||
</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">
|
||||
<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>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
@ -47,10 +47,10 @@
|
|||
<span class="message-title">{{ scope.row.title }}</span>
|
||||
</template>
|
||||
</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">
|
||||
<template #default="scope">
|
||||
<el-button @click="handleRestore(scope.$index)">还原</el-button>
|
||||
<el-button size="small" @click="handleRestore(scope.$index)">还原</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"strict": true,
|
||||
"strict": false,
|
||||
"jsx": "preserve",
|
||||
"sourceMap": true,
|
||||
"resolveJsonModule": true,
|
||||
|
|
Loading…
Reference in New Issue