公司业绩管理页面搭建
This commit is contained in:
parent
5a4e9fdba8
commit
711db26d31
|
|
@ -9,6 +9,7 @@ declare module '@vue/runtime-core' {
|
|||
export interface GlobalComponents {
|
||||
AppIcon: typeof import('./src/components/AppIcon.vue')['default']
|
||||
AvatarUpload: typeof import('./src/components/AvatarUpload.vue')['default']
|
||||
DialogModel: typeof import('./src/components/DialogModel.vue')['default']
|
||||
ElAlert: typeof import('element-plus/es')['ElAlert']
|
||||
ElAvatar: typeof import('element-plus/es')['ElAvatar']
|
||||
ElButton: typeof import('element-plus/es')['ElButton']
|
||||
|
|
@ -17,6 +18,7 @@ declare module '@vue/runtime-core' {
|
|||
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
||||
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
|
||||
ElCol: typeof import('element-plus/es')['ElCol']
|
||||
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
||||
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||
ElDivider: typeof import('element-plus/es')['ElDivider']
|
||||
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
||||
|
|
|
|||
|
|
@ -22,9 +22,11 @@
|
|||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.14.1",
|
||||
"@vitejs/plugin-vue": "^3.0.0",
|
||||
"@vue/compiler-sfc": "^3.1.2",
|
||||
"sass": "^1.49.7",
|
||||
"sass-loader": "^16.0.5",
|
||||
"typescript": "^4.6.4",
|
||||
"unplugin-auto-import": "^0.11.5",
|
||||
"unplugin-vue-components": "^0.22.12",
|
||||
|
|
@ -249,6 +251,16 @@
|
|||
"integrity": "sha512-jMN2moJ+lSf1VZXQo3VXeMCjoXuciVONig8+U0YNBop5aBvQw4qkolx1Nzn1i0T8L2l9IZ3jju6bS1pPwlaY1w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.14.1",
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/@types/node/-/node-22.14.1.tgz",
|
||||
"integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/web-bluetooth": {
|
||||
"version": "0.0.15",
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/@types/web-bluetooth/-/web-bluetooth-0.0.15.tgz",
|
||||
|
|
@ -1506,6 +1518,13 @@
|
|||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/neo-async": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/neo-async/-/neo-async-2.6.2.tgz",
|
||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
|
|
@ -1744,6 +1763,47 @@
|
|||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sass-loader": {
|
||||
"version": "16.0.5",
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/sass-loader/-/sass-loader-16.0.5.tgz",
|
||||
"integrity": "sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"neo-async": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18.12.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/webpack"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@rspack/core": "0.x || 1.x",
|
||||
"node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
|
||||
"sass": "^1.3.0",
|
||||
"sass-embedded": "*",
|
||||
"webpack": "^5.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@rspack/core": {
|
||||
"optional": true
|
||||
},
|
||||
"node-sass": {
|
||||
"optional": true
|
||||
},
|
||||
"sass": {
|
||||
"optional": true
|
||||
},
|
||||
"sass-embedded": {
|
||||
"optional": true
|
||||
},
|
||||
"webpack": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/schart.js": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/schart.js/-/schart.js-3.0.4.tgz",
|
||||
|
|
@ -1860,6 +1920,13 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://repo.huaweicloud.com/repository/npm/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/unimport": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/unimport/-/unimport-1.3.0.tgz",
|
||||
|
|
|
|||
|
|
@ -22,9 +22,11 @@
|
|||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"sass": "^1.49.7",
|
||||
"@types/node": "^22.14.1",
|
||||
"@vitejs/plugin-vue": "^3.0.0",
|
||||
"@vue/compiler-sfc": "^3.1.2",
|
||||
"sass": "^1.49.7",
|
||||
"sass-loader": "^16.0.5",
|
||||
"typescript": "^4.6.4",
|
||||
"unplugin-auto-import": "^0.11.5",
|
||||
"unplugin-vue-components": "^0.22.12",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
declare module '*.vue' {
|
||||
import { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
|
||||
// 添加对 @/views 的路径支持(可选)
|
||||
declare module '@/views/*' {
|
||||
import { DefineComponent } from 'vue'
|
||||
const component: DefineComponent<{}, {}, any>
|
||||
export default component
|
||||
}
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
import request from '../utils/request';
|
||||
import {BASE_URI} from "./base";
|
||||
import request from '../utils/request'
|
||||
import { BASE_URI } from './base'
|
||||
|
||||
export function login(data: { username: string; password: string }) {
|
||||
return request({
|
||||
url: `${BASE_URI}/login`,
|
||||
method: 'post',
|
||||
data: data
|
||||
});
|
||||
data: data,
|
||||
})
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
return request({
|
||||
url: `${BASE_URI}/logout`,
|
||||
method: 'post',
|
||||
});
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
<template>
|
||||
<el-dialog
|
||||
:title="props.dialogConfig.outerTitle"
|
||||
:width="props.dialogConfig.outerWidth"
|
||||
v-model="props.dialogConfig.outerVisible"
|
||||
v-if="props.dialogConfig.outerVisible"
|
||||
:before-close="handleCloseOuter"
|
||||
append-to-body
|
||||
>
|
||||
<!-- 外层弹框内容 -->
|
||||
<slot name="outerContent"></slot>
|
||||
|
||||
<!-- 内层对话框 -->
|
||||
<el-dialog
|
||||
:title="props.dialogConfig.innerTitle"
|
||||
:width="props.dialogConfig.innerWidth"
|
||||
v-model="props.dialogConfig.innerVisible"
|
||||
v-if="props.dialogConfig.innerVisible"
|
||||
:before-close="handleCloseInner"
|
||||
append-to-body
|
||||
>
|
||||
<!-- 内层弹框内容 -->
|
||||
<slot name="innerContent"></slot>
|
||||
</el-dialog>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const props = defineProps({
|
||||
dialogConfig: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const emits = defineEmits(['closeDialogOuter', 'closeDialogInner'])
|
||||
|
||||
const handleCloseOuter = () => {
|
||||
emits('closeDialogOuter', false)
|
||||
}
|
||||
const handleCloseInner = () => {
|
||||
emits('closeDialogInner', false)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.el-dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
max-height: 95vh;
|
||||
min-height: 95vh;
|
||||
.el-dialog__body {
|
||||
flex: 1;
|
||||
overflow-y: scroll;
|
||||
padding: 20px 40px;
|
||||
}
|
||||
.dialog-content {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,124 +1,121 @@
|
|||
<template>
|
||||
<div class="sidebar">
|
||||
<el-menu
|
||||
class="sidebar-el-menu"
|
||||
:default-active="onRoutes"
|
||||
:collapse="sidebar.collapse"
|
||||
background-color="#324157"
|
||||
text-color="#bfcbd9"
|
||||
active-text-color="#20a0ff"
|
||||
unique-opened
|
||||
router
|
||||
>
|
||||
<template v-for="item in items">
|
||||
<template v-if="item.subs">
|
||||
<el-sub-menu :index="item.index" :key="item.index">
|
||||
<template #title>
|
||||
<el-icon>
|
||||
<component :is="item.icon"></component>
|
||||
</el-icon>
|
||||
<span>{{ item.title }}</span>
|
||||
</template>
|
||||
<template v-for="subItem in item.subs">
|
||||
<el-sub-menu
|
||||
v-if="subItem.subs"
|
||||
:index="subItem.index"
|
||||
:key="subItem.index"
|
||||
>
|
||||
<template #title>
|
||||
<el-icon>
|
||||
<component :is="subItem.icon"></component>
|
||||
</el-icon>
|
||||
{{ subItem.title }}
|
||||
<div class="sidebar">
|
||||
<el-menu
|
||||
class="sidebar-el-menu"
|
||||
:default-active="onRoutes"
|
||||
:collapse="sidebar.collapse"
|
||||
background-color="#324157"
|
||||
text-color="#bfcbd9"
|
||||
active-text-color="#20a0ff"
|
||||
unique-opened
|
||||
router
|
||||
>
|
||||
<template v-for="item in items">
|
||||
<template v-if="item.subs">
|
||||
<el-sub-menu :index="item.index" :key="item.index">
|
||||
<template #title>
|
||||
<el-icon>
|
||||
<component :is="item.icon"></component>
|
||||
</el-icon>
|
||||
<span>{{ item.title }}</span>
|
||||
</template>
|
||||
<template v-for="subItem in item.subs">
|
||||
<el-sub-menu v-if="subItem.subs" :index="subItem.index" :key="subItem.index">
|
||||
<template #title>
|
||||
<el-icon>
|
||||
<component :is="subItem.icon"></component>
|
||||
</el-icon>
|
||||
{{ subItem.title }}
|
||||
</template>
|
||||
<el-menu-item v-for="(threeItem, i) in subItem.subs" :key="i" :index="threeItem.index">
|
||||
<el-icon>
|
||||
<component :is="threeItem.icon"></component>
|
||||
</el-icon>
|
||||
{{ threeItem.title }}
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
<el-menu-item v-else :index="subItem.index">
|
||||
<el-icon>
|
||||
<component :is="subItem.icon"></component>
|
||||
</el-icon>
|
||||
{{ subItem.title }}
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</el-sub-menu>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-menu-item :index="item.index" :key="item.index">
|
||||
<el-icon>
|
||||
<component :is="item.icon"></component>
|
||||
</el-icon>
|
||||
<template #title>{{ item?.title }}</template>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
<el-menu-item v-for="(threeItem, i) in subItem.subs" :key="i" :index="threeItem.index">
|
||||
<el-icon>
|
||||
<component :is="threeItem.icon"></component>
|
||||
</el-icon>
|
||||
{{ threeItem.title }}
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
<el-menu-item v-else :index="subItem.index">
|
||||
<el-icon>
|
||||
<component :is="subItem.icon"></component>
|
||||
</el-icon>
|
||||
{{ subItem.title }}
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</el-sub-menu>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-menu-item :index="item.index" :key="item.index">
|
||||
<el-icon>
|
||||
<component :is="item.icon"></component>
|
||||
</el-icon>
|
||||
<template #title>{{ item?.title }}</template>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</template>
|
||||
</el-menu>
|
||||
</div>
|
||||
</el-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {computed, ref} from 'vue';
|
||||
import {useSidebarStore} from '../store/sidebar';
|
||||
import {useRoute} from 'vue-router';
|
||||
import {getMenus} from "../api/resource";
|
||||
|
||||
import { computed, ref } from 'vue'
|
||||
import { useSidebarStore } from '../store/sidebar'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { getMenus } from '../api/resource'
|
||||
|
||||
interface MenuItem {
|
||||
index: string;
|
||||
icon: string;
|
||||
title: string;
|
||||
subs: MenuItem[] | undefined;
|
||||
index: string
|
||||
icon: string
|
||||
title: string
|
||||
subs: MenuItem[] | undefined
|
||||
}
|
||||
|
||||
const items = ref<MenuItem[]>([]);
|
||||
const items = ref<MenuItem[]>([])
|
||||
|
||||
getMenus().then(res => {
|
||||
items.value = getDataNode(res.data, 1);
|
||||
});
|
||||
getMenus().then((res) => {
|
||||
items.value = getDataNode(res.data, 1)
|
||||
})
|
||||
|
||||
const getDataNode: any = (menus: any[], parentId: number) => {
|
||||
return menus.filter(m => m.parentId === parentId).map((menu: any) => {
|
||||
let subs: MenuItem[] = getDataNode(menus, menu.id);
|
||||
return {
|
||||
index: menu.url,
|
||||
icon: menu.icon,
|
||||
title: menu.name,
|
||||
subs: subs?.length === 0 ? undefined : subs
|
||||
}
|
||||
});
|
||||
return menus
|
||||
.filter((m) => m.parentId === parentId)
|
||||
.map((menu: any) => {
|
||||
let subs: MenuItem[] = getDataNode(menus, menu.id)
|
||||
return {
|
||||
index: menu.url,
|
||||
icon: menu.icon,
|
||||
title: menu.name,
|
||||
subs: subs?.length === 0 ? undefined : subs,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const route = useRoute();
|
||||
const route = useRoute()
|
||||
const onRoutes = computed(() => {
|
||||
return route.path;
|
||||
});
|
||||
return route.path
|
||||
})
|
||||
|
||||
const sidebar = useSidebarStore();
|
||||
const sidebar = useSidebarStore()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.sidebar {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 70px;
|
||||
bottom: 0;
|
||||
overflow-y: scroll;
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 70px;
|
||||
bottom: 0;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.sidebar::-webkit-scrollbar {
|
||||
width: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.sidebar-el-menu:not(.el-menu--collapse) {
|
||||
width: 250px;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.sidebar > ul {
|
||||
height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
41
src/main.ts
41
src/main.ts
|
|
@ -1,28 +1,33 @@
|
|||
import {createApp} from 'vue';
|
||||
import {createPinia} from 'pinia';
|
||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue';
|
||||
import App from './App.vue';
|
||||
import router from './router';
|
||||
import 'element-plus/dist/index.css';
|
||||
import './assets/css/icon.css';
|
||||
import {useBasicStore} from "./store/basic";
|
||||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import 'element-plus/dist/index.css'
|
||||
import './assets/css/icon.css'
|
||||
import { useBasicStore } from './store/basic'
|
||||
import ElementPlus from 'element-plus'
|
||||
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
||||
|
||||
const app = createApp(App);
|
||||
app.use(createPinia());
|
||||
app.use(router);
|
||||
const app = createApp(App)
|
||||
app.use(createPinia())
|
||||
app.use(router)
|
||||
|
||||
// 注册element plus图标
|
||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||
app.component(key, component);
|
||||
app.component(key, component)
|
||||
}
|
||||
const basicStore = useBasicStore();
|
||||
const basicStore = useBasicStore()
|
||||
app.directive('action', {
|
||||
mounted(el, binding) {
|
||||
const permissions: string[] = basicStore?.userinfo?.permissions || [];
|
||||
const actionName: string = binding.arg || '';
|
||||
const permissions: string[] = basicStore?.userinfo?.permissions || []
|
||||
const actionName: string = binding.arg || ''
|
||||
if (permissions && !permissions.includes(actionName)) {
|
||||
el['hidden'] = true;
|
||||
el['hidden'] = true
|
||||
}
|
||||
},
|
||||
});
|
||||
app.mount('#app');
|
||||
})
|
||||
app.mount('#app')
|
||||
app.use(ElementPlus, {
|
||||
locale: zhCn,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
|
||||
import { createRouter, createWebHashHistory, RouteRecordRaw, createWebHistory } from 'vue-router'
|
||||
import Home from '../views/home.vue'
|
||||
import { useBasicStore } from '../store/basic'
|
||||
|
||||
|
|
@ -77,6 +77,16 @@ const routes: RouteRecordRaw[] = [
|
|||
},
|
||||
component: () => import(/* webpackChunkName: "user" */ '../views/user.vue'),
|
||||
},
|
||||
|
||||
{
|
||||
path: '/performance-manage',
|
||||
name: 'performance-manage',
|
||||
meta: {
|
||||
title: '登录',
|
||||
},
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "login" */ '@/views/company-manage/performance-manage/index.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
@ -87,6 +97,7 @@ const routes: RouteRecordRaw[] = [
|
|||
},
|
||||
component: () => import(/* webpackChunkName: "login" */ '../views/login.vue'),
|
||||
},
|
||||
|
||||
{
|
||||
path: '/403',
|
||||
name: '403',
|
||||
|
|
@ -98,12 +109,11 @@ const routes: RouteRecordRaw[] = [
|
|||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
history: createWebHistory(),
|
||||
routes,
|
||||
})
|
||||
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
// document.title = ` 市场部投标信息检索工具`
|
||||
const token = localStorage.getItem('token')
|
||||
const basicStore = useBasicStore()
|
||||
if (!token && to.path !== '/login') {
|
||||
|
|
|
|||
|
|
@ -1,45 +1,47 @@
|
|||
import axios, {AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse} from 'axios';
|
||||
import {ElMessage} from "element-plus";
|
||||
import router from "../router";
|
||||
import axios, { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import router from '../router'
|
||||
|
||||
const service: AxiosInstance = axios.create({
|
||||
timeout: 5000
|
||||
});
|
||||
timeout: 5000,
|
||||
baseURL: '/dev-api',
|
||||
})
|
||||
|
||||
service.interceptors.request.use(
|
||||
(config: AxiosRequestConfig) => {
|
||||
const headerToken = localStorage.getItem('token');
|
||||
const headerToken = localStorage.getItem('token')
|
||||
if (headerToken) {
|
||||
// @ts-ignore
|
||||
config.headers['Authorization'] = 'Bearer ' + headerToken
|
||||
}
|
||||
|
||||
return config;
|
||||
return config
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
console.log(error);
|
||||
return Promise.reject();
|
||||
}
|
||||
);
|
||||
console.log(error)
|
||||
return Promise.reject()
|
||||
},
|
||||
)
|
||||
|
||||
service.interceptors.response.use(
|
||||
(response: AxiosResponse) => {
|
||||
console.log('response', response)
|
||||
if (response.status === 200) {
|
||||
return response;
|
||||
return response
|
||||
} else {
|
||||
Promise.reject();
|
||||
Promise.reject()
|
||||
}
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
console.log(error);
|
||||
console.log('error', error)
|
||||
if (error.response?.status === 401) {
|
||||
localStorage.removeItem('token');
|
||||
router.push('/login');
|
||||
localStorage.removeItem('token')
|
||||
// router.push('/login')
|
||||
}
|
||||
// @ts-ignore
|
||||
ElMessage.error(error.response?.data?.message);
|
||||
return Promise.reject();
|
||||
}
|
||||
);
|
||||
ElMessage.error(error.response?.data?.message || '请求失败,请切换网络后尝试')
|
||||
return Promise.reject()
|
||||
},
|
||||
)
|
||||
|
||||
export default service;
|
||||
export default service
|
||||
|
|
|
|||
|
|
@ -0,0 +1,192 @@
|
|||
<template>
|
||||
<el-form :model="addAndEditForm" :rules="addAndEditRules" ref="login" label-width="0px" label-position="top">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="工程名称" prop="proName">
|
||||
<el-input v-model="addAndEditForm.proName" placeholder="请输入工程名称" clearable> </el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="电压等级" prop="level">
|
||||
<el-input v-model="addAndEditForm.level" placeholder="请输入工程名称" clearable> </el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="起止时间" prop="startTime">
|
||||
<el-input v-model="addAndEditForm.startTime" placeholder="请输入工程名称" clearable> </el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="竣工日期" prop="endTime">
|
||||
<el-input v-model="addAndEditForm.endTime" placeholder="请输入工程名称" clearable> </el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="变电站座数" prop="num">
|
||||
<el-input v-model="addAndEditForm.num" placeholder="请输入工程名称" clearable> </el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="线路建设规模" prop="scale">
|
||||
<el-input v-model="addAndEditForm.scale" placeholder="请输入工程名称" clearable> </el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="承包范围" prop="fw">
|
||||
<el-input v-model="addAndEditForm.fw" placeholder="请输入工程名称" clearable> </el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="业主单位" prop="unit">
|
||||
<el-input v-model="addAndEditForm.unit" placeholder="请输入工程名称" clearable> </el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="业务单位联系方式" prop="unitPhone">
|
||||
<el-input v-model="addAndEditForm.unitPhone" placeholder="请输入工程名称" clearable> </el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<div style="display: flex; align-items: center; padding: 8px 0">
|
||||
<div> 项目关键人员 </div>
|
||||
<el-button :icon="CirclePlus" type="primary" link @click="onHandleAdd">添加</el-button>
|
||||
</div>
|
||||
|
||||
<el-table :data="addTableList" stripe style="width: 100%">
|
||||
<el-table-column label="序号" width="55" type="index" />
|
||||
<el-table-column align="center" label="担任职务" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.zhiW" placeholder="请输入职务" clearable />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="姓名">
|
||||
<template #default="{ row }">
|
||||
<el-select v-model="row.name" clearable>
|
||||
<el-option label="张三" value="1" />
|
||||
<el-option label="李四" value="2" />
|
||||
<el-option label="王五" value="3" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" prop="zhiW" label="身份证号" show-overflow-tooltip />
|
||||
<el-table-column align="center" prop="zhiW" label="电话" show-overflow-tooltip />
|
||||
<el-table-column align="center" label="工作内容" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.content" placeholder="请输入工作内容" clearable />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" prop="zhiW" label="业绩证明材料" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<el-button link @click="uploadOuterVisible = true"> 上传 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button :icon="DeleteFilled" type="danger" link @click="onHandleDelete(scope)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-dialog
|
||||
title="上传"
|
||||
width="40%"
|
||||
v-model="uploadOuterVisible"
|
||||
v-if="uploadOuterVisible"
|
||||
:before-close="(uploadOuterVisible = false)"
|
||||
append-to-body
|
||||
>
|
||||
<!-- 外层弹框内容 -->
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { CirclePlus, DeleteFilled } from '@element-plus/icons-vue'
|
||||
import { ref } from 'vue'
|
||||
const uploadOuterVisible = ref(false)
|
||||
const addAndEditForm = ref({
|
||||
proName: '',
|
||||
level: '',
|
||||
startTime: [],
|
||||
endTime: '',
|
||||
num: '',
|
||||
scale: '',
|
||||
fw: '',
|
||||
unit: '',
|
||||
unitPhone: '',
|
||||
})
|
||||
|
||||
const addAndEditRules = ref({
|
||||
proName: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入输工程名称',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
level: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入电压等级',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
startTime: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择起止时间',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
endTime: [
|
||||
{
|
||||
required: true,
|
||||
message: '请选择竣工时间',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
fw: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入承包范围',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
unit: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入业主单位',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
unitPhone: [
|
||||
{
|
||||
required: true,
|
||||
message: '请输入业主单位联系方式',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const addTableList: any = ref([])
|
||||
|
||||
const onHandleAdd = () => {
|
||||
addTableList.value.push({
|
||||
zhiW: '',
|
||||
name: '',
|
||||
content: '',
|
||||
})
|
||||
}
|
||||
|
||||
// 删除
|
||||
const onHandleDelete = (row: any) => {
|
||||
console.log(row, 'row')
|
||||
|
||||
addTableList.value.splice(row.$index, 1)
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
<template>
|
||||
<!-- 公司业绩管理 -->
|
||||
|
||||
<div class="container">
|
||||
<el-form :model="queryParam" ref="login" label-width="0px" class="ms-content">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<el-form-item>
|
||||
<el-input v-model="queryParam.projectName" placeholder="请输入工程名称" clearable> </el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<el-form-item>
|
||||
<el-date-picker
|
||||
v-model="timeValue"
|
||||
type="daterange"
|
||||
range-separator="~"
|
||||
value-format="YYYY-MM-DD"
|
||||
end-placeholder="结束时间"
|
||||
start-placeholder="开始时间"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item>
|
||||
<el-button :icon="Search" type="primary">查询</el-button>
|
||||
<el-button :icon="Refresh">重置</el-button>
|
||||
<el-button :icon="Plus" type="primary" @click="onHandleAdd">新增业绩</el-button>
|
||||
<el-button :icon="Download">导出数据</el-button>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
|
||||
<el-table :data="tableList" stripe style="width: 100%">
|
||||
<el-table-column label="序号" width="55" type="index" />
|
||||
<el-table-column
|
||||
:key="index"
|
||||
align="center"
|
||||
:prop="item.prop"
|
||||
:label="item.label"
|
||||
show-overflow-tooltip
|
||||
v-for="(item, index) in tableColumn"
|
||||
/>
|
||||
|
||||
<el-table-column label="操作" width="200" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button :icon="WarningFilled" type="success" size="small" link>详情</el-button>
|
||||
<el-button :icon="EditPen" type="primary" size="small" link>编辑</el-button>
|
||||
<el-button :icon="DeleteFilled" type="danger" size="small" link>删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<DialogModel :dialogConfig="dialogConfig" @closeDialogOuter="closeDialogOuter">
|
||||
<template #outerContent>
|
||||
<AddAndEditForm />
|
||||
</template>
|
||||
</DialogModel>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import DialogModel from '@/components/DialogModel.vue'
|
||||
import AddAndEditForm from './components/addAndEditForm.vue'
|
||||
import { Search, Refresh, Download, Plus, WarningFilled, EditPen, DeleteFilled } from '@element-plus/icons-vue'
|
||||
import { reactive, ref } from 'vue'
|
||||
|
||||
const dialogConfig = ref({
|
||||
outerTitle: '新增',
|
||||
innerTitle: false,
|
||||
outerWidth: '80%',
|
||||
outerVisible: false,
|
||||
innerVisible: false,
|
||||
})
|
||||
const queryParam = ref({
|
||||
projectName: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
})
|
||||
|
||||
const timeValue = ref([])
|
||||
const tableList = ref([
|
||||
{
|
||||
projectName: '测试工程1',
|
||||
},
|
||||
{
|
||||
projectName: '测试工程2',
|
||||
},
|
||||
{
|
||||
projectName: '测试工程3',
|
||||
},
|
||||
])
|
||||
const tableColumn = ref([
|
||||
{ label: '工程名称', prop: 'projectName' },
|
||||
{ label: '电压等级', prop: '' },
|
||||
{ label: '起止时间', prop: '' },
|
||||
{ label: '竣工日期', prop: '' },
|
||||
{ label: '变电站数量', prop: '' },
|
||||
{ label: '线路建设规模(折单公里)', prop: '' },
|
||||
{ label: '承包范围', prop: '' },
|
||||
{ label: '业主单位', prop: '' },
|
||||
{ label: '业主单位联系方式', prop: '' },
|
||||
{ label: '关键人员', prop: '' },
|
||||
])
|
||||
|
||||
const onHandleAdd = () => {
|
||||
console.log('新增')
|
||||
dialogConfig.value.outerVisible = true
|
||||
}
|
||||
|
||||
const closeDialogOuter = () => {
|
||||
dialogConfig.value.outerVisible = false
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss"></style>
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
<div class="ms-title">市场部投标信息检索工具</div>
|
||||
<el-form :model="param" :rules="rules" ref="login" label-width="0px" class="ms-content">
|
||||
<el-form-item prop="username">
|
||||
<el-input v-model="param.username" placeholder="username">
|
||||
<el-input v-model="param.username" placeholder="请输入登录账号" clearable>
|
||||
<template #prepend>
|
||||
<el-button :icon="User" disabled></el-button>
|
||||
</template>
|
||||
|
|
@ -13,9 +13,11 @@
|
|||
<el-form-item prop="password">
|
||||
<el-input
|
||||
type="password"
|
||||
placeholder="password"
|
||||
placeholder="请输入密码"
|
||||
v-model="param.password"
|
||||
@keyup.enter="submitForm(login)"
|
||||
show-password
|
||||
clearable
|
||||
>
|
||||
<template #prepend>
|
||||
<el-button :icon="Lock" disabled></el-button>
|
||||
|
|
|
|||
|
|
@ -1,511 +1,548 @@
|
|||
<template>
|
||||
<div class="data-center-wrap">
|
||||
<el-card shadow="never" style="height: 100%">
|
||||
<el-row :gutter="20" style="height: 100%">
|
||||
<el-col :xl="4" :lg="4" style="border-right: 1px solid #dcdfe6">
|
||||
<div style="margin-bottom: 24px; font-weight: 700">角色管理</div>
|
||||
<el-divider></el-divider>
|
||||
<el-button @click="addVisible = true;Object.assign(form, new Role());" type="primary" link
|
||||
v-action:role:create>新建角色
|
||||
</el-button>
|
||||
<div style="margin-top: 16px">
|
||||
<div
|
||||
class="role-item"
|
||||
:class="{ 'role-item-active': item.id === activeRoleId }"
|
||||
v-for="(item, index) in roleList"
|
||||
:key="index"
|
||||
@click="handleRoleChange(item)"
|
||||
>
|
||||
<div>
|
||||
<div>{{ item.name }}</div>
|
||||
</div>
|
||||
<el-dropdown trigger="hover">
|
||||
<el-icon>
|
||||
<setting/>
|
||||
</el-icon>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<span v-action:role:update>
|
||||
<el-dropdown-item @click="handleEdit" v-action:role:update>编辑</el-dropdown-item>
|
||||
</span>
|
||||
<span v-action:role:delete>
|
||||
<el-dropdown-item @click="handleDelete(roleList.find(r => r?.id === activeRoleId))">
|
||||
<span class="del-btn">删除</span>
|
||||
</el-dropdown-item>
|
||||
</span>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xl="20" :lg="20">
|
||||
<el-col :span="24">
|
||||
<el-col :span="24" style="padding-left: 0px;">
|
||||
{{ roleList.find(r => r?.id === activeRoleId)?.name }}
|
||||
<el-button text :icon="Edit" @click="handleEdit" v-action:role:update>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button text :icon="Delete" class="red"
|
||||
@click="handleDelete(roleList.find(r => r?.id === activeRoleId))" v-action:role:delete>
|
||||
删除
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col style="font-size: 8px;color: #777777;padding-left: 0px;" :span="24">
|
||||
{{ roleList.find(r => r?.id === activeRoleId)?.description }}
|
||||
</el-col>
|
||||
</el-col>
|
||||
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleChangeRoleUserClient">
|
||||
<el-tab-pane label="角色成员" name="first">
|
||||
<div style="margin-bottom: 24px">
|
||||
<el-button type="primary" @click="isOrgSelectShow = true" v-action:role:update>调整成员</el-button>
|
||||
</div>
|
||||
<el-table :data="tableData" border class="table" ref="multipleTable"
|
||||
header-cell-class-name="table-header">
|
||||
<el-table-column prop="id" label="ID" width="55" align="center"></el-table-column>
|
||||
<el-table-column prop="username" label="用户名"></el-table-column>
|
||||
<el-table-column prop="gender" label="性别">
|
||||
<template #default="{ row }">
|
||||
<span>{{ row.gender === 'MALE' ? '男' : '女' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="头像" align="center">
|
||||
<template #default="scope">
|
||||
<el-image
|
||||
class="table-td-thumb"
|
||||
:src="scope.row.avatar"
|
||||
:z-index="10"
|
||||
:preview-src-list="[scope?.row?.avatar]"
|
||||
preview-teleported
|
||||
>
|
||||
</el-image>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="拥有的角色">
|
||||
<template #default="scope">
|
||||
<sppan v-for="(role, index) in scope.row?.roles">
|
||||
<template v-if="index > 0">, </template>
|
||||
{{ role.name }}
|
||||
</sppan>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination">
|
||||
<el-pagination
|
||||
background
|
||||
layout="total, prev, pager, next"
|
||||
:current-page="userQuery.pageIndex"
|
||||
:page-size="userQuery.pageSize"
|
||||
:total="pageTotal"
|
||||
@current-change="handlePageChange"
|
||||
></el-pagination>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="权限设置" name="second">
|
||||
<div style="margin-bottom: 24px">
|
||||
<el-button type="primary" @click="savePermission" v-action:role:update>保存</el-button>
|
||||
</div>
|
||||
<div v-for="(menu, index) in rolePermission" :key="index">
|
||||
<el-row>
|
||||
<el-col :span="18" :style="{fontWeight:'bold'}">{{ menu.name }}</el-col>
|
||||
<el-col :span="6" :style="{textAlign:'right'}">
|
||||
<el-switch
|
||||
size="small"
|
||||
v-model="menu.enabled"
|
||||
@change="onChangeSwitch($event,menu)"/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-divider type="horizontal" :style="{margin: '5px'}"/>
|
||||
<el-row :gutter="16" v-for="(checkbox, tab) in menu.children" :key="tab">
|
||||
<el-col :xl="4" :lg="4">
|
||||
{{ checkbox.name }}:
|
||||
</el-col>
|
||||
<el-col :xl="20" :lg="20">
|
||||
<el-checkbox
|
||||
:disabled="!menu.enabled"
|
||||
v-model="checkbox.checkedAll"
|
||||
:indeterminate="checkbox.indeterminate"
|
||||
@change="onChangeCheckAll($event,checkbox)"
|
||||
>全选
|
||||
</el-checkbox>
|
||||
<el-checkbox-group :disabled="!menu.enabled" v-model="checkbox.selected"
|
||||
@change="onChangeCheck($event,checkbox)">
|
||||
<el-checkbox v-for="btn in checkbox?.actionsOptions" :key="btn.id" :label="btn.id">
|
||||
{{ btn.name }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div class="data-center-wrap">
|
||||
<el-card shadow="never" style="height: 100%">
|
||||
<el-row :gutter="20" style="height: 100%">
|
||||
<el-col :xl="4" :lg="4" style="border-right: 1px solid #dcdfe6">
|
||||
<div style="margin-bottom: 24px; font-weight: 700">角色管理</div>
|
||||
<el-divider></el-divider>
|
||||
<el-button
|
||||
@click="
|
||||
() => {
|
||||
addVisible = true
|
||||
Object.assign(form, new Role())
|
||||
}
|
||||
"
|
||||
type="primary"
|
||||
link
|
||||
v-action:role:create
|
||||
>新建角色
|
||||
</el-button>
|
||||
<div style="margin-top: 16px">
|
||||
<div
|
||||
class="role-item"
|
||||
:class="{ 'role-item-active': item.id === activeRoleId }"
|
||||
v-for="(item, index) in roleList"
|
||||
:key="index"
|
||||
@click="handleRoleChange(item)"
|
||||
>
|
||||
<div>
|
||||
<div>{{ item.name }}</div>
|
||||
</div>
|
||||
<el-dropdown trigger="hover">
|
||||
<el-icon>
|
||||
<setting />
|
||||
</el-icon>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<span v-action:role:update>
|
||||
<el-dropdown-item @click="handleEdit" v-action:role:update
|
||||
>编辑</el-dropdown-item
|
||||
>
|
||||
</span>
|
||||
<span v-action:role:delete>
|
||||
<el-dropdown-item
|
||||
@click="handleDelete(roleList.find((r) => r?.id === activeRoleId))"
|
||||
>
|
||||
<span class="del-btn">删除</span>
|
||||
</el-dropdown-item>
|
||||
</span>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :xl="20" :lg="20">
|
||||
<el-col :span="24">
|
||||
<el-col :span="24" style="padding-left: 0px">
|
||||
{{ roleList.find((r) => r?.id === activeRoleId)?.name }}
|
||||
<el-button text :icon="Edit" @click="handleEdit" v-action:role:update> 编辑 </el-button>
|
||||
<el-button
|
||||
text
|
||||
:icon="Delete"
|
||||
class="red"
|
||||
@click="handleDelete(roleList.find((r) => r?.id === activeRoleId))"
|
||||
v-action:role:delete
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</el-col>
|
||||
<el-col style="font-size: 8px; color: #777777; padding-left: 0px" :span="24">
|
||||
{{ roleList.find((r) => r?.id === activeRoleId)?.description }}
|
||||
</el-col>
|
||||
</el-col>
|
||||
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleChangeRoleUserClient">
|
||||
<el-tab-pane label="角色成员" name="first">
|
||||
<div style="margin-bottom: 24px">
|
||||
<el-button type="primary" @click="isOrgSelectShow = true" v-action:role:update
|
||||
>调整成员</el-button
|
||||
>
|
||||
</div>
|
||||
<el-table
|
||||
:data="tableData"
|
||||
border
|
||||
class="table"
|
||||
ref="multipleTable"
|
||||
header-cell-class-name="table-header"
|
||||
>
|
||||
<el-table-column prop="id" label="ID" width="55" align="center"></el-table-column>
|
||||
<el-table-column prop="username" label="用户名"></el-table-column>
|
||||
<el-table-column prop="gender" label="性别">
|
||||
<template #default="{ row }">
|
||||
<span>{{ row.gender === 'MALE' ? '男' : '女' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="头像" align="center">
|
||||
<template #default="scope">
|
||||
<el-image
|
||||
class="table-td-thumb"
|
||||
:src="scope.row.avatar"
|
||||
:z-index="10"
|
||||
:preview-src-list="[scope?.row?.avatar]"
|
||||
preview-teleported
|
||||
>
|
||||
</el-image>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="拥有的角色">
|
||||
<template #default="scope">
|
||||
<sppan v-for="(role, index) in scope.row?.roles">
|
||||
<template v-if="index > 0">, </template>
|
||||
{{ role.name }}
|
||||
</sppan>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="pagination">
|
||||
<el-pagination
|
||||
background
|
||||
layout="total, prev, pager, next"
|
||||
:current-page="userQuery.pageIndex"
|
||||
:page-size="userQuery.pageSize"
|
||||
:total="pageTotal"
|
||||
@current-change="handlePageChange"
|
||||
></el-pagination>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="权限设置" name="second">
|
||||
<div style="margin-bottom: 24px">
|
||||
<el-button type="primary" @click="savePermission" v-action:role:update>保存</el-button>
|
||||
</div>
|
||||
<div v-for="(menu, index) in rolePermission" :key="index">
|
||||
<el-row>
|
||||
<el-col :span="18" :style="{ fontWeight: 'bold' }">{{ menu.name }}</el-col>
|
||||
<el-col :span="6" :style="{ textAlign: 'right' }">
|
||||
<el-switch
|
||||
size="small"
|
||||
v-model="menu.enabled"
|
||||
@change="onChangeSwitch($event, menu)"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-divider type="horizontal" :style="{ margin: '5px' }" />
|
||||
<el-row :gutter="16" v-for="(checkbox, tab) in menu.children" :key="tab">
|
||||
<el-col :xl="4" :lg="4"> {{ checkbox.name }}: </el-col>
|
||||
<el-col :xl="20" :lg="20">
|
||||
<el-checkbox
|
||||
:disabled="!menu.enabled"
|
||||
v-model="checkbox.checkedAll"
|
||||
:indeterminate="checkbox.indeterminate"
|
||||
@change="onChangeCheckAll($event, checkbox)"
|
||||
>全选
|
||||
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
{{ checkbox.id }}
|
||||
</el-checkbox>
|
||||
<el-checkbox-group
|
||||
:disabled="!menu.enabled"
|
||||
v-model="checkbox.selected"
|
||||
@change="onChangeCheck($event, checkbox)"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="btn in checkbox?.actionsOptions"
|
||||
:key="btn.id"
|
||||
:label="btn.id"
|
||||
>
|
||||
{{ btn.name }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<!-- 组织架构选择弹出框 -->
|
||||
<OrgSelect
|
||||
append-to-body
|
||||
v-if="isOrgSelectShow"
|
||||
:visible="isOrgSelectShow"
|
||||
:activeRoleId="activeRoleId"
|
||||
@on-cancel="handleOrgSelectCancel"
|
||||
@on-submit="handleOrgSelectSubmit"
|
||||
/>
|
||||
<!-- 组织架构选择弹出框 -->
|
||||
<OrgSelect
|
||||
append-to-body
|
||||
v-if="isOrgSelectShow"
|
||||
:visible="isOrgSelectShow"
|
||||
:activeRoleId="activeRoleId"
|
||||
@on-cancel="handleOrgSelectCancel"
|
||||
@on-submit="handleOrgSelectSubmit"
|
||||
/>
|
||||
|
||||
<!-- 新增弹出框 -->
|
||||
<el-dialog title="新增" v-model="addVisible" width="30%">
|
||||
<el-form label-width="70px">
|
||||
<el-form-item label="用户名">
|
||||
<el-input v-model="form.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input v-model="form.description" type="textarea"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="addVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="saveAdd">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 新增弹出框 -->
|
||||
<el-dialog title="新增" v-model="addVisible" width="30%">
|
||||
<el-form label-width="70px">
|
||||
<el-form-item label="用户名">
|
||||
<el-input v-model="form.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input v-model="form.description" type="textarea"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="addVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="saveAdd">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 编辑弹出框 -->
|
||||
<el-dialog title="编辑" v-model="editVisible" width="30%">
|
||||
<el-form label-width="70px">
|
||||
<el-form label-width="70px">
|
||||
<el-form-item label="用户名">
|
||||
<el-input v-model="form.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input v-model="form.description" type="textarea"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="editVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="saveEdit">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
<!-- 编辑弹出框 -->
|
||||
<el-dialog title="编辑" v-model="editVisible" width="30%">
|
||||
<el-form label-width="70px">
|
||||
<el-form label-width="70px">
|
||||
<el-form-item label="用户名">
|
||||
<el-input v-model="form.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input v-model="form.description" type="textarea"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="editVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="saveEdit">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import {reactive, ref} from "vue";
|
||||
import { reactive, ref } from 'vue'
|
||||
import {
|
||||
changeResources,
|
||||
changeUsers,
|
||||
createRole,
|
||||
deleteRole,
|
||||
getRoleList,
|
||||
getRoleUserList,
|
||||
updateRole
|
||||
} from "../api/role";
|
||||
import {ElMessage, ElMessageBox, TabsPaneContext} from "element-plus";
|
||||
import {getResourceTree as reqResourceTree} from "../api/resource";
|
||||
import {Delete, Edit} from '@element-plus/icons-vue';
|
||||
import OrgSelect, {OrgSelectedData} from "../components/OrgSelect.vue";
|
||||
changeResources,
|
||||
changeUsers,
|
||||
createRole,
|
||||
deleteRole,
|
||||
getRoleList,
|
||||
getRoleUserList,
|
||||
updateRole,
|
||||
} from '../api/role'
|
||||
import { ElMessage, ElMessageBox, TabsPaneContext } from 'element-plus'
|
||||
import { getResourceTree as reqResourceTree } from '../api/resource'
|
||||
import { Delete, Edit } from '@element-plus/icons-vue'
|
||||
import OrgSelect, { OrgSelectedData } from '../components/OrgSelect.vue'
|
||||
|
||||
const isOrgSelectShow = ref(false)
|
||||
|
||||
interface Resource {
|
||||
id: number;
|
||||
name: string;
|
||||
type: string;
|
||||
permission: string;
|
||||
url: string;
|
||||
children?: Resource[]
|
||||
id: number
|
||||
name: string
|
||||
type: string
|
||||
permission: string
|
||||
url: string
|
||||
children?: Resource[]
|
||||
}
|
||||
|
||||
interface RoleInterface {
|
||||
id: number;
|
||||
name?: string;
|
||||
description?: string;
|
||||
resourceIds?: number[];
|
||||
id: number
|
||||
name?: string
|
||||
description?: string
|
||||
resourceIds?: number[]
|
||||
}
|
||||
|
||||
class Role implements RoleInterface {
|
||||
id = 0;
|
||||
name = '';
|
||||
description = '';
|
||||
resourceIds = [];
|
||||
id = 0
|
||||
name = ''
|
||||
description = ''
|
||||
resourceIds = []
|
||||
}
|
||||
|
||||
interface Permission {
|
||||
id: number;
|
||||
name: string;
|
||||
enabled: boolean,
|
||||
children: {
|
||||
id: number;
|
||||
name: string;
|
||||
checkedAll: boolean;
|
||||
indeterminate: boolean;
|
||||
selected: number[];
|
||||
actionsOptions: {
|
||||
id: number;
|
||||
name: string;
|
||||
id: number
|
||||
name: string
|
||||
enabled: boolean
|
||||
children: {
|
||||
id: number
|
||||
name: string
|
||||
checkedAll: boolean
|
||||
indeterminate: boolean
|
||||
selected: number[]
|
||||
actionsOptions: {
|
||||
id: number
|
||||
name: string
|
||||
}[]
|
||||
}[]
|
||||
}[];
|
||||
}
|
||||
|
||||
interface UserTableItem {
|
||||
id: number;
|
||||
userName: string;
|
||||
gender: string;
|
||||
state: string;
|
||||
roles: { id: number, name: string }
|
||||
id: number
|
||||
userName: string
|
||||
gender: string
|
||||
state: string
|
||||
roles: { id: number; name: string }
|
||||
}
|
||||
|
||||
interface RoleSelectable extends RoleInterface {
|
||||
value: number;
|
||||
label?: string;
|
||||
value: number
|
||||
label?: string
|
||||
}
|
||||
|
||||
const roleList = ref<RoleInterface[]>([]);
|
||||
const activeRoleId = ref<number>(1);
|
||||
|
||||
const roleList = ref<RoleInterface[]>([])
|
||||
const activeRoleId = ref<number>(1)
|
||||
|
||||
const reqRoleList = async () => {
|
||||
try {
|
||||
const { data, } = await getRoleList();
|
||||
roleList.value = data;
|
||||
getResourceTree(); // 获取权限列表
|
||||
} catch (error) {
|
||||
ElMessage.error(error as Error);
|
||||
}
|
||||
};
|
||||
try {
|
||||
const { data } = await getRoleList()
|
||||
roleList.value = data
|
||||
getResourceTree() // 获取权限列表
|
||||
} catch (error) {
|
||||
ElMessage.error(error as Error)
|
||||
}
|
||||
}
|
||||
|
||||
reqRoleList();
|
||||
reqRoleList()
|
||||
|
||||
const handleRoleChange = (role: RoleInterface) => {
|
||||
activeRoleId.value = role.id;
|
||||
getUserData(role.id);
|
||||
handlePermission();
|
||||
activeRoleId.value = role.id
|
||||
getUserData(role.id)
|
||||
handlePermission()
|
||||
}
|
||||
|
||||
//用户表格数据
|
||||
|
||||
const userQuery = reactive({
|
||||
username: '',
|
||||
state: '',
|
||||
pageIndex: 1,
|
||||
pageSize: 10
|
||||
});
|
||||
const tableData = ref<UserTableItem[]>([]);
|
||||
const pageTotal = ref(0);
|
||||
username: '',
|
||||
state: '',
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
})
|
||||
const tableData = ref<UserTableItem[]>([])
|
||||
const pageTotal = ref(0)
|
||||
|
||||
const getUserData = (roleId: number) => {
|
||||
getRoleUserList(roleId, {
|
||||
page: userQuery.pageIndex,
|
||||
size: userQuery.pageSize,
|
||||
username: userQuery.username || undefined,
|
||||
state: userQuery.state || undefined,
|
||||
}).then(res => {
|
||||
tableData.value = res.data.list;
|
||||
pageTotal.value = res.data.total;
|
||||
});
|
||||
getRoleUserList(roleId, {
|
||||
page: userQuery.pageIndex,
|
||||
size: userQuery.pageSize,
|
||||
username: userQuery.username || undefined,
|
||||
state: userQuery.state || undefined,
|
||||
}).then((res) => {
|
||||
tableData.value = res.data.list
|
||||
pageTotal.value = res.data.total
|
||||
})
|
||||
}
|
||||
getUserData(activeRoleId.value);
|
||||
|
||||
getUserData(activeRoleId.value)
|
||||
|
||||
// 分页导航
|
||||
const handlePageChange = (val: number) => {
|
||||
userQuery.pageIndex = val;
|
||||
getUserData(activeRoleId.value);
|
||||
};
|
||||
userQuery.pageIndex = val
|
||||
getUserData(activeRoleId.value)
|
||||
}
|
||||
|
||||
//标签页
|
||||
const activeName = ref('first');
|
||||
const rolePermission = ref<Permission[]>([]);
|
||||
const activeName = ref('first')
|
||||
const rolePermission = ref<Permission[]>([])
|
||||
|
||||
const getResourceTree = () => {
|
||||
//初始化权限资源树
|
||||
reqResourceTree().then((res) => {
|
||||
console.log(res.data, '--996')
|
||||
rolePermission.value = res.data.map((menu: Resource) => {
|
||||
return {
|
||||
id: menu.id,
|
||||
name: menu.name,
|
||||
enabled: true,
|
||||
children:
|
||||
menu.children?.map((checkbox: Resource) => {
|
||||
return {
|
||||
id: checkbox.id,
|
||||
name: checkbox.name,
|
||||
checkedAll: false,
|
||||
indeterminate: false,
|
||||
selected: [],
|
||||
actionsOptions:
|
||||
checkbox.children?.map((p: Resource) => {
|
||||
return {
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
}
|
||||
}) || [],
|
||||
}
|
||||
}) || [],
|
||||
}
|
||||
})
|
||||
|
||||
//初始化权限资源树
|
||||
reqResourceTree().then(res => {
|
||||
rolePermission.value = res.data.map((menu: Resource) => {
|
||||
return {
|
||||
id: menu.id,
|
||||
name: menu.name,
|
||||
enabled: true,
|
||||
children: menu.children?.map((checkbox: Resource) => {
|
||||
return {
|
||||
id: checkbox.id,
|
||||
name: checkbox.name,
|
||||
checkedAll: false,
|
||||
indeterminate: false,
|
||||
selected: [],
|
||||
actionsOptions: checkbox.children?.map((p: Resource) => {
|
||||
return {
|
||||
id: p.id,
|
||||
name: p.name
|
||||
};
|
||||
}) || []
|
||||
};
|
||||
}) || []
|
||||
};
|
||||
});
|
||||
|
||||
// 赋值
|
||||
handlePermission();
|
||||
});
|
||||
// 赋值
|
||||
handlePermission()
|
||||
})
|
||||
}
|
||||
|
||||
function handlePermission() {
|
||||
let role: any = roleList.value.find(r => r.id == activeRoleId.value);
|
||||
const resourceIds: number[] = role.resourceIds || [];
|
||||
rolePermission.value.forEach(p => {
|
||||
onChangeSwitch(resourceIds.includes(p.id), p);
|
||||
p.children.forEach(pp => {
|
||||
const selected: any[] = pp.actionsOptions.filter(action => resourceIds.includes(action.id)).map(action => action.id);
|
||||
onChangeCheckAll(selected.length === pp.actionsOptions.length, pp);
|
||||
pp.selected = selected;
|
||||
onChangeCheck(selected, pp);
|
||||
});
|
||||
});
|
||||
let role: any = roleList.value.find((r) => r.id == activeRoleId.value)
|
||||
const resourceIds: number[] = role.resourceIds || []
|
||||
rolePermission.value.forEach((p) => {
|
||||
onChangeSwitch(resourceIds.includes(p.id), p)
|
||||
p.children.forEach((pp) => {
|
||||
const selected: any[] = pp.actionsOptions
|
||||
.filter((action) => resourceIds.includes(action.id))
|
||||
.map((action) => action.id)
|
||||
onChangeCheckAll(selected.length === pp.actionsOptions.length, pp)
|
||||
pp.selected = selected
|
||||
onChangeCheck(selected, pp)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const onChangeSwitch = (enabled: boolean, permission: any) => {
|
||||
permission.enabled = enabled;
|
||||
permission.enabled = enabled
|
||||
}
|
||||
|
||||
const onChangeCheckAll = (checked: boolean, permission: any) => {
|
||||
Object.assign(permission, {
|
||||
selected: checked ? permission.actionsOptions.map((obj: any) => obj.id) : [],
|
||||
indeterminate: false,
|
||||
checkedAll: checked
|
||||
});
|
||||
Object.assign(permission, {
|
||||
selected: checked ? permission.actionsOptions.map((obj: any) => obj.id) : [],
|
||||
indeterminate: false,
|
||||
checkedAll: checked,
|
||||
})
|
||||
}
|
||||
|
||||
const onChangeCheck = (selected: number[], permission: any) => {
|
||||
permission.indeterminate = !!permission.selected.length && (permission.selected.length < permission.actionsOptions.length);
|
||||
permission.checkedAll = permission.selected.length === permission.actionsOptions.length;
|
||||
permission.indeterminate =
|
||||
!!permission.selected.length && permission.selected.length < permission.actionsOptions.length
|
||||
permission.checkedAll = permission.selected.length === permission.actionsOptions.length
|
||||
}
|
||||
|
||||
const handleChangeRoleUserClient = (tab: TabsPaneContext, event: Event) => {
|
||||
|
||||
}
|
||||
const handleChangeRoleUserClient = (tab: TabsPaneContext, event: Event) => {}
|
||||
|
||||
const handleEdit = () => {
|
||||
let role: any = roleList.value?.find(r => r?.id === activeRoleId.value);
|
||||
form.name = role.name;
|
||||
form.description = role.description;
|
||||
editVisible.value = true;
|
||||
};
|
||||
let role: any = roleList.value?.find((r) => r?.id === activeRoleId.value)
|
||||
form.name = role.name
|
||||
form.description = role.description
|
||||
editVisible.value = true
|
||||
}
|
||||
|
||||
const addVisible = ref<boolean>(false);
|
||||
const editVisible = ref<boolean>(false);
|
||||
let form = reactive(new Role());
|
||||
const addVisible = ref<boolean>(false)
|
||||
const editVisible = ref<boolean>(false)
|
||||
let form = reactive(new Role())
|
||||
|
||||
const saveAdd = () => {
|
||||
createRole(form).then(res => {
|
||||
reqRoleList();
|
||||
ElMessage.success(`新增成功`);
|
||||
addVisible.value = false;
|
||||
});
|
||||
};
|
||||
createRole(form).then((res) => {
|
||||
reqRoleList()
|
||||
ElMessage.success(`新增成功`)
|
||||
addVisible.value = false
|
||||
})
|
||||
}
|
||||
const saveEdit = () => {
|
||||
updateRole(activeRoleId.value, form).then(res => {
|
||||
reqRoleList();
|
||||
ElMessage.success(`修改成功`);
|
||||
editVisible.value = false;
|
||||
});
|
||||
};
|
||||
updateRole(activeRoleId.value, form).then((res) => {
|
||||
reqRoleList()
|
||||
ElMessage.success(`修改成功`)
|
||||
editVisible.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const savePermission = () => {
|
||||
let resourceIds: number[] = [];
|
||||
rolePermission.value.forEach(p => {
|
||||
if (p.enabled) {
|
||||
resourceIds.push(p.id);
|
||||
}
|
||||
p.children.forEach(pp => {
|
||||
if (pp.selected?.length) {
|
||||
resourceIds.push(pp.id);
|
||||
}
|
||||
pp.selected.forEach(sel => resourceIds.push(sel));
|
||||
console.log('rolePermission', rolePermission)
|
||||
let resourceIds: number[] = []
|
||||
rolePermission.value.forEach((p) => {
|
||||
if (p.enabled) {
|
||||
resourceIds.push(p.id)
|
||||
}
|
||||
p.children.forEach((pp) => {
|
||||
if (pp.selected?.length) {
|
||||
resourceIds.push(pp.id)
|
||||
}
|
||||
|
||||
if (pp.checkedAll) {
|
||||
resourceIds.push(pp.id)
|
||||
}
|
||||
pp.selected.forEach((sel) => resourceIds.push(sel))
|
||||
})
|
||||
})
|
||||
|
||||
changeResources(activeRoleId.value, resourceIds).then((res) => {
|
||||
reqRoleList()
|
||||
ElMessage.success(`修改角色权限成功`)
|
||||
editVisible.value = false
|
||||
})
|
||||
});
|
||||
changeResources(activeRoleId.value, resourceIds).then(res => {
|
||||
reqRoleList();
|
||||
ElMessage.success(`修改角色权限成功`);
|
||||
editVisible.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
// 删除操作
|
||||
const handleDelete = (role: any) => {
|
||||
// 二次确认删除
|
||||
ElMessageBox.confirm('确定要删除吗?', '提示', {
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
deleteRole(role.id).then(res => {
|
||||
reqRoleList();
|
||||
ElMessage.success('删除成功');
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
};
|
||||
// 二次确认删除
|
||||
ElMessageBox.confirm('确定要删除吗?', '提示', {
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
deleteRole(role.id).then((res) => {
|
||||
reqRoleList()
|
||||
ElMessage.success('删除成功')
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
const handleOrgSelectCancel = () => {
|
||||
isOrgSelectShow.value = false;
|
||||
isOrgSelectShow.value = false
|
||||
}
|
||||
const handleOrgSelectSubmit = (p: OrgSelectedData) => {
|
||||
isOrgSelectShow.value = false;
|
||||
console.log(p);
|
||||
debugger
|
||||
let userIds: number[] = p.selected?.map((u: { id: number; }) => u.id);
|
||||
changeUsers(activeRoleId.value, userIds).then(res => {
|
||||
getUserData(activeRoleId.value);
|
||||
ElMessage.success(`修改角色成员成功`);
|
||||
editVisible.value = false;
|
||||
});
|
||||
isOrgSelectShow.value = false
|
||||
console.log(p)
|
||||
debugger
|
||||
let userIds: number[] = p.selected?.map((u: { id: number }) => u.id)
|
||||
changeUsers(activeRoleId.value, userIds).then((res) => {
|
||||
getUserData(activeRoleId.value)
|
||||
ElMessage.success(`修改角色成员成功`)
|
||||
editVisible.value = false
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.data-center-wrap {
|
||||
position: relative;
|
||||
position: relative;
|
||||
|
||||
.role-item {
|
||||
font-size: 14px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 4px;
|
||||
.role-item {
|
||||
font-size: 14px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 4px;
|
||||
|
||||
&:hover {
|
||||
background-color: #f5f7fa;
|
||||
&:hover {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
&-active {
|
||||
background-color: #ecf5ff;
|
||||
}
|
||||
|
||||
.el-icon {
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
&-active {
|
||||
background-color: #ecf5ff;
|
||||
.el-pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin: 20px 0;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.el-icon {
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin: 20px 0;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.red {
|
||||
color: #F56C6C;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.table-td-thumb {
|
||||
display: block;
|
||||
margin: auto;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: block;
|
||||
margin: auto;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,22 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"sourceMap": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.d.ts","src/**/*.vue"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"sourceMap": true,
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"skipLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"],
|
||||
"references": [{ "path": "./tsconfig.node.json" }]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +1,42 @@
|
|||
import { defineConfig } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import VueSetupExtend from 'vite-plugin-vue-setup-extend';
|
||||
import AutoImport from 'unplugin-auto-import/vite';
|
||||
import Components from 'unplugin-vue-components/vite';
|
||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import VueSetupExtend from 'vite-plugin-vue-setup-extend'
|
||||
import AutoImport from 'unplugin-auto-import/vite'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||
import path from 'path'
|
||||
|
||||
export default defineConfig({
|
||||
base: './',
|
||||
plugins: [
|
||||
vue(),
|
||||
VueSetupExtend(),
|
||||
AutoImport({
|
||||
resolvers: [ElementPlusResolver()]
|
||||
}),
|
||||
Components({
|
||||
resolvers: [ElementPlusResolver()]
|
||||
})
|
||||
],
|
||||
server: {
|
||||
host: '0.0.0.0',
|
||||
port: 8080,
|
||||
proxy: {
|
||||
'/admin3': {
|
||||
target: `http://192.168.0.38:8080`,
|
||||
},
|
||||
},
|
||||
},
|
||||
optimizeDeps: {
|
||||
include: ['schart.js']
|
||||
}
|
||||
});
|
||||
base: '/',
|
||||
plugins: [
|
||||
vue(),
|
||||
VueSetupExtend(),
|
||||
AutoImport({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),
|
||||
Components({
|
||||
resolvers: [ElementPlusResolver()],
|
||||
}),
|
||||
],
|
||||
server: {
|
||||
host: '0.0.0.0',
|
||||
port: 8080,
|
||||
proxy: {
|
||||
'/dev-api': {
|
||||
// target: `http://192.168.0.38:8080/search_tool`,
|
||||
target: `http://192.168.0.60:8080`,
|
||||
secure: false,
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/dev-api/, ''),
|
||||
},
|
||||
},
|
||||
},
|
||||
optimizeDeps: {
|
||||
include: ['schart.js'],
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, './src'),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
|||
26
yarn.lock
26
yarn.lock
|
|
@ -111,6 +111,13 @@
|
|||
resolved "https://repo.huaweicloud.com/repository/npm/@types/marked/-/marked-4.0.5.tgz"
|
||||
integrity sha512-jMN2moJ+lSf1VZXQo3VXeMCjoXuciVONig8+U0YNBop5aBvQw4qkolx1Nzn1i0T8L2l9IZ3jju6bS1pPwlaY1w==
|
||||
|
||||
"@types/node@^22.14.1", "@types/node@>= 14":
|
||||
version "22.14.1"
|
||||
resolved "https://repo.huaweicloud.com/repository/npm/@types/node/-/node-22.14.1.tgz"
|
||||
integrity sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==
|
||||
dependencies:
|
||||
undici-types "~6.21.0"
|
||||
|
||||
"@types/web-bluetooth@^0.0.15":
|
||||
version "0.0.15"
|
||||
resolved "https://repo.huaweicloud.com/repository/npm/@types/web-bluetooth/-/web-bluetooth-0.0.15.tgz"
|
||||
|
|
@ -687,6 +694,11 @@ nanoid@^3.3.6:
|
|||
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz"
|
||||
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
|
||||
|
||||
neo-async@^2.6.2:
|
||||
version "2.6.2"
|
||||
resolved "https://repo.huaweicloud.com/repository/npm/neo-async/-/neo-async-2.6.2.tgz"
|
||||
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
||||
|
||||
normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz"
|
||||
|
|
@ -797,7 +809,14 @@ run-parallel@^1.1.9:
|
|||
dependencies:
|
||||
queue-microtask "^1.2.2"
|
||||
|
||||
sass@*, sass@^1.49.7:
|
||||
sass-loader@^16.0.5:
|
||||
version "16.0.5"
|
||||
resolved "https://repo.huaweicloud.com/repository/npm/sass-loader/-/sass-loader-16.0.5.tgz"
|
||||
integrity sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==
|
||||
dependencies:
|
||||
neo-async "^2.6.2"
|
||||
|
||||
sass@*, sass@^1.3.0, sass@^1.49.7:
|
||||
version "1.62.1"
|
||||
resolved "https://registry.npmjs.org/sass/-/sass-1.62.1.tgz"
|
||||
integrity sha512-NHpxIzN29MXvWiuswfc1W3I0N8SXBd8UR26WntmDlRYf0bSADnwnOjsyMZ3lMezSlArD33Vs3YFhp7dWvL770A==
|
||||
|
|
@ -872,6 +891,11 @@ ufo@^1.1.2:
|
|||
resolved "https://registry.npmjs.org/ufo/-/ufo-1.1.2.tgz"
|
||||
integrity sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==
|
||||
|
||||
undici-types@~6.21.0:
|
||||
version "6.21.0"
|
||||
resolved "https://repo.huaweicloud.com/repository/npm/undici-types/-/undici-types-6.21.0.tgz"
|
||||
integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==
|
||||
|
||||
unimport@^1.0.1:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmjs.org/unimport/-/unimport-1.3.0.tgz"
|
||||
|
|
|
|||
Loading…
Reference in New Issue