WEB
24
tencent/.gitignore
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
3
tencent/.vscode/extensions.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
|
||||||
|
}
|
18
tencent/README.md
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Vue 3 + TypeScript + Vite
|
||||||
|
|
||||||
|
This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
|
||||||
|
|
||||||
|
## Recommended IDE Setup
|
||||||
|
|
||||||
|
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
|
||||||
|
|
||||||
|
## Type Support For `.vue` Imports in TS
|
||||||
|
|
||||||
|
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
|
||||||
|
|
||||||
|
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
|
||||||
|
|
||||||
|
1. Disable the built-in TypeScript Extension
|
||||||
|
1. Run `Extensions: Show Built-in Extensions` from VSCode's command palette
|
||||||
|
2. Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
|
||||||
|
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
|
BIN
tencent/dist.zip
Normal file
13
tencent/index.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>后台管理</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
1910
tencent/package-lock.json
generated
Normal file
29
tencent/package.json
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"name": "tencent",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vue-tsc && vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ant-design-vue": "^4.2.3",
|
||||||
|
"axios": "^1.6.7",
|
||||||
|
"echarts": "^4.9.0",
|
||||||
|
"element-plus": "^2.6.0",
|
||||||
|
"pinia": "^2.1.7",
|
||||||
|
"pinia-plugin-persistedstate": "^3.2.1",
|
||||||
|
"vue": "^3.4.19",
|
||||||
|
"vue-router": "^4.3.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitejs/plugin-vue": "^5.0.4",
|
||||||
|
"babel-plugin-component": "^1.1.1",
|
||||||
|
"sass": "^1.77.0",
|
||||||
|
"typescript": "^5.2.2",
|
||||||
|
"vite": "^5.1.4",
|
||||||
|
"vue-tsc": "^1.8.27"
|
||||||
|
}
|
||||||
|
}
|
1
tencent/public/vite.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
20
tencent/src/API/myAxios.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import axios from "axios"
|
||||||
|
const myAxios = axios.create({
|
||||||
|
withCredentials:true,
|
||||||
|
//baseURL:'http://localhost:9999/api'
|
||||||
|
baseURL:'http://39.101.78.35:6271/api'
|
||||||
|
});
|
||||||
|
|
||||||
|
myAxios.interceptors.request.use(function (config) {
|
||||||
|
return config;
|
||||||
|
}, function (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
myAxios.interceptors.response.use(function (response) {
|
||||||
|
return response.data;
|
||||||
|
}, function (error) {
|
||||||
|
return Promise.reject(error);
|
||||||
|
});
|
||||||
|
export default myAxios;
|
23
tencent/src/App.vue
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<router-view></router-view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
html {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
background-color: deeppink;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: deeppink;
|
||||||
|
}
|
||||||
|
</style>
|
1
tencent/src/assets/vue.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
|
After Width: | Height: | Size: 496 B |
BIN
tencent/src/images/200.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
tencent/src/images/R-C.jpeg
Normal file
After Width: | Height: | Size: 89 KiB |
BIN
tencent/src/images/avatar.jpg
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
tencent/src/images/background.png
Normal file
After Width: | Height: | Size: 465 KiB |
BIN
tencent/src/images/bgi.jpg
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
tencent/src/images/bgi.png
Normal file
After Width: | Height: | Size: 140 KiB |
BIN
tencent/src/images/cart.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
tencent/src/images/center-bg.png
Normal file
After Width: | Height: | Size: 130 KiB |
BIN
tencent/src/images/good.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
tencent/src/images/load.gif
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
tencent/src/images/loading.gif
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
tencent/src/images/login-bg.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
tencent/src/images/logo.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
tencent/src/images/love.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
tencent/src/images/my.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
tencent/src/images/none.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
tencent/src/images/qishou.jpg
Normal file
After Width: | Height: | Size: 225 KiB |
35
tencent/src/main.ts
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import { createApp } from 'vue'
|
||||||
|
//elementplus
|
||||||
|
import ElementPlus from 'element-plus'
|
||||||
|
import 'element-plus/dist/index.css'
|
||||||
|
import App from './App.vue'
|
||||||
|
//router
|
||||||
|
import router from "./router"
|
||||||
|
//pinia
|
||||||
|
import { createPinia } from 'pinia'
|
||||||
|
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
|
||||||
|
//ant
|
||||||
|
import Antd from 'ant-design-vue'
|
||||||
|
import 'ant-design-vue/lib/button/style'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//pinia
|
||||||
|
const pinia = createPinia()
|
||||||
|
pinia.use(piniaPluginPersistedstate)
|
||||||
|
|
||||||
|
const app = createApp(App)
|
||||||
|
// 新增代码:注册全部组件
|
||||||
|
app.use(Antd)
|
||||||
|
app.use(router)
|
||||||
|
app.use(ElementPlus)
|
||||||
|
app.use(createPinia())
|
||||||
|
//挂载实例
|
||||||
|
app.mount('#app')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
8
tencent/src/router/index.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import {createRouter, createWebHashHistory} from "vue-router";
|
||||||
|
import {routes} from "./routes";
|
||||||
|
|
||||||
|
const router =createRouter({
|
||||||
|
history: createWebHashHistory(),
|
||||||
|
routes,
|
||||||
|
})
|
||||||
|
export default router
|
92
tencent/src/router/routes.ts
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
export const routes = [
|
||||||
|
{ path: '/login', component: () => import("../views/Login.vue")},
|
||||||
|
{ path: '/index',
|
||||||
|
component: () => import("../views/Layout/Index.vue"),
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
name:'首页',
|
||||||
|
component: () => import("../views/Home.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/header',
|
||||||
|
component: () => import("../views/Layout/Header.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/aside',
|
||||||
|
component: () => import("../views/Layout/Aside.vue"),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/sort',
|
||||||
|
component: () => import("../views/sort.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/setting',
|
||||||
|
name:'系统管理',
|
||||||
|
component: () => import("../views/Setting.vue"),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/merchant',
|
||||||
|
name:'商家管理',
|
||||||
|
component: () => import("../views/UserList/merchant.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/rider',
|
||||||
|
name:'跑腿管理',
|
||||||
|
component: () => import("../views/UserList/Rider.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/user',
|
||||||
|
name:'学生管理',
|
||||||
|
component: () => import("../views/UserList/user.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/order',
|
||||||
|
name:'订单管理',
|
||||||
|
component: () => import("../views/Order.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/talk',
|
||||||
|
component: () => import("../views/Talk.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/statistics',
|
||||||
|
component: () => import("../views/Statistics.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/center',
|
||||||
|
name:'个人中心',
|
||||||
|
component: () => import("../views/Center.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/evaluateAnalysis',
|
||||||
|
component: () => import("../views/analysis/evaluate.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/behaviorAnalysis',
|
||||||
|
component: () => import("../views/analysis/Behavior.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/orderAnalysis',
|
||||||
|
component: () => import("../views/analysis/Order.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/pointsAnalysis',
|
||||||
|
component: () => import("../views/analysis/points.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/postManage',
|
||||||
|
name:'帖子管理',
|
||||||
|
component: () => import("../views/forum/PostManage.vue"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/notification',
|
||||||
|
name:'通知与公告',
|
||||||
|
component: () => import("../views/forum/Notification.vue"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
17
tencent/src/stores/index.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { createPinia} from 'pinia'
|
||||||
|
|
||||||
|
const pinia = createPinia();
|
||||||
|
|
||||||
|
export default pinia
|
||||||
|
/*import { createPinia } from 'pinia'
|
||||||
|
|
||||||
|
// 创建 pinia 实例
|
||||||
|
const pinia = createPinia()
|
||||||
|
// 使用持久化存储插件
|
||||||
|
pinia.use(persist)
|
||||||
|
|
||||||
|
// 默认导出,给 main.ts 使用
|
||||||
|
export default pinia
|
||||||
|
|
||||||
|
// 模块统一导出
|
||||||
|
export * from './modules/member'*/
|
37
tencent/src/stores/userStore.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
import myAxios from "../API/myAxios.ts";
|
||||||
|
|
||||||
|
export const userStore = defineStore('user', {
|
||||||
|
state: () => {
|
||||||
|
return {
|
||||||
|
loginUser:{
|
||||||
|
username:'未登录',
|
||||||
|
avatarUrl:'',
|
||||||
|
userRole:'notLogin',
|
||||||
|
createTime:'null'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
persist: true,
|
||||||
|
actions:{
|
||||||
|
//获取用户信息
|
||||||
|
async getLoginUser() {
|
||||||
|
//请求登录信息
|
||||||
|
console.log("login已经调用");
|
||||||
|
//const res:any = await myAxios.get('/user/current');
|
||||||
|
const res:any = await myAxios.get('/user/current', { withCredentials: true });
|
||||||
|
console.log("11111")
|
||||||
|
console.log(res);
|
||||||
|
console.log("11111222222")
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
this.updateUser(res.data)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//更新用户信息
|
||||||
|
updateUser(payLoad: any) {
|
||||||
|
this.loginUser = payLoad;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
11
tencent/src/style.css
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
html {
|
||||||
|
/*滚动时采用平滑过度*/
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
display: block;
|
||||||
|
}
|
31
tencent/src/views/Center.vue
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {useRoute} from "vue-router";
|
||||||
|
const route = useRoute()
|
||||||
|
import {House} from "@element-plus/icons-vue";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="header">
|
||||||
|
<el-icon class="icon"><House /></el-icon>
|
||||||
|
/{{route.name}}
|
||||||
|
</div>
|
||||||
|
<div class="avatar"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.header {
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
background-color: white;
|
||||||
|
.icon {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 20px;
|
||||||
|
line-height: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.avatar {
|
||||||
|
width: 500px;
|
||||||
|
height: 250px;
|
||||||
|
background-color: pink;
|
||||||
|
}
|
||||||
|
</style>
|
177
tencent/src/views/Home.vue
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
//import {House} from "@element-plus/icons-vue";
|
||||||
|
import BrokenLine from "./echart/BrokenLine.vue";
|
||||||
|
import pie from "./echart/Pie.vue";
|
||||||
|
import Trading from "./echart/Trading.vue";
|
||||||
|
import { HomeOutlined} from '@ant-design/icons-vue';
|
||||||
|
import {ref} from 'vue'
|
||||||
|
|
||||||
|
const list=ref([
|
||||||
|
{
|
||||||
|
style:'success',
|
||||||
|
message:'昨天的订单高峰期系统有些卡顿,请检查。'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
style:'info',
|
||||||
|
message:'新增功能测试完成,无明显bug,可上线。'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
style:'warning',
|
||||||
|
message:'客户反映配送时间显示不准确,需优化。'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
style:'error',
|
||||||
|
message:'下周促销活动准备就绪,请确保系统稳定。'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
style:'warning',
|
||||||
|
message:'请关注最近一周的销售数据波动情况。'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
style:'warning',
|
||||||
|
message:'高峰期配送员不够,请考虑增加人手。'
|
||||||
|
},
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a-breadcrumb class="header">
|
||||||
|
<a-breadcrumb-item href="">
|
||||||
|
<home-outlined />
|
||||||
|
</a-breadcrumb-item>
|
||||||
|
<a-breadcrumb-item>{{ $route.name }}</a-breadcrumb-item>
|
||||||
|
</a-breadcrumb>
|
||||||
|
<!-- <div class="header">
|
||||||
|
<el-icon class="icon"><House /></el-icon>
|
||||||
|
/{{route.name}}
|
||||||
|
</div>-->
|
||||||
|
<div class="mainLeft">
|
||||||
|
<div class="overview">
|
||||||
|
<div class="container">
|
||||||
|
<div class="square">
|
||||||
|
<p>每日交易量</p>
|
||||||
|
<img src="../images/cart.png" width="35px">
|
||||||
|
<h2>996</h2>
|
||||||
|
</div>
|
||||||
|
<div class="square">
|
||||||
|
<p>每日跑腿接单</p>
|
||||||
|
<img src="../images/cart.png" width="35px">
|
||||||
|
<h2>996</h2>
|
||||||
|
</div>
|
||||||
|
<div class="square">
|
||||||
|
<p>订单好评总数</p>
|
||||||
|
<img src="../images/cart.png" width="35px">
|
||||||
|
<h2>996</h2>
|
||||||
|
</div>
|
||||||
|
<div class="square">
|
||||||
|
<p>活跃用户数</p>
|
||||||
|
<img src="../images/cart.png" width="35px">
|
||||||
|
<h2>996</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="brokenLine">
|
||||||
|
<BrokenLine></BrokenLine>
|
||||||
|
</div>
|
||||||
|
<div class="pie1">
|
||||||
|
<pie></pie>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="mainRight">
|
||||||
|
<div class="feedback">
|
||||||
|
<h3>留言板</h3>
|
||||||
|
<div style="max-width: 600px" class="feedback">
|
||||||
|
<el-alert v-for="(item,index) in list" :key="index" :title="item.message" :type="item.style" show-icon class="message"/>
|
||||||
|
<!-- <el-alert title="Info alert" type="info" show-icon class="message"/>
|
||||||
|
<el-alert title="Warning alert" type="warning" show-icon class="message"/>
|
||||||
|
<el-alert title="Error alert" type="error" show-icon class="message"/>
|
||||||
|
<el-alert title="Error alert" type="error" show-icon class="message"/>
|
||||||
|
<el-alert title="Error alert" type="error" show-icon class="message"/>-->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="trade">
|
||||||
|
<Trading></Trading>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.header {
|
||||||
|
width: 100%;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
background-color: white;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mainLeft {
|
||||||
|
display: inline-block;
|
||||||
|
width: 65%;
|
||||||
|
height: 90%;
|
||||||
|
.overview {
|
||||||
|
width: 95%;
|
||||||
|
height: 13%;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.mainRight {
|
||||||
|
float: right;
|
||||||
|
width: 35%;
|
||||||
|
height: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 15px;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
.square {
|
||||||
|
width: 150px;
|
||||||
|
height: 80px;
|
||||||
|
background-color: rgba(0, 204, 255, 0.72);
|
||||||
|
border-radius: 15px;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-left: 15px;
|
||||||
|
}
|
||||||
|
.brokenLine {
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 100%;
|
||||||
|
height: 40%;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
.feedback {
|
||||||
|
width: 87%;
|
||||||
|
height: 60%;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
.message {
|
||||||
|
margin: 10px 0 0;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
.message:first-child {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.pie1 {
|
||||||
|
width: 90%;
|
||||||
|
height: 35%;
|
||||||
|
}
|
||||||
|
.trade {
|
||||||
|
width: 100%;
|
||||||
|
height: 40%;
|
||||||
|
}
|
||||||
|
</style>
|
81
tencent/src/views/Layout/Aside.vue
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {onMounted, ref} from 'vue'
|
||||||
|
import {
|
||||||
|
Document,
|
||||||
|
Menu as IconMenu,
|
||||||
|
House,
|
||||||
|
Setting,
|
||||||
|
ChatLineRound,
|
||||||
|
Histogram,
|
||||||
|
} from "@element-plus/icons-vue";
|
||||||
|
import {useRoute} from "vue-router";
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const activeIndex = ref('/Index')
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
setActiveIndex();
|
||||||
|
})
|
||||||
|
const setActiveIndex = () =>{
|
||||||
|
activeIndex.value = route.path
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-menu
|
||||||
|
:default-active="activeIndex"
|
||||||
|
class="el-menu-vertical-demo"
|
||||||
|
router
|
||||||
|
active-text-color="#0f40f5"
|
||||||
|
background-color="white"
|
||||||
|
text-color="#000"
|
||||||
|
>
|
||||||
|
<el-menu-item index="/">
|
||||||
|
<el-icon><House /></el-icon>
|
||||||
|
<span>首页</span>
|
||||||
|
</el-menu-item>
|
||||||
|
<el-sub-menu index="/merchant">
|
||||||
|
<template #title>
|
||||||
|
<el-icon>
|
||||||
|
<IconMenu />
|
||||||
|
</el-icon>
|
||||||
|
<span>用户管理</span>
|
||||||
|
</template>
|
||||||
|
<el-menu-item index="/merchant">商家管理 </el-menu-item>
|
||||||
|
<el-menu-item index="/rider">跑腿管理</el-menu-item>
|
||||||
|
<el-menu-item index="/user">普通用户管理</el-menu-item>
|
||||||
|
</el-sub-menu>
|
||||||
|
<el-menu-item index="/order">
|
||||||
|
<el-icon><document /></el-icon>
|
||||||
|
<span>订单管理</span>
|
||||||
|
</el-menu-item>
|
||||||
|
|
||||||
|
<el-sub-menu index="/talk">
|
||||||
|
<template #title>
|
||||||
|
<el-icon><ChatLineRound /></el-icon>
|
||||||
|
<span>论坛管理</span>
|
||||||
|
</template>
|
||||||
|
<el-menu-item index="/postManage">帖子管理</el-menu-item>
|
||||||
|
<el-menu-item index="/notification">通知与公告</el-menu-item>
|
||||||
|
</el-sub-menu>
|
||||||
|
|
||||||
|
<el-sub-menu index="/statistics">
|
||||||
|
<template #title>
|
||||||
|
<el-icon><Histogram /></el-icon>
|
||||||
|
<span>数据统计</span>
|
||||||
|
</template>
|
||||||
|
<el-menu-item index="/behaviorAnalysis">用户行为分析 </el-menu-item>
|
||||||
|
<el-menu-item index="/orderAnalysis">订单分析</el-menu-item>
|
||||||
|
<el-menu-item index="/evaluateAnalysis">评价分析</el-menu-item>
|
||||||
|
<el-menu-item index="/pointsAnalysis">积分活动分析</el-menu-item>
|
||||||
|
</el-sub-menu>
|
||||||
|
<el-menu-item index="/setting">
|
||||||
|
<el-icon><setting /></el-icon>
|
||||||
|
<span>系统管理</span>
|
||||||
|
</el-menu-item>
|
||||||
|
</el-menu>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
146
tencent/src/views/Layout/Header.vue
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {onMounted, ref} from "vue";
|
||||||
|
import {Search,Bell,Sunny} from "@element-plus/icons-vue";
|
||||||
|
import myAxios from "../../API/myAxios.ts";
|
||||||
|
import {ElMessage} from "element-plus";
|
||||||
|
import {useRouter} from "vue-router";
|
||||||
|
import {userStore} from "../../stores/userStore.ts";
|
||||||
|
const router = useRouter();
|
||||||
|
const store = userStore();
|
||||||
|
const logout= async() => {
|
||||||
|
const res:any = await myAxios.post("/user/logout", {
|
||||||
|
})
|
||||||
|
ElMessage({
|
||||||
|
showClose: true,
|
||||||
|
type: res.code === 0 ? 'success' : "error",
|
||||||
|
message: res.code === 0 ? '退出成功' : `退出失败`,
|
||||||
|
})
|
||||||
|
if (res.code === 0 && res.data) {
|
||||||
|
store.$reset();
|
||||||
|
await router.replace('/login')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const open = ref<boolean>(false);
|
||||||
|
|
||||||
|
const afterOpenChange = (bool: boolean) => {
|
||||||
|
console.log('open', bool);
|
||||||
|
};
|
||||||
|
|
||||||
|
const showDrawer = () => {
|
||||||
|
open.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(()=>{
|
||||||
|
console.log(store.loginUser);
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="boxLeft">
|
||||||
|
<img src="../../images/logo.png" class="boxImg">
|
||||||
|
</div>
|
||||||
|
<div class="user">
|
||||||
|
{{store.loginUser.userRole==='notLogin'?'未登录':store.loginUser.username}}
|
||||||
|
</div>
|
||||||
|
<div class="boxRight">
|
||||||
|
<div class="icon1">
|
||||||
|
<el-icon><Search /></el-icon>
|
||||||
|
</div>
|
||||||
|
<div class="icon2">
|
||||||
|
<el-icon><Bell /></el-icon>
|
||||||
|
</div>
|
||||||
|
<div class="icon3">
|
||||||
|
<el-icon><Sunny /></el-icon>
|
||||||
|
</div>
|
||||||
|
<el-dropdown>
|
||||||
|
<a-avatar size="large" class="people">
|
||||||
|
<template #icon><img :src="store.loginUser.avatarUrl" alt=""></template>
|
||||||
|
</a-avatar>
|
||||||
|
<template #dropdown>
|
||||||
|
<el-dropdown-menu>
|
||||||
|
<el-dropdown-item @click="logout"><el-icon><Bell /></el-icon>退出登录</el-dropdown-item>
|
||||||
|
<el-dropdown-item @click="showDrawer"><el-icon><Bell /></el-icon>个人中心</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
</el-dropdown>
|
||||||
|
|
||||||
|
<a-drawer
|
||||||
|
v-model:open="open"
|
||||||
|
class="custom-class"
|
||||||
|
root-class-name="root-class-name"
|
||||||
|
:root-style="{ color: 'blue' }"
|
||||||
|
style="color: #646464"
|
||||||
|
title="个人中心"
|
||||||
|
placement="right"
|
||||||
|
@after-open-change="afterOpenChange"
|
||||||
|
>
|
||||||
|
<el-avatar :size="64" :src="store.loginUser.avatarUrl"></el-avatar>
|
||||||
|
|
||||||
|
<div class="message">
|
||||||
|
<p class="firstmessage">用户名:{{ store.loginUser.username }}</p>
|
||||||
|
<p>账号ID:{{ store.loginUser.username }}</p>
|
||||||
|
<p>注册时间:2024-06-20</p>
|
||||||
|
<p>账号权限:管理员</p>
|
||||||
|
</div>
|
||||||
|
</a-drawer>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.boxLeft {
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.user {
|
||||||
|
padding-left: 1070px;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 50px;
|
||||||
|
}
|
||||||
|
.boxImg {
|
||||||
|
width:200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.boxRight {
|
||||||
|
float: right;
|
||||||
|
width: 120px;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon1 {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.icon2 {
|
||||||
|
margin-left: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.icon3 {
|
||||||
|
margin-left: 10px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.people {
|
||||||
|
float: right;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-left: 10px;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.custom-class img{
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.message {
|
||||||
|
float: right;
|
||||||
|
margin-right: 100px;
|
||||||
|
}
|
||||||
|
.firstmessage {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
</style>
|
45
tencent/src/views/Layout/Index.vue
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import Header from "./Header.vue"
|
||||||
|
import Aside from "./Aside.vue"
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="common-layout">
|
||||||
|
<el-container style="height: 100%;">
|
||||||
|
<el-header class="header">
|
||||||
|
<Header></Header>
|
||||||
|
</el-header>
|
||||||
|
<el-container>
|
||||||
|
<el-aside width="200px" class="aside">
|
||||||
|
<Aside></Aside>
|
||||||
|
</el-aside>
|
||||||
|
<el-container>
|
||||||
|
<el-main class="main">
|
||||||
|
<router-view></router-view>
|
||||||
|
</el-main>
|
||||||
|
</el-container>
|
||||||
|
</el-container>
|
||||||
|
</el-container>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.common-layout {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
.main {
|
||||||
|
width: 100%;
|
||||||
|
padding: 2px;
|
||||||
|
background-color: #F7F7F7;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
width: 100%;
|
||||||
|
height: 8%;
|
||||||
|
}
|
||||||
|
.aside {
|
||||||
|
width: 12%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
305
tencent/src/views/Login.vue
Normal file
|
@ -0,0 +1,305 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {ref} from 'vue';
|
||||||
|
import {useRouter} from "vue-router";
|
||||||
|
import myAxios from "../API/myAxios.ts";
|
||||||
|
import {ElMessage} from "element-plus";
|
||||||
|
import {userStore} from "../stores/userStore.ts";
|
||||||
|
const router = useRouter();
|
||||||
|
const userAccount = ref('');
|
||||||
|
const userPassword= ref('');
|
||||||
|
const store = userStore();
|
||||||
|
|
||||||
|
const doLogin = async() =>{
|
||||||
|
console.log(userAccount.value);
|
||||||
|
console.log(userPassword.value);
|
||||||
|
const res:any = await myAxios.post("/user/login",{
|
||||||
|
userAccount: userAccount.value,
|
||||||
|
userPassword: userPassword.value
|
||||||
|
})
|
||||||
|
ElMessage({
|
||||||
|
showClose:true,
|
||||||
|
type: res.code===0?'success':"error",
|
||||||
|
message:res.code===0?'登录成功':`登录失败:${res.message}`,
|
||||||
|
})
|
||||||
|
console.log(res.data);
|
||||||
|
const resone:any = await myAxios.get('/user/current', { withCredentials: true });
|
||||||
|
console.log(resone);
|
||||||
|
console.log(res.code);
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
await store.getLoginUser()
|
||||||
|
|
||||||
|
await router.replace({path: '/'})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div id="login">
|
||||||
|
<header class="login-header">
|
||||||
|
<div class="container m-top-20">
|
||||||
|
<h1 class="logo">
|
||||||
|
<RouterLink to="/">校快送</RouterLink>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<section class="login-section">
|
||||||
|
<div class="wrapper">
|
||||||
|
<nav>
|
||||||
|
<RouterLink to="/">登录</RouterLink>
|
||||||
|
</nav>
|
||||||
|
<div class="account-box">
|
||||||
|
<div class="form">
|
||||||
|
<el-form ref="formRef" label-position="right" label-width="60px"
|
||||||
|
status-icon>
|
||||||
|
<el-form-item prop="userAccount" placeholder="请输入用户名" label="账户">
|
||||||
|
<el-input v-model="userAccount"/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="userPassword" placeholder="请输入密码" label="密码">
|
||||||
|
<el-input v-model="userPassword"/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-button size="large" class="subBtn" @click="doLogin">点击登录</el-button>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<footer class="login-footer">
|
||||||
|
<div class="container">
|
||||||
|
<p>CopyRight © 校快送</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
|
||||||
|
.login-header {
|
||||||
|
background: #fff;
|
||||||
|
border-bottom: 1px solid #e4e4e4;
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
width: 200px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
display: block;
|
||||||
|
height: 90px;
|
||||||
|
width: 100%;
|
||||||
|
text-indent: -9999px;
|
||||||
|
background: url("../images/logo.png") no-repeat center 18px / contain;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-bottom: 38px;
|
||||||
|
margin-left: 20px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry {
|
||||||
|
width: 120px;
|
||||||
|
margin-bottom: 38px;
|
||||||
|
font-size: 16px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 14px;
|
||||||
|
color: blue;
|
||||||
|
letter-spacing: -5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-section {
|
||||||
|
background: url('../images/bgi.jpg') no-repeat center / cover;
|
||||||
|
height: 488px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
width: 380px;
|
||||||
|
background: #fff;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 54px;
|
||||||
|
transform: translate3d(100px, 0, 0);
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15);
|
||||||
|
|
||||||
|
nav {
|
||||||
|
font-size: 14px;
|
||||||
|
height: 55px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-bottom: 1px solid #f5f5f5;
|
||||||
|
display: flex;
|
||||||
|
padding: 0 40px;
|
||||||
|
text-align: right;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
a {
|
||||||
|
flex: 1;
|
||||||
|
line-height: 1;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 18px;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-footer {
|
||||||
|
padding: 30px 0 50px;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
p {
|
||||||
|
text-align: center;
|
||||||
|
color: #999;
|
||||||
|
padding-top: 20px;
|
||||||
|
|
||||||
|
a {
|
||||||
|
line-height: 1;
|
||||||
|
padding: 0 10px;
|
||||||
|
color: #999;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
~a {
|
||||||
|
border-left: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-box {
|
||||||
|
.toggle {
|
||||||
|
padding: 15px 40px;
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: blue;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form {
|
||||||
|
padding: 0 20px 20px 20px;
|
||||||
|
|
||||||
|
&-item {
|
||||||
|
margin-bottom: 28px;
|
||||||
|
|
||||||
|
.input {
|
||||||
|
position: relative;
|
||||||
|
height: 36px;
|
||||||
|
|
||||||
|
>i {
|
||||||
|
width: 34px;
|
||||||
|
height: 34px;
|
||||||
|
background: #cfcdcd;
|
||||||
|
color: #fff;
|
||||||
|
position: absolute;
|
||||||
|
left: 1px;
|
||||||
|
top: 1px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 34px;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
padding-left: 44px;
|
||||||
|
border: 1px solid #cfcdcd;
|
||||||
|
height: 36px;
|
||||||
|
line-height: 36px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&.error {
|
||||||
|
border-color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active,
|
||||||
|
&:focus {
|
||||||
|
border-color: blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.code {
|
||||||
|
position: absolute;
|
||||||
|
right: 1px;
|
||||||
|
top: 1px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 34px;
|
||||||
|
font-size: 14px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
color: #666;
|
||||||
|
width: 90px;
|
||||||
|
height: 34px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
>.error {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 28px;
|
||||||
|
color: blue;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.agree {
|
||||||
|
a {
|
||||||
|
color: #069;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 40px;
|
||||||
|
background: blue;
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
background: #cfcdcd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action {
|
||||||
|
padding: 20px 40px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.url {
|
||||||
|
a {
|
||||||
|
color: #999;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.subBtn {
|
||||||
|
background: blue;
|
||||||
|
border-radius: 15px;
|
||||||
|
width: 100%;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
11
tencent/src/views/Message.vue
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
102
tencent/src/views/New.vue
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {onMounted, ref} from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
|
||||||
|
|
||||||
|
const main = ref();
|
||||||
|
onMounted(() => {
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
|
||||||
|
const labelRight = {
|
||||||
|
position: 'right'
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const init = () => {
|
||||||
|
const myChart = echarts.init(main.value);
|
||||||
|
let option = {
|
||||||
|
title: {
|
||||||
|
text: '每日用户新增'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: 80,
|
||||||
|
bottom: 30
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'value',
|
||||||
|
position: 'top',
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
type: 'dashed'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'category',
|
||||||
|
axisLine: { show: false },
|
||||||
|
axisLabel: { show: false },
|
||||||
|
axisTick: { show: false },
|
||||||
|
splitLine: { show: false },
|
||||||
|
data: [
|
||||||
|
'three',
|
||||||
|
'two',
|
||||||
|
'one'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Cost',
|
||||||
|
type: 'bar',
|
||||||
|
stack: 'Total',
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
formatter: '{b}'
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ value: -0.07, label: labelRight },
|
||||||
|
{ value: -0.09, label: labelRight },
|
||||||
|
0.2,
|
||||||
|
0.44,
|
||||||
|
{ value: -0.23, label: labelRight },
|
||||||
|
0.08,
|
||||||
|
{ value: -0.17, label: labelRight },
|
||||||
|
0.47,
|
||||||
|
{ value: -0.36, label: labelRight },
|
||||||
|
0.18
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
myChart.setOption(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>>
|
||||||
|
<div class="echarts">
|
||||||
|
<div style="width: 100%; height: 100%; margin-top: 1rem">
|
||||||
|
<div ref="main" style="width: 100%; height: 100%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.echarts {
|
||||||
|
width: 90%;
|
||||||
|
height: 80%;
|
||||||
|
border-radius: 12px;
|
||||||
|
margin: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: #ffffff;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
186
tencent/src/views/Order.vue
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {ref} from 'vue'
|
||||||
|
import {onMounted} from "vue";
|
||||||
|
import myAxios from "../API/myAxios.ts";
|
||||||
|
import {Action, ElMessage, ElMessageBox} from "element-plus";
|
||||||
|
import { HomeOutlined, UserOutlined } from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
|
||||||
|
const tableData = ref([]);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getUserList();
|
||||||
|
})
|
||||||
|
|
||||||
|
const onSearch = () => {
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
const onReset = () => {
|
||||||
|
searchParams.value.username = '';
|
||||||
|
searchParams.value.phone='';
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = ref({
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
username: '',
|
||||||
|
phone: '',
|
||||||
|
userStatus:0
|
||||||
|
});
|
||||||
|
|
||||||
|
const createTime = (row: any)=> {
|
||||||
|
let data = row.createTime;
|
||||||
|
return data.slice(0,16).replace('T',`~`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getUserList = async () => {
|
||||||
|
const res:any = await myAxios.get("/user/search",{
|
||||||
|
params: {
|
||||||
|
current: searchParams.value.current,
|
||||||
|
pageSize: searchParams.value.pageSize,
|
||||||
|
username: searchParams.value.username,
|
||||||
|
phone: searchParams.value.phone,
|
||||||
|
userStatus: searchParams.value.userStatus
|
||||||
|
}})
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
tableData.value = res.data;
|
||||||
|
} else {
|
||||||
|
ElMessage({
|
||||||
|
type:"error",
|
||||||
|
message: `加载数据失败:${res.message}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const view = () => {
|
||||||
|
ElMessageBox.alert('This is a message', 'Title', {
|
||||||
|
confirmButtonText: 'OK',
|
||||||
|
callback: (action: Action) => {
|
||||||
|
ElMessage({
|
||||||
|
type: 'info',
|
||||||
|
message: `action: ${action}`,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const doDelete =async (id:string) => {
|
||||||
|
const res:any = await myAxios.post("/user/delete",{id:id})
|
||||||
|
ElMessage({
|
||||||
|
showClose:true,
|
||||||
|
type:res.code === 0 ? 'success' : "error",
|
||||||
|
message:res.code === 0 ? '删除成功' : `删除失败:${res.message}`
|
||||||
|
})
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
await getUserList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const doBan =async (id:string, isBan: boolean) => {
|
||||||
|
const res:any = await myAxios.post("/user/update",{id:id, userRole: isBan ? 2 :0})
|
||||||
|
ElMessage({
|
||||||
|
showClose:true,
|
||||||
|
type:res.code === 0 ? 'success' : "error",
|
||||||
|
message:res.code === 0 ? '操作成功' : `操作失败:${res.message}`
|
||||||
|
})
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
await getUserList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(searchParams.value.userStatus===1){
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a-breadcrumb class="header">
|
||||||
|
<a-breadcrumb-item href="">
|
||||||
|
<home-outlined />
|
||||||
|
</a-breadcrumb-item>
|
||||||
|
<a-breadcrumb-item href="">
|
||||||
|
<user-outlined />
|
||||||
|
<span>{{ $route.path }}</span>
|
||||||
|
</a-breadcrumb-item>
|
||||||
|
<a-breadcrumb-item>{{ $route.name }}</a-breadcrumb-item>
|
||||||
|
</a-breadcrumb>
|
||||||
|
|
||||||
|
|
||||||
|
<!--搜索部分-->
|
||||||
|
<div class="search-box">
|
||||||
|
<el-form
|
||||||
|
:inline="true"
|
||||||
|
:model="searchParams"
|
||||||
|
>
|
||||||
|
<el-form-item label="用户名称" class="search">
|
||||||
|
<el-input v-model="searchParams.username" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="手机号" class="search">
|
||||||
|
<el-input v-model="searchParams.phone" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-button type="primary" @click="onSearch" style="margin-top: 10px" color="#4e58fd">搜索</el-button>
|
||||||
|
<el-button type="primary" @click="onReset" style="margin-top: 10px" color="#4e58fd">重置</el-button>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<div class="table">
|
||||||
|
<el-table :data="tableData" style="width: 100%;height: 80%" border stripe>
|
||||||
|
<el-table-column label="订单ID" prop="id"/>
|
||||||
|
<el-table-column label="用户名称" prop="username"/>
|
||||||
|
<el-table-column label="手机号" prop="phone"/>
|
||||||
|
<el-table-column label="订单状态" prop="userStatus" >
|
||||||
|
<template #default="scope">
|
||||||
|
<div v-if="scope.row.userRole === 1">
|
||||||
|
<el-tag type="success">进行中</el-tag>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="scope.row.userRole === 0">
|
||||||
|
<el-tag type="success">已结束</el-tag>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="scope.row.userRole === 2">
|
||||||
|
<el-tag type="warning">已取消</el-tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="入驻时间" prop="createtime" :formatter="createTime"/>
|
||||||
|
<el-table-column align="center" label="操作">
|
||||||
|
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link size="small" type="warning" :disabled="scope.row.userRole === 1"
|
||||||
|
@click="doBan(scope.row.id, scope.row.userRole !== 2)">
|
||||||
|
{{scope.row.userRole === 2? '解封' : '封禁'}}
|
||||||
|
</el-button>
|
||||||
|
<el-button link size="small" type="warning" @click="view">
|
||||||
|
查看
|
||||||
|
</el-button>
|
||||||
|
<el-button link size="small" type="danger" :disabled="scope.row.userRole === 'admin'"
|
||||||
|
@click="doDelete(scope.row.id)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.header {
|
||||||
|
width: 100%;
|
||||||
|
height: 30px;
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
}
|
||||||
|
h4 {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
.search {
|
||||||
|
margin-top: 10px;
|
||||||
|
float: left;
|
||||||
|
width: 20%;
|
||||||
|
height: 7%;
|
||||||
|
}
|
||||||
|
.table {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
1
tencent/src/views/Setting.vue
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<template>系统设置</template>
|
11
tencent/src/views/Signin.vue
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
注册
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
11
tencent/src/views/Statistics.vue
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="Statistics">数据统计</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
11
tencent/src/views/Talk.vue
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="talk">论坛管理</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
48
tencent/src/views/UserList/DialogModule.vue
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:title="title"
|
||||||
|
:visible.sync="isVisible"
|
||||||
|
width="30%"
|
||||||
|
@close="$emit('close')"
|
||||||
|
>
|
||||||
|
<slot></slot>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="isVisible = false">Cancel</el-button>
|
||||||
|
<el-button type="primary" @click="confirm">Confirm</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "CustomDialog",
|
||||||
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
modelValue: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isVisible: this.modelValue,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
modelValue(newValue) {
|
||||||
|
this.isVisible = newValue;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
confirm() {
|
||||||
|
this.$emit("update:modelValue", false);
|
||||||
|
this.$emit("confirm");
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
353
tencent/src/views/UserList/Rider.vue
Normal file
|
@ -0,0 +1,353 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {ref} from 'vue'
|
||||||
|
import {onMounted} from "vue";
|
||||||
|
import myAxios from "../../API/myAxios.ts";
|
||||||
|
import {Action, ElMessage, ElMessageBox} from "element-plus";
|
||||||
|
import { HomeOutlined, UserOutlined } from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
|
||||||
|
const tableData = ref([]);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getUserList();
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const onSearch = () => {
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
const onReset = () => {
|
||||||
|
searchParams.value.username = '';
|
||||||
|
searchParams.value.phone='';
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = ref({
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
username: '',
|
||||||
|
phone: '',
|
||||||
|
userStatus:0
|
||||||
|
});
|
||||||
|
|
||||||
|
const createTime = (row: any)=> {
|
||||||
|
let data = row.createTime;
|
||||||
|
return data.slice(0,16).replace('T',`~`)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const total= ref(0);
|
||||||
|
const getUserList = async () => {
|
||||||
|
const res:any = await myAxios.get("/user/search",{
|
||||||
|
params: {
|
||||||
|
current: searchParams.value.current,
|
||||||
|
pageSize: searchParams.value.pageSize,
|
||||||
|
username: searchParams.value.username,
|
||||||
|
phone: searchParams.value.phone,
|
||||||
|
userStatus: searchParams.value.userStatus
|
||||||
|
}})
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
tableData.value = res.data;
|
||||||
|
total.value = parseInt(res.data.total)
|
||||||
|
} else {
|
||||||
|
ElMessage({
|
||||||
|
type:"error",
|
||||||
|
message: `加载数据失败:${res.message}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const doDelete =async (id:string) => {
|
||||||
|
const res:any = await myAxios.post("/user/delete",{id:id})
|
||||||
|
ElMessage({
|
||||||
|
showClose:true,
|
||||||
|
type:res.code === 0 ? 'success' : "error",
|
||||||
|
message:res.code === 0 ? '删除成功' : `删除失败:${res.message}`
|
||||||
|
})
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
await getUserList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const doBan =async (id:string, isBan: boolean) => {
|
||||||
|
const res:any = await myAxios.post("/user/update",{id:id, userRole: isBan ? 2 :0})
|
||||||
|
ElMessage({
|
||||||
|
showClose:true,
|
||||||
|
type:res.code === 0 ? 'success' : "error",
|
||||||
|
message:res.code === 0 ? '操作成功' : `操作失败:${res.message}`
|
||||||
|
})
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
await getUserList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//分页
|
||||||
|
const handleCurrentChange = (current: number) => {
|
||||||
|
searchParams.value = {
|
||||||
|
...searchParams.value,
|
||||||
|
current: current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleSizeChange = (size: number) => {
|
||||||
|
searchParams.value = {
|
||||||
|
...searchParams.value,
|
||||||
|
pageSize: size
|
||||||
|
}
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(searchParams.value.userStatus===1){
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
* */
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const editorDialogVisible = ref(false)
|
||||||
|
const addForm = ref({
|
||||||
|
avatarUrl: '',
|
||||||
|
userAccount: '',
|
||||||
|
userPassword: '',
|
||||||
|
username: '',
|
||||||
|
})
|
||||||
|
const editorForm:any = ref({
|
||||||
|
avatarUrl: '',
|
||||||
|
email: '',
|
||||||
|
gender: 0,
|
||||||
|
id: 0,
|
||||||
|
isDelete: 0,
|
||||||
|
phone: '',
|
||||||
|
updateTime: '',
|
||||||
|
userAccount: '',
|
||||||
|
userPassword: '',
|
||||||
|
userRole: 0,
|
||||||
|
userStates: 0,
|
||||||
|
username: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const onAdd = async () => {
|
||||||
|
try {
|
||||||
|
const obj = {
|
||||||
|
id: Math.floor(Math.random() * 1000),
|
||||||
|
...addForm.value
|
||||||
|
}
|
||||||
|
console.log('Adding user:', obj); // 添加调试输出
|
||||||
|
const response = await myAxios.post('/user/add', obj)
|
||||||
|
console.log('Response:', response); // 添加调试输出
|
||||||
|
if (response.status === 200) {
|
||||||
|
tableData.value.push(obj)
|
||||||
|
dialogVisible.value = false
|
||||||
|
ElMessage.success('添加成功')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error adding user:', error)
|
||||||
|
ElMessage.error('添加失败,请稍后再试')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
|
||||||
|
const editorRow = (e: any) => {
|
||||||
|
editorDialogVisible.value = true;
|
||||||
|
editorForm.value = { ...e }; // Clone the object to avoid mutating the original data
|
||||||
|
};
|
||||||
|
|
||||||
|
const onEditor = async () => {
|
||||||
|
try {
|
||||||
|
const findIndex = tableData.value.findIndex((item) => item.id === editorForm.value.id);
|
||||||
|
tableData.value[findIndex] = { ...editorForm.value }; // Update the local state
|
||||||
|
|
||||||
|
// Make the API call to update the user on the server
|
||||||
|
await myAxios.post('/user/update', editorForm.value);
|
||||||
|
|
||||||
|
editorDialogVisible.value = false;
|
||||||
|
ElMessage.success('更改成功');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to update user:', error);
|
||||||
|
ElMessage.error('更新失败,请检查您的网络连接或稍后再试。');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<!--面包屑-->
|
||||||
|
<a-breadcrumb class="header">
|
||||||
|
<a-breadcrumb-item href="">
|
||||||
|
<home-outlined />
|
||||||
|
</a-breadcrumb-item>
|
||||||
|
<a-breadcrumb-item href="">
|
||||||
|
<user-outlined />
|
||||||
|
<span>{{ $route.path }}</span>
|
||||||
|
</a-breadcrumb-item>
|
||||||
|
<a-breadcrumb-item>{{ $route.name }}</a-breadcrumb-item>
|
||||||
|
</a-breadcrumb>
|
||||||
|
<!--搜索部分-->
|
||||||
|
<div class="search-box">
|
||||||
|
<el-form
|
||||||
|
:inline="true"
|
||||||
|
:model="searchParams"
|
||||||
|
>
|
||||||
|
<el-form-item label="跑腿姓名" class="search">
|
||||||
|
<el-input v-model="searchParams.username" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="手机号" class="search">
|
||||||
|
<el-input v-model="searchParams.phone" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-button type="primary" @click="onSearch" style="margin-top: 10px" color="#4e58fd">搜索</el-button>
|
||||||
|
<el-button type="primary" @click="onReset" style="margin-top: 10px" color="#4e58fd">重置</el-button>
|
||||||
|
<!--新增-->
|
||||||
|
<el-button type="primary" @click="dialogVisible = true" style="margin-top: 10px" color="#4e58fd">新增</el-button>
|
||||||
|
<el-dialog
|
||||||
|
v-model="dialogVisible"
|
||||||
|
title="添加"
|
||||||
|
width="500"
|
||||||
|
>
|
||||||
|
<el-form>
|
||||||
|
<el-form-item label="ID" label-width="100">
|
||||||
|
<el-input v-model="addForm.avatarUrl"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户名" label-width="100">
|
||||||
|
<el-input v-model="addForm.username"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="账户" label-width="100">
|
||||||
|
<el-input v-model="addForm.userAccount"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="密码" label-width="100">
|
||||||
|
<el-input v-model="addForm.userPassword"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" label-width="100">
|
||||||
|
<el-select v-model="addForm.avatarUrl">
|
||||||
|
<el-option value="0" label="管理员">管理员</el-option>
|
||||||
|
<el-option value="1" label="普通用户">普通用户</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="dialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="onAdd">
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
<!--修改操作-->
|
||||||
|
<el-dialog
|
||||||
|
v-model="editorDialogVisible"
|
||||||
|
title="编辑"
|
||||||
|
width="500"
|
||||||
|
>
|
||||||
|
<el-form>
|
||||||
|
<el-form-item label="ID" label-width="100">
|
||||||
|
<el-input v-model="editorForm.avatarUrl"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户名" label-width="100">
|
||||||
|
<el-input v-model="editorForm.username"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="日期" label-width="100">
|
||||||
|
<el-input v-model="editorForm.userAccount"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="地址" label-width="100">
|
||||||
|
<el-input v-model="editorForm.userPassword"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" label-width="100">
|
||||||
|
<el-select v-model="editorForm.avatarUrl">
|
||||||
|
<el-option value="1" label="普通用户">普通用户</el-option>
|
||||||
|
<el-option value="0" label="管理员">管理员</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="editorDialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="onEditor">
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table">
|
||||||
|
<el-table :data="tableData" style="width: 100%;height: 80%" border stripe>
|
||||||
|
<el-table-column label="骑手ID" prop="id"/>
|
||||||
|
<el-table-column label="骑手姓名" prop="username"/>
|
||||||
|
<el-table-column label="手机号" prop="phone"/>
|
||||||
|
<el-table-column label="状态" prop="userStatus" >
|
||||||
|
<template #default="scope">
|
||||||
|
<div v-if="scope.row.userRole === 1">
|
||||||
|
<el-tag type="success">跑腿中</el-tag>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="scope.row.userRole === 0">
|
||||||
|
<el-tag type="success">跑腿中</el-tag>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="scope.row.userRole === 2">
|
||||||
|
<el-tag type="warning">被封禁</el-tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="订单总量" prop="createtime" :formatter="createTime"/>
|
||||||
|
<el-table-column align="center" label="操作">
|
||||||
|
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link size="small" type="warning" :disabled="scope.row.userRole === 1"
|
||||||
|
@click="doBan(scope.row.id, scope.row.userRole !== 2)">
|
||||||
|
{{scope.row.userRole === 2? '解封' : '封禁'}}
|
||||||
|
</el-button>
|
||||||
|
<el-button link size="small" type="info" @click="editorRow(scope.row)">编辑</el-button>
|
||||||
|
<el-button link size="small" type="danger" :disabled="scope.row.userRole === 'admin'"
|
||||||
|
@click="doDelete(scope.row.id)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="pagination">
|
||||||
|
<el-pagination
|
||||||
|
background
|
||||||
|
:page-size="searchParams.pageSize"
|
||||||
|
:current-page="searchParams.current"
|
||||||
|
layout="total,sizes, prev, pager, next,jumper"
|
||||||
|
:total="total"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
class="pagination"
|
||||||
|
:page-sizes="[10.20]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.header {
|
||||||
|
width: 100%;
|
||||||
|
height: 30px;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
h4 {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
.search {
|
||||||
|
margin-top: 10px;
|
||||||
|
float: left;
|
||||||
|
width: 20%;
|
||||||
|
height: 7%;
|
||||||
|
}
|
||||||
|
.table {
|
||||||
|
width: 100%;
|
||||||
|
height: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
214
tencent/src/views/UserList/merchant.vue
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {ref} from 'vue'
|
||||||
|
import {onMounted} from "vue";
|
||||||
|
import myAxios from "../../API/myAxios.ts";
|
||||||
|
import {Action, ElMessage, ElMessageBox} from "element-plus";
|
||||||
|
import { HomeOutlined, UserOutlined } from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
const total= ref(0);
|
||||||
|
//时间处理
|
||||||
|
const tableData = ref([]);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getUserList();
|
||||||
|
})
|
||||||
|
|
||||||
|
const onSearch = () => {
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
const onReset = () => {
|
||||||
|
searchParams.value.businessName = '';
|
||||||
|
searchParams.value.businessPhone='';
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = ref({
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
businessName: '',
|
||||||
|
businessPhone: '',
|
||||||
|
storeStatus:0
|
||||||
|
});
|
||||||
|
|
||||||
|
const createTime = (row: any)=> {
|
||||||
|
let data = row.createTime;
|
||||||
|
return data.slice(0,16).replace('T',`~`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getUserList = async () => {
|
||||||
|
const res:any = await myAxios.post("/business/list",{
|
||||||
|
params: {
|
||||||
|
current: searchParams.value.current,
|
||||||
|
pageSize: searchParams.value.pageSize,
|
||||||
|
businessName: searchParams.value.businessName,
|
||||||
|
phone: searchParams.value.businessPhone,
|
||||||
|
storeStatus: searchParams.value.storeStatus
|
||||||
|
}})
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
tableData.value = res.data;
|
||||||
|
total.value = parseInt(res.data.total)
|
||||||
|
} else {
|
||||||
|
ElMessage({
|
||||||
|
type:"error",
|
||||||
|
message: `加载数据失败:${res.message}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//查看
|
||||||
|
const view = () => {
|
||||||
|
ElMessageBox.alert('This is a message', 'Title', {
|
||||||
|
confirmButtonText: 'OK',
|
||||||
|
callback: (action: Action) => {
|
||||||
|
ElMessage({
|
||||||
|
type: 'info',
|
||||||
|
message: `action: ${action}`,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const doDelete =async (id:string) => {
|
||||||
|
const res:any = await myAxios.post("/user/delete",{id:id})
|
||||||
|
ElMessage({
|
||||||
|
showClose:true,
|
||||||
|
type:res.code === 0 ? 'success' : "error",
|
||||||
|
message:res.code === 0 ? '删除成功' : `删除失败:${res.message}`
|
||||||
|
})
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
await getUserList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//分页
|
||||||
|
const handleCurrentChange = (current: number) => {
|
||||||
|
searchParams.value = {
|
||||||
|
...searchParams.value,
|
||||||
|
current: current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleSizeChange = (size: number) => {
|
||||||
|
searchParams.value = {
|
||||||
|
...searchParams.value,
|
||||||
|
pageSize: size
|
||||||
|
}
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
const doBan =async (id:string, isBan: boolean) => {
|
||||||
|
const res:any = await myAxios.post("/user/update",{id:id, userRole: isBan ? 2 :0})
|
||||||
|
ElMessage({
|
||||||
|
showClose:true,
|
||||||
|
type:res.code === 0 ? 'success' : "error",
|
||||||
|
message:res.code === 0 ? '操作成功' : `操作失败:${res.message}`
|
||||||
|
})
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
await getUserList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(searchParams.value.storeStatus===1){
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a-breadcrumb class="header">
|
||||||
|
<a-breadcrumb-item href="">
|
||||||
|
<home-outlined />
|
||||||
|
</a-breadcrumb-item>
|
||||||
|
<a-breadcrumb-item href="">
|
||||||
|
<user-outlined />
|
||||||
|
<span>{{ $route.path }}</span>
|
||||||
|
</a-breadcrumb-item>
|
||||||
|
<a-breadcrumb-item>{{ $route.name }}</a-breadcrumb-item>
|
||||||
|
</a-breadcrumb>
|
||||||
|
|
||||||
|
<!--搜索部分-->
|
||||||
|
<div class="search-box">
|
||||||
|
<el-form
|
||||||
|
:inline="true"
|
||||||
|
:model="searchParams"
|
||||||
|
>
|
||||||
|
<el-form-item label="商户名称" class="search">
|
||||||
|
<el-input v-model="searchParams.businessName" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="手机号" class="search">
|
||||||
|
<el-input v-model="searchParams.businessPhone" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-button type="primary" @click="onSearch" style="margin-top: 10px" color="#4e58fd">搜索</el-button>
|
||||||
|
<el-button type="primary" @click="onReset" style="margin-top: 10px" color="#4e58fd">重置</el-button>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<div class="table">
|
||||||
|
<el-table :data="tableData" style="width: 100%;height: 80%" border stripe>
|
||||||
|
<el-table-column label="商户ID" prop="id"/>
|
||||||
|
<el-table-column label="商户名称" prop="businessName"/>
|
||||||
|
<el-table-column label="手机号" prop="businessPhone"/>
|
||||||
|
<el-table-column label="店铺状态" prop="storeStatus" >
|
||||||
|
<template #default="scope">
|
||||||
|
<div v-if="scope.row.storeStatus === 1">
|
||||||
|
<el-tag type="success">正常</el-tag>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="scope.row.storeStatus === 0">
|
||||||
|
<el-tag type="success">正常</el-tag>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="scope.row.storeStatus === 2">
|
||||||
|
<el-tag type="warning">封店</el-tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="入驻时间" prop="createtime" :formatter="createTime"/>
|
||||||
|
<el-table-column align="center" label="操作">
|
||||||
|
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link size="small" type="warning" :disabled="scope.row.userRole === 1"
|
||||||
|
@click="doBan(scope.row.id, scope.row.userRole !== 2)">
|
||||||
|
{{scope.row.userRole === 2? '解封' : '封禁'}}
|
||||||
|
</el-button>
|
||||||
|
<el-button link size="small" type="warning" @click="view">
|
||||||
|
查看
|
||||||
|
</el-button>
|
||||||
|
<el-button link size="small" type="danger" :disabled="scope.row.userRole === 'admin'"
|
||||||
|
@click="doDelete(scope.row.id)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="pagination">
|
||||||
|
<el-pagination
|
||||||
|
background
|
||||||
|
:page-size="searchParams.pageSize"
|
||||||
|
:current-page="searchParams.current"
|
||||||
|
layout="total,sizes, prev, pager, next,jumper"
|
||||||
|
:total="total"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
class="pagination"
|
||||||
|
:page-sizes="[10.20]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.header {
|
||||||
|
width: 100%;
|
||||||
|
height: 30px;
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
}
|
||||||
|
h4 {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
.search {
|
||||||
|
margin-top: 10px;
|
||||||
|
float: left;
|
||||||
|
width: 20%;
|
||||||
|
height: 7%;
|
||||||
|
}
|
||||||
|
.table {
|
||||||
|
width: 100%;
|
||||||
|
height: 80%;
|
||||||
|
}
|
||||||
|
</style>
|
379
tencent/src/views/UserList/user.vue
Normal file
|
@ -0,0 +1,379 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {reactive, ref} from 'vue'
|
||||||
|
import {onMounted} from "vue";
|
||||||
|
import myAxios from "../../API/myAxios.ts";
|
||||||
|
import {Action, ElMessage, ElMessageBox} from "element-plus";
|
||||||
|
import { HomeOutlined, UserOutlined } from '@ant-design/icons-vue';
|
||||||
|
const current1 = ref<number>(1);
|
||||||
|
const onChange = (pageNumber: number) => {
|
||||||
|
console.log('Page: ', pageNumber);
|
||||||
|
};
|
||||||
|
|
||||||
|
//时间处理
|
||||||
|
const tableData = ref([]);
|
||||||
|
//分页
|
||||||
|
const total= ref(0);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getUserList();
|
||||||
|
})
|
||||||
|
|
||||||
|
const onSearch = () => {
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
const onReset = () => {
|
||||||
|
searchParams.value.username = '';
|
||||||
|
searchParams.value.phone='';
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = ref({
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
username: '',
|
||||||
|
phone: '',
|
||||||
|
userStatus:0,
|
||||||
|
email:''
|
||||||
|
});
|
||||||
|
const getUserList = async () => {
|
||||||
|
const res:any = await myAxios.get("/user/search",{
|
||||||
|
params: {
|
||||||
|
current: searchParams.value.current,
|
||||||
|
pageSize: searchParams.value.pageSize,
|
||||||
|
username: searchParams.value.username,
|
||||||
|
phone: searchParams.value.phone,
|
||||||
|
userStatus: searchParams.value.userStatus,
|
||||||
|
email: searchParams.value.email
|
||||||
|
}})
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
tableData.value = res.data;
|
||||||
|
total.value = parseInt(res.data.total)
|
||||||
|
} else {
|
||||||
|
ElMessage({
|
||||||
|
type:"error",
|
||||||
|
message: `加载数据失败:${res.message}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//查看
|
||||||
|
const view = () => {
|
||||||
|
ElMessageBox.alert('This is a message', 'Title', {
|
||||||
|
// if you want to disable its autofocus
|
||||||
|
//autofocus: false,
|
||||||
|
confirmButtonText: 'OK',
|
||||||
|
callback: (action: Action) => {
|
||||||
|
ElMessage({
|
||||||
|
type: 'info',
|
||||||
|
message: `action: ${action}`,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const doDelete =async (id:string) => {
|
||||||
|
const res:any = await myAxios.post("/user/delete",{id:id})
|
||||||
|
ElMessage({
|
||||||
|
showClose:true,
|
||||||
|
type:res.code === 0 ? 'success' : "error",
|
||||||
|
message:res.code === 0 ? '删除成功' : `删除失败:${res.message}`
|
||||||
|
})
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
await getUserList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
changed: true,
|
||||||
|
value2:true,
|
||||||
|
value3:true,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const doBan =async (id:string, isBan: boolean) => {
|
||||||
|
const res:any = await myAxios.post("/user/update",{id:id, userRole: isBan ? 2 :0})
|
||||||
|
ElMessage({
|
||||||
|
showClose:true,
|
||||||
|
type:res.code === 0 ? 'success' : "error",
|
||||||
|
message:res.code === 0 ? '操作成功' : `操作失败:${res.message}`
|
||||||
|
})
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
await getUserList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//分页
|
||||||
|
const handleCurrentChange = (current: number) => {
|
||||||
|
searchParams.value = {
|
||||||
|
...searchParams.value,
|
||||||
|
current: current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleSizeChange = (size: number) => {
|
||||||
|
searchParams.value = {
|
||||||
|
...searchParams.value,
|
||||||
|
pageSize: size
|
||||||
|
}
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增
|
||||||
|
* */
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const editorDialogVisible = ref(false)
|
||||||
|
const addForm = ref({
|
||||||
|
avatarUrl: '',
|
||||||
|
userAccount: '',
|
||||||
|
userPassword: '',
|
||||||
|
username: '',
|
||||||
|
})
|
||||||
|
const editorForm:any = ref({
|
||||||
|
avatarUrl: '',
|
||||||
|
email: '',
|
||||||
|
gender: 0,
|
||||||
|
id: 0,
|
||||||
|
isDelete: 0,
|
||||||
|
phone: '',
|
||||||
|
updateTime: '',
|
||||||
|
userAccount: '',
|
||||||
|
userPassword: '',
|
||||||
|
userRole: 0,
|
||||||
|
userStates: 0,
|
||||||
|
username: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const onAdd = async () => {
|
||||||
|
try {
|
||||||
|
const obj = {
|
||||||
|
id: Math.floor(Math.random() * 1000),
|
||||||
|
...addForm.value
|
||||||
|
}
|
||||||
|
console.log('Adding user:', obj); // 添加调试输出
|
||||||
|
const response = await myAxios.post('/user/add', obj)
|
||||||
|
console.log('Response:', response); // 添加调试输出
|
||||||
|
if (response.status === 200) {
|
||||||
|
tableData.value.push(obj)
|
||||||
|
dialogVisible.value = false
|
||||||
|
ElMessage.success('添加成功')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error adding user:', error)
|
||||||
|
ElMessage.error('添加失败,请稍后再试')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onMounted(onAdd)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑
|
||||||
|
* const editorRow = (e:any) => {
|
||||||
|
* editorDialogVisible.value = true
|
||||||
|
* editorForm.value = e
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* const onEditor = async () => {
|
||||||
|
* try {
|
||||||
|
* const response = await axios.put('/api/user/update', editorForm.value);
|
||||||
|
*
|
||||||
|
* if (response.status === 200) {
|
||||||
|
* const findIndex = tableData.value.findIndex(item => item.id === editorForm.value.id);
|
||||||
|
* tableData.value[findIndex] = editorForm.value;
|
||||||
|
* editorDialogVisible.value = false;
|
||||||
|
* ElMessage.success('更改成功');
|
||||||
|
* } else {
|
||||||
|
* ElMessage.error('更新失败,请稍后重试');
|
||||||
|
* }
|
||||||
|
* } catch (error) {
|
||||||
|
* console.error(error);
|
||||||
|
* ElMessage.error('服务器错误,请稍后重试');
|
||||||
|
* }
|
||||||
|
* };
|
||||||
|
* */
|
||||||
|
|
||||||
|
const editorRow = (e: any) => {
|
||||||
|
editorDialogVisible.value = true;
|
||||||
|
editorForm.value = { ...e }; // Clone the object to avoid mutating the original data
|
||||||
|
};
|
||||||
|
|
||||||
|
const onEditor = async () => {
|
||||||
|
try {
|
||||||
|
const findIndex = tableData.value.findIndex((item) => item.id === editorForm.value.id);
|
||||||
|
tableData.value[findIndex] = { ...editorForm.value }; // Update the local state
|
||||||
|
|
||||||
|
// Make the API call to update the user on the server
|
||||||
|
await myAxios.post('/user/update', editorForm.value);
|
||||||
|
|
||||||
|
editorDialogVisible.value = false;
|
||||||
|
ElMessage.success('更改成功');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to update user:', error);
|
||||||
|
ElMessage.error('更新失败,请检查您的网络连接或稍后再试。');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<!--面包屑-->
|
||||||
|
<a-breadcrumb class="header">
|
||||||
|
<a-breadcrumb-item href="">
|
||||||
|
<home-outlined />
|
||||||
|
</a-breadcrumb-item>
|
||||||
|
<a-breadcrumb-item href="">
|
||||||
|
<user-outlined />
|
||||||
|
<span>{{ $route.path }}</span>
|
||||||
|
</a-breadcrumb-item>
|
||||||
|
<a-breadcrumb-item>{{ $route.name }}</a-breadcrumb-item>
|
||||||
|
</a-breadcrumb>
|
||||||
|
<!--搜索部分-->
|
||||||
|
<div class="search-box">
|
||||||
|
<el-form
|
||||||
|
:inline="true"
|
||||||
|
:model="searchParams"
|
||||||
|
>
|
||||||
|
<el-form-item label="学生姓名" class="search">
|
||||||
|
<el-input v-model="searchParams.username" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="手机号" class="search">
|
||||||
|
<el-input v-model="searchParams.phone" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-button type="primary" @click="onSearch" style="margin-top: 10px" color="#4e58fd">搜索</el-button>
|
||||||
|
<el-button type="primary" @click="onReset" style="margin-top: 10px" color="#4e58fd">重置</el-button>
|
||||||
|
<!--新增-->
|
||||||
|
<el-button type="primary" @click="dialogVisible = true" style="margin-top: 10px" color="#4e58fd">新增</el-button>
|
||||||
|
<el-dialog
|
||||||
|
v-model="dialogVisible"
|
||||||
|
title="添加"
|
||||||
|
width="500"
|
||||||
|
>
|
||||||
|
<el-form>
|
||||||
|
<el-form-item label="ID" label-width="100">
|
||||||
|
<el-input v-model="addForm.avatarUrl"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户名" label-width="100">
|
||||||
|
<el-input v-model="addForm.username"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="账户" label-width="100">
|
||||||
|
<el-input v-model="addForm.userAccount"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="密码" label-width="100">
|
||||||
|
<el-input v-model="addForm.userPassword"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" label-width="100">
|
||||||
|
<el-select v-model="addForm.avatarUrl">
|
||||||
|
<el-option value="0" label="管理员">管理员</el-option>
|
||||||
|
<el-option value="1" label="普通用户">普通用户</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="dialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="onAdd">
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
<!--修改操作-->
|
||||||
|
<el-dialog
|
||||||
|
v-model="editorDialogVisible"
|
||||||
|
title="编辑"
|
||||||
|
width="500"
|
||||||
|
>
|
||||||
|
<el-form>
|
||||||
|
<el-form-item label="ID" label-width="100">
|
||||||
|
<el-input v-model="editorForm.avatarUrl"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户名" label-width="100">
|
||||||
|
<el-input v-model="editorForm.username"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="日期" label-width="100">
|
||||||
|
<el-input v-model="editorForm.userAccount"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="地址" label-width="100">
|
||||||
|
<el-input v-model="editorForm.userPassword"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" label-width="100">
|
||||||
|
<el-select v-model="editorForm.avatarUrl">
|
||||||
|
<el-option value="1" label="普通用户">普通用户</el-option>
|
||||||
|
<el-option value="0" label="管理员">管理员</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="editorDialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="onEditor">
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="table" v-if="state.changed">
|
||||||
|
<el-table :data="tableData" style="width: 100%;height: 80%" border stripe>
|
||||||
|
<el-table-column label="学生学号" prop="id"/>
|
||||||
|
<el-table-column label="学生姓名" prop="username"/>
|
||||||
|
<el-table-column label="联系电话" prop="phone"/>
|
||||||
|
<el-table-column label="邮箱" prop="email"/>
|
||||||
|
<el-table-column prop="userRole" label="身份" align="center" width="100">
|
||||||
|
<template #default="scope">
|
||||||
|
<div v-if="scope.row.userRole === 1">
|
||||||
|
<el-tag>管理员</el-tag>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="scope.row.userRole === 0">
|
||||||
|
<el-tag type="success">普通用户</el-tag>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="scope.row.userRole === 2">
|
||||||
|
<el-tag type="warning">被封禁</el-tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" label="操作">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link size="small" type="warning" :disabled="scope.row.userRole === 1"
|
||||||
|
@click="doBan(scope.row.id, scope.row.userRole !== 2)">
|
||||||
|
{{scope.row.userRole === 2? '解封' : '封禁'}}
|
||||||
|
</el-button>
|
||||||
|
<el-button link size="small" type="info" @click="editorRow(scope.row)">编辑</el-button>
|
||||||
|
<el-button link size="small" type="danger" :disabled="scope.row.userRole === 1"
|
||||||
|
@click="doDelete(scope.row.id)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!--分页查询-->
|
||||||
|
<div>
|
||||||
|
<a-pagination v-model:current="current1" show-quick-jumper :total="500" @change="onChange" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.header {
|
||||||
|
width: 100%;
|
||||||
|
height: 30px;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
h4 {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
.search {
|
||||||
|
margin-top: 10px;
|
||||||
|
float: left;
|
||||||
|
width: 20%;
|
||||||
|
height: 7%;
|
||||||
|
}
|
||||||
|
.table {
|
||||||
|
width: 100%;
|
||||||
|
height: 80%;
|
||||||
|
}
|
||||||
|
.pagination {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
</style>
|
2
tencent/src/views/analysis/Behavior.vue
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
<template>用户行为分析</template>
|
||||||
|
<script></script>
|
11
tencent/src/views/analysis/Order.vue
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="Order">订单分析</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
1
tencent/src/views/analysis/evaluate.vue
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<template>评分分析</template>
|
11
tencent/src/views/analysis/points.vue
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="points">积分活动分析</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
190
tencent/src/views/echart/BrokenLine.vue
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {onMounted, ref} from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
|
||||||
|
|
||||||
|
const main = ref();
|
||||||
|
onMounted(() => {
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
|
||||||
|
const init = () => {
|
||||||
|
const myChart = echarts.init(main.value);
|
||||||
|
let option = {
|
||||||
|
color: ['#80FFA5', '#00DDFF', '#37A2FF', '#FF0087', '#FFBF00'],
|
||||||
|
title: {
|
||||||
|
text: '数据表'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'cross',
|
||||||
|
label: {
|
||||||
|
backgroundColor: '#6a7985'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['好评点赞量', 'App点击量', '订单生产量', '活跃用户量']
|
||||||
|
},
|
||||||
|
toolbox: {
|
||||||
|
feature: {
|
||||||
|
saveAsImage: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'value'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '好评点赞量',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
smooth: true,
|
||||||
|
lineStyle: {
|
||||||
|
width: 0
|
||||||
|
},
|
||||||
|
showSymbol: false,
|
||||||
|
areaStyle: {
|
||||||
|
opacity: 0.8,
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgb(128, 255, 165)'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: 'rgb(1, 191, 236)'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series'
|
||||||
|
},
|
||||||
|
data: [140, 232, 101, 264, 90, 340, 250]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'App点击量',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
smooth: true,
|
||||||
|
lineStyle: {
|
||||||
|
width: 0
|
||||||
|
},
|
||||||
|
showSymbol: false,
|
||||||
|
areaStyle: {
|
||||||
|
opacity: 0.8,
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgb(0, 221, 255)'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: 'rgb(77, 119, 255)'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series'
|
||||||
|
},
|
||||||
|
data: [120, 282, 111, 234, 220, 340, 310]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '订单生产量',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
smooth: true,
|
||||||
|
lineStyle: {
|
||||||
|
width: 0
|
||||||
|
},
|
||||||
|
showSymbol: false,
|
||||||
|
areaStyle: {
|
||||||
|
opacity: 0.8,
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgb(55, 162, 255)'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: 'rgb(116, 21, 219)'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series'
|
||||||
|
},
|
||||||
|
data: [320, 132, 201, 334, 190, 130, 220]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '活跃用户量',
|
||||||
|
type: 'line',
|
||||||
|
stack: 'Total',
|
||||||
|
smooth: true,
|
||||||
|
lineStyle: {
|
||||||
|
width: 0
|
||||||
|
},
|
||||||
|
showSymbol: false,
|
||||||
|
areaStyle: {
|
||||||
|
opacity: 0.8,
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: 'rgb(255, 0, 135)'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: 'rgb(135, 0, 157)'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series'
|
||||||
|
},
|
||||||
|
data: [220, 402, 231, 134, 190, 230, 120]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
myChart.setOption(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="echarts">
|
||||||
|
<div style="width: 100%; height: 100%; margin-top: 1rem">
|
||||||
|
|
||||||
|
<div ref="main" style="width: 100%; height: 100%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.echarts {
|
||||||
|
width: 90%;
|
||||||
|
height: 80%;
|
||||||
|
border-radius: 12px;
|
||||||
|
margin: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: #ffffff;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
124
tencent/src/views/echart/Pie.vue
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
import {onMounted, ref} from "vue";
|
||||||
|
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
|
||||||
|
|
||||||
|
const main = ref();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const init = () => {
|
||||||
|
const myChart = echarts.init(main.value);
|
||||||
|
|
||||||
|
let option = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
formatter: '{a} <br/>{b}: {c} ({d}%)'
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: [
|
||||||
|
'网上交易',
|
||||||
|
'App点击',
|
||||||
|
'骑手上门',
|
||||||
|
'其他',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Access From',
|
||||||
|
type: 'pie',
|
||||||
|
selectedMode: 'single',
|
||||||
|
radius: [0, '30%'],
|
||||||
|
label: {
|
||||||
|
position: 'inner',
|
||||||
|
fontSize: 14
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ value: 1548, name: 'Search Engine' },
|
||||||
|
{ value: 775, name: 'Direct' },
|
||||||
|
{ value: 679, name: 'Marketing', selected: true }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Access From',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['45%', '60%'],
|
||||||
|
labelLine: {
|
||||||
|
length: 30
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
formatter: '{a|{a}}{abg|}\n{hr|}\n {b|{b}:}{c} {per|{d}%} ',
|
||||||
|
backgroundColor: '#F6F8FC',
|
||||||
|
borderColor: '#8C8D8E',
|
||||||
|
borderWidth: 1,
|
||||||
|
borderRadius: 4,
|
||||||
|
rich: {
|
||||||
|
a: {
|
||||||
|
color: '#6E7079',
|
||||||
|
lineHeight: 22,
|
||||||
|
align: 'center'
|
||||||
|
},
|
||||||
|
hr: {
|
||||||
|
borderColor: '#8C8D8E',
|
||||||
|
width: '100%',
|
||||||
|
borderWidth: 1,
|
||||||
|
height: 0
|
||||||
|
},
|
||||||
|
b: {
|
||||||
|
color: '#4C5058',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: 'bold',
|
||||||
|
lineHeight: 33
|
||||||
|
},
|
||||||
|
per: {
|
||||||
|
color: '#fff',
|
||||||
|
backgroundColor: '#4C5058',
|
||||||
|
padding: [3, 4],
|
||||||
|
borderRadius: 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ value: 1048, name: '网上交易' },
|
||||||
|
{ value: 335, name: 'App点击' },
|
||||||
|
{ value: 310, name: '骑手上门' },
|
||||||
|
{ value: 251, name: '其他' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
myChart.setOption(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="echarts">
|
||||||
|
<div style="width: 100%; height: 100%; margin-top: 1rem">
|
||||||
|
<div ref="main" style="width: 100%; height: 100%"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.echarts {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 12px;
|
||||||
|
margin: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: #ffffff;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
76
tencent/src/views/echart/Trading.vue
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
import {onMounted, ref} from "vue";
|
||||||
|
import * as echarts from "echarts";
|
||||||
|
|
||||||
|
|
||||||
|
const main = ref();
|
||||||
|
onMounted(() => {
|
||||||
|
init();
|
||||||
|
});
|
||||||
|
|
||||||
|
const init = () => {
|
||||||
|
const myChart = echarts.init(main.value);
|
||||||
|
let option = {
|
||||||
|
title: {
|
||||||
|
text: '工作交易统计'
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['外卖类', '跑腿类']
|
||||||
|
},
|
||||||
|
radar: {
|
||||||
|
indicator: [
|
||||||
|
{ name: '周一', max: 6500 },
|
||||||
|
{ name: '周二', max: 16000 },
|
||||||
|
{ name: '周三', max: 30000 },
|
||||||
|
{ name: '周四', max: 38000 },
|
||||||
|
{ name: '周五', max: 52000 },
|
||||||
|
{ name: '周六', max: 25000 }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'Budget vs spending',
|
||||||
|
type: 'radar',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
value: [4200, 3000, 20000, 35000, 50000, 18000],
|
||||||
|
name: '外卖类'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: [5000, 14000, 28000, 26000, 42000, 21000],
|
||||||
|
name: '跑腿类'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
myChart.setOption(option);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="echarts">
|
||||||
|
<div style="width: 100%; height: 100%; margin-top: 1rem">
|
||||||
|
<div ref="main" style="width: 100%; height: 100%" class="center"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.echarts {
|
||||||
|
margin:10px auto;
|
||||||
|
width: 80%;
|
||||||
|
height: 90%;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: #ffffff;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.center {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
98
tencent/src/views/forum/Notification.vue
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
<template>
|
||||||
|
<a-breadcrumb class="header">
|
||||||
|
<a-breadcrumb-item href="">
|
||||||
|
<home-outlined />
|
||||||
|
</a-breadcrumb-item>
|
||||||
|
<a-breadcrumb-item href="">
|
||||||
|
<user-outlined />
|
||||||
|
<span>{{ $route.path }}</span>
|
||||||
|
</a-breadcrumb-item>
|
||||||
|
<a-breadcrumb-item>{{ $route.name }}</a-breadcrumb-item>
|
||||||
|
</a-breadcrumb>
|
||||||
|
<el-table :data="tableData" stripe style="width: 100%">
|
||||||
|
<el-table-column prop="title" label="公告标题" width="400" />
|
||||||
|
<el-table-column prop="name" label="管理员" width="180" />
|
||||||
|
<el-table-column label="状态" >
|
||||||
|
<el-tag type="success">正常</el-tag>
|
||||||
|
</el-table-column>>
|
||||||
|
<el-table-column prop="address" label="操作">
|
||||||
|
<el-tag type="warning">封禁</el-tag>
|
||||||
|
<el-tag type="info">查看</el-tag>
|
||||||
|
<el-tag type="danger">删除</el-tag>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { HomeOutlined, UserOutlined } from '@ant-design/icons-vue';
|
||||||
|
const tableData = [
|
||||||
|
{
|
||||||
|
title: '重要通知:系统维护升级时间安排',
|
||||||
|
name: '小明',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '社区新规则:共同维护我们的网络环境',
|
||||||
|
name: '小李',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '公告:用户协议更新,请所有成员查阅',
|
||||||
|
name: '小红',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '活动预告:年度用户大会即将开启,精彩不容错过',
|
||||||
|
name: '小张',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '温馨提示:保护个人信息安全的小贴士',
|
||||||
|
name: '小张',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '新功能上线:优化您的用户体验',
|
||||||
|
name: '小张',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '积分奖励计划:参与社区活动获得更多福利',
|
||||||
|
name: '小张',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户反馈精选:我们正在倾听并持续改进',
|
||||||
|
name: '小张',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '公告:用户协议更新,请所有成员查阅',
|
||||||
|
name: '小红',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '活动预告:年度用户大会即将开启,精彩不容错过',
|
||||||
|
name: '小张',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '温馨提示:保护个人信息安全的小贴士',
|
||||||
|
name: '小张',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '新功能上线:优化您的用户体验',
|
||||||
|
name: '小张',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '积分奖励计划:参与社区活动获得更多福利',
|
||||||
|
name: '小张',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户反馈精选:我们正在倾听并持续改进',
|
||||||
|
name: '小张',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.header {
|
||||||
|
width: 100%;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
background-color: white;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
192
tencent/src/views/forum/PostManage.vue
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {ref} from 'vue'
|
||||||
|
import {onMounted} from "vue";
|
||||||
|
import myAxios from "../../API/myAxios.ts";
|
||||||
|
import {Action, ElMessage, ElMessageBox} from "element-plus";
|
||||||
|
import { HomeOutlined, UserOutlined } from '@ant-design/icons-vue';
|
||||||
|
|
||||||
|
|
||||||
|
const tableData = ref([]);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getUserList();
|
||||||
|
})
|
||||||
|
|
||||||
|
const onSearch = () => {
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
const onReset = () => {
|
||||||
|
searchParams.value.username = '';
|
||||||
|
searchParams.value.phone='';
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchParams = ref({
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
username: '',
|
||||||
|
phone: '',
|
||||||
|
userStatus:0
|
||||||
|
});
|
||||||
|
|
||||||
|
const createTime = (row: any)=> {
|
||||||
|
let data = row.createTime;
|
||||||
|
return data.slice(0,16).replace('T',`~`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const getUserList = async () => {
|
||||||
|
const res:any = await myAxios.get("/user/search",{
|
||||||
|
params: {
|
||||||
|
current: searchParams.value.current,
|
||||||
|
pageSize: searchParams.value.pageSize,
|
||||||
|
username: searchParams.value.username,
|
||||||
|
phone: searchParams.value.phone,
|
||||||
|
userStatus: searchParams.value.userStatus
|
||||||
|
}})
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
tableData.value = res.data;
|
||||||
|
//total.value = parseInt(res.data.total)
|
||||||
|
} else {
|
||||||
|
ElMessage({
|
||||||
|
type:"error",
|
||||||
|
message: `加载数据失败:${res.message}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//查看
|
||||||
|
const view = () => {
|
||||||
|
ElMessageBox.alert('This is a message', 'Title', {
|
||||||
|
// if you want to disable its autofocus
|
||||||
|
//autofocus: false,
|
||||||
|
confirmButtonText: 'OK',
|
||||||
|
callback: (action: Action) => {
|
||||||
|
ElMessage({
|
||||||
|
type: 'info',
|
||||||
|
message: `action: ${action}`,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const doDelete =async (id:string) => {
|
||||||
|
const res:any = await myAxios.post("/user/delete",{id:id})
|
||||||
|
ElMessage({
|
||||||
|
showClose:true,
|
||||||
|
type:res.code === 0 ? 'success' : "error",
|
||||||
|
message:res.code === 0 ? '删除成功' : `删除失败:${res.message}`
|
||||||
|
})
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
await getUserList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const doBan =async (id:string, isBan: boolean) => {
|
||||||
|
const res:any = await myAxios.post("/user/update",{id:id, userRole: isBan ? 2 :0})
|
||||||
|
ElMessage({
|
||||||
|
showClose:true,
|
||||||
|
type:res.code === 0 ? 'success' : "error",
|
||||||
|
message:res.code === 0 ? '操作成功' : `操作失败:${res.message}`
|
||||||
|
})
|
||||||
|
if(res.code === 0 && res.data) {
|
||||||
|
await getUserList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(searchParams.value.userStatus===1){
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<a-breadcrumb class="header">
|
||||||
|
<a-breadcrumb-item href="">
|
||||||
|
<home-outlined />
|
||||||
|
</a-breadcrumb-item>
|
||||||
|
<a-breadcrumb-item href="">
|
||||||
|
<user-outlined />
|
||||||
|
<span>{{ $route.path }}</span>
|
||||||
|
</a-breadcrumb-item>
|
||||||
|
<a-breadcrumb-item>{{ $route.name }}</a-breadcrumb-item>
|
||||||
|
</a-breadcrumb>
|
||||||
|
|
||||||
|
|
||||||
|
<!--搜索部分-->
|
||||||
|
<div class="search-box">
|
||||||
|
<el-form
|
||||||
|
:inline="true"
|
||||||
|
:model="searchParams"
|
||||||
|
>
|
||||||
|
<el-form-item label="姓名" class="search">
|
||||||
|
<el-input v-model="searchParams.username" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="手机号" class="search">
|
||||||
|
<el-input v-model="searchParams.phone" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-button type="primary" @click="onSearch" style="margin-top: 10px" color="#4e58fd">搜索</el-button>
|
||||||
|
<el-button type="primary" @click="onReset" style="margin-top: 10px" color="#4e58fd">重置</el-button>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<div class="table">
|
||||||
|
<el-table :data="tableData" style="width: 100%;height: 80%" border stripe>
|
||||||
|
<el-table-column label="日期" prop="createtime" :formatter="createTime"/>
|
||||||
|
<el-table-column label="用户ID" prop="id"/>
|
||||||
|
<el-table-column label="姓名" prop="username"/>
|
||||||
|
<el-table-column label="帖子ID" prop="phone" ></el-table-column>
|
||||||
|
|
||||||
|
<el-table-column label="帖子标题" prop="username"/>
|
||||||
|
<el-table-column label="帖子状态" prop="userStatus">
|
||||||
|
<template #default="scope">
|
||||||
|
<div v-if="scope.row.userRole === 1">
|
||||||
|
<el-tag type="success">正常</el-tag>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="scope.row.userRole === 0">
|
||||||
|
<el-tag type="success">正常</el-tag>
|
||||||
|
</div>
|
||||||
|
<div v-else-if="scope.row.userRole === 2">
|
||||||
|
<el-tag type="warning">封店</el-tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column align="center" label="操作">
|
||||||
|
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button link size="small" type="warning" :disabled="scope.row.userRole === 1"
|
||||||
|
@click="doBan(scope.row.id, scope.row.userRole !== 2)">
|
||||||
|
{{scope.row.userRole === 2? '解封' : '封禁'}}
|
||||||
|
</el-button>
|
||||||
|
<el-button link size="small" type="warning" @click="view">
|
||||||
|
查看
|
||||||
|
</el-button>
|
||||||
|
<el-button link size="small" type="danger" :disabled="scope.row.userRole === 'admin'"
|
||||||
|
@click="doDelete(scope.row.id)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.header {
|
||||||
|
width: 100%;
|
||||||
|
height: 30px;
|
||||||
|
background-color: white;
|
||||||
|
|
||||||
|
}
|
||||||
|
h4 {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
.search {
|
||||||
|
margin-top: 10px;
|
||||||
|
float: left;
|
||||||
|
width: 20%;
|
||||||
|
height: 7%;
|
||||||
|
}
|
||||||
|
.table {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
64
tencent/src/views/sort.vue
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
<template>
|
||||||
|
<el-scrollbar height="400px">
|
||||||
|
<el-table :data="tableData" style="width: 100%">
|
||||||
|
<el-table-column prop="date" label="日期" width="120" />
|
||||||
|
<el-table-column prop="amount" label="销售总金额" width="120" />
|
||||||
|
<el-table-column prop="profit" label="利润" />
|
||||||
|
</el-table>
|
||||||
|
</el-scrollbar>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
const tableData = [
|
||||||
|
{
|
||||||
|
date: '2024-03-06',
|
||||||
|
amount: '1500¥',
|
||||||
|
profit: '500¥',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2024-03-05',
|
||||||
|
amount: '5130¥',
|
||||||
|
profit: '510¥',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2024-03-04',
|
||||||
|
amount: '4500¥',
|
||||||
|
profit: '500¥',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2024-03-03',
|
||||||
|
amount: '4600¥',
|
||||||
|
profit: '600¥',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2024-03-02',
|
||||||
|
amount: '4600¥',
|
||||||
|
profit: '600¥',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2024-03-01',
|
||||||
|
amount: '4600¥',
|
||||||
|
profit: '600¥',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2024-02-29',
|
||||||
|
amount: '4600¥',
|
||||||
|
profit: '600¥',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2024-02-28',
|
||||||
|
amount: '4600¥',
|
||||||
|
profit: '600¥',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2024-02-27',
|
||||||
|
amount: '4600¥',
|
||||||
|
profit: '600¥',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2024-02-26',
|
||||||
|
amount: '4600¥',
|
||||||
|
profit: '600¥',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
</script>
|
1
tencent/src/vite-env.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/// <reference types="vite/client" />
|
25
tencent/tsconfig.json
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2020",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
|
||||||
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
|
}
|
12
tencent/tsconfig.node.json
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true,
|
||||||
|
"allowJs": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
8
tencent/vite.config.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [vue(),
|
||||||
|
],
|
||||||
|
})
|