提交 2f298568 authored 作者: Administrator's avatar Administrator

更新依赖,去除冗余代码

上级 87c17e4a
# 开发环境 # 开发环境
VITE_APP_TITLE = "星云平台测试" VITE_APP_TITLE = "Lic管理系统"
VITE_APP_PORT = 3003 VITE_APP_PORT = 3003
# 请求接口 # 请求接口
VITE_APP_BASE_URL = "lic" VITE_APP_BASE_URL = "lic"
\ No newline at end of file
#生产环境 #生产环境
VITE_APP_TITLE = "星云平台" VITE_APP_TITLE = "Lic平台"
VITE_APP_PORT = 3002 VITE_APP_PORT = 3002
# 请求接口 # 请求接口
VITE_APP_BASE_URL = "lic" VITE_APP_BASE_URL = "lic"
# starbos-ui #### Software Architecture
#### Description Software architecture description
星支平台前端框架,
#### Installation
#### Software Architecture
Software architecture description 1. xxxx
2. xxxx
#### Installation 3. xxxx
1. xxxx #### Instructions
2. xxxx
3. xxxx 1. xxxx
2. xxxx
#### Instructions 3. xxxx
1. xxxx #### Contribution
2. xxxx
3. xxxx 1. Fork the repository
2. Create Feat_xxx branch
#### Contribution 3. Commit your code
4. Create Pull Request
1. Fork the repository
2. Create Feat_xxx branch #### Gitee Feature
3. Commit your code
4. Create Pull Request 1. You can use Readme_XXX.md to support different languages, such as Readme_en.md, Readme_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
#### Gitee Feature 4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md 6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
# starbos-ui # starbos-ui
#### 介绍 #### 介绍
星云平台前端框架,基于vite +vue3.0+typescript+element-plus开发
Lic 平台前端框架,基于 vite +vue3.0+typescript+element-plus 开发
## 项目安装
``` ## 项目安装
yarn install
``` ```
yarn install
### 项目编译及启动 ```
```
yarn dev ### 项目编译及启动
```
```
### 编译部署 yarn dev
``` ```
yarn build
``` ### 编译部署
### 行格式化 ```
``` yarn build
yarn lint ```
```
### 行格式化
### 自定义配置
See [Configuration Reference](https://cli.vuejs.org/config/). ```
yarn lint
```
### 自定义配置
See [Configuration Reference](https://cli.vuejs.org/config/).
...@@ -3,3 +3,5 @@ services: ...@@ -3,3 +3,5 @@ services:
build: build:
context: ./ context: ./
image: registry.lingqingkeji.com/lic-portal image: registry.lingqingkeji.com/lic-portal
ports:
- 8091:8091
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -8,39 +8,33 @@ ...@@ -8,39 +8,33 @@
"tsc": "vue-tsc --noEmit" "tsc": "vue-tsc --noEmit"
}, },
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^1.1.4", "@element-plus/icons-vue": "^2.0.10",
"axios": "^0.24.0", "axios": "^0.24.0",
"echarts": "^5.3.0", "element-plus": "^2.6.0",
"element-plus": "^2.1.11",
"eslint": "^8.4.1", "eslint": "^8.4.1",
"eslint-plugin-vue": "^8.2.0", "eslint-plugin-vue": "^8.2.0",
"lodash": "^4.17.21",
"moment": "^2.29.1",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"qs": "^6.10.3", "qs": "^6.10.3",
"socket.io-client": "^4.5.0", "vue": "^3.2.45",
"vue": "^3.2.33",
"vue-demi": "^0.13.1", "vue-demi": "^0.13.1",
"vue-i18n": "^9.1.10", "vue-i18n": "^9.1.10",
"vue-router": "4", "vue-router": "^4.1.6",
"vue-socket.io": "^3.0.10",
"vue3-cron": "^1.1.8",
"vuex": "^4.0.2" "vuex": "^4.0.2"
}, },
"devDependencies": { "devDependencies": {
"@types/lodash": "^4.14.182", "@types/node": "^18.11.18",
"@types/node": "^16.11.12",
"@types/qs": "^6.9.7", "@types/qs": "^6.9.7",
"@vitejs/plugin-vue": "^2.3.1", "@vitejs/plugin-vue": "^4.0.0",
"sass": "^1.86.0", "sass": "^1.57.1",
"typescript": "^4.4.3", "terser": "^5.39.0",
"unplugin-auto-import": "^0.7.1", "typescript": "^4.9.3",
"unplugin-auto-import": "^0.12.1",
"unplugin-icons": "^0.14.3", "unplugin-icons": "^0.14.3",
"unplugin-vue-components": "^0.19.3", "unplugin-vue-components": "^0.22.12",
"vite": "^2.6.14", "vite": "^4.0.0",
"vite-plugin-inspect": "^0.5.0", "vite-plugin-inspect": "^0.5.0",
"vite-plugin-svg-icons": "^2.0.1", "vite-plugin-svg-icons": "^2.0.1",
"vue-tsc": "^0.3.0" "vue-tsc": "^1.0.11"
}, },
"license": "ISC" "license": "ISC"
} }
This source diff could not be displayed because it is too large. You can view the blob instead.
<!-- 此处注意,使用 v-model="visible"绑定的形式 <template>
上线会报错 <el-dialog
:title="title"
修改为如下方式 :model-value="visible"
:model-value="visible" :before-close="onClose"
--> append-to-body
<template> :width="width + 'px'"
<el-dialog >
:title='title' <div class="container" :style="{ height: height + 'px' }">
:model-value="visible" <slot name="content"></slot>
:before-close="onClose" </div>
append-to-body <template #footer>
:width="width + 'px'" <span class="dialog-footer">
> <el-button type="danger" @click="onClose">取消</el-button>
<div class="container" :style="{height:height + 'px'}"> <el-button type="primary" @click="onConfirm">确定</el-button>
<slot name="content"></slot> </span>
</div> </template>
<template #footer> </el-dialog>
<span class="dialog-footer"> </template>
<el-button type='danger' @click="onClose">取消</el-button> <script setup lang="ts">
<el-button type="primary" @click="onConfirm">确定</el-button> defineProps({
</span> title: {
</template> //弹框标题
</el-dialog> type: String,
</template> default: "标题",
<script setup lang='ts'> },
import { ref, reactive } from 'vue' visible: {
const props = defineProps({ //控制弹框的展示和影藏
title: {//弹框标题 type: Boolean,
type: String, default: false,
default: '标题' },
}, width: {
visible: { //控制弹框的展示和影藏 type: Number,
type: Boolean, default: 600,
default: false },
}, height: {
width: { type: Number,
type: Number, default: 250,
default: 600 },
}, });
height: { const emit = defineEmits(["onClose", "onConfirm"]);
type: Number, //定义弹框的关闭
default: 250 const onClose = () => {
} emit("onClose");
}) };
const emit = defineEmits(['onClose','onConfirm']) //定义弹框的确定
//定义弹框的关闭 const onConfirm = () => {
const onClose = () =>{ emit("onConfirm");
emit('onClose') };
} </script>
//定义弹框的确定 <style lang="scss" scope>
const onConfirm = () =>{ .container {
emit('onConfirm') overflow-x: initial;
} overflow-y: auto;
</script> }
<style lang="scss" scope> .el-dialog {
.container { border-top-left-radius: 7px !important;
overflow-x: initial; border-top-right-radius: 7px !important;
overflow-y: auto; .el-dialog__header {
} border-top-left-radius: 7px !important;
.el-dialog { border-top-right-radius: 7px !important;
border-top-left-radius: 7px !important; background-color: #1890ff !important;
border-top-right-radius: 7px !important; .el-dialog__title {
.el-dialog__header { color: #fff;
border-top-left-radius: 7px !important; font-size: 16px;
border-top-right-radius: 7px !important; font-weight: 600;
background-color: #1890ff !important; }
.el-dialog__title { .el-dialog__close {
color: #fff; color: #fff;
font-size: 16px; }
font-weight: 600; }
} .el-dialog__body {
.el-dialog__close { padding: 10px;
color: #fff; }
} .el-dialog__footer {
} border-top: 1px solid #e8eaec !important;
.el-dialog__body { padding: 10px;
padding: 10px; }
} }
.el-dialog__footer { </style>
border-top: 1px solid #e8eaec !important;
padding: 10px;
}
}
</style>
\ No newline at end of file
<template>
<div class="components-input-demo-presuffix">
<a-input
@click="openModal"
placeholder="corn表达式"
v-model="cron"
@change="handleOK"
>
<a-icon slot="prefix" type="schedule" title="corn控件" />
<a-icon
v-if="cron"
slot="suffix"
type="close-circle"
@click="handleEmpty"
title="清空"
/>
</a-input>
<JCronModal ref="innerVueCron" :data="cron" @ok="handleOK"></JCronModal>
</div>
</template>
<script>
import JCronModal from "@/components/corn/JCronModal.vue";
export default {
name: "JCron",
components: {
JCronModal,
},
props: {
value: {
required: false,
type: String,
default: "",
},
},
data() {
return {
cron: this.value,
};
},
watch: {
value(val) {
this.cron = val;
},
},
methods: {
openModal() {
this.$refs.innerVueCron.show();
},
handleOK(val) {
this.cron = val;
this.$emit("change", this.cron);
// this.$emit("change", Object.assign({}, this.cron));
},
handleEmpty() {
this.handleOK("");
},
},
model: {
prop: "value",
event: "change",
},
};
</script>
<style scoped>
.components-input-demo-presuffix .anticon-close-circle {
cursor: pointer;
color: #ccc;
transition: color 0.3s;
font-size: 12px;
}
.components-input-demo-presuffix .anticon-close-circle:hover {
color: #f5222d;
}
.components-input-demo-presuffix .anticon-close-circle:active {
color: #666;
}
</style>
差异被折叠。
<template>
<div>
<div ref="commonEchartRef" :style="{ height: height, width: width }"></div>
</div>
</template>
<script setup lang='ts'>
import { ref, onMounted, watchEffect } from 'vue'
import useEcharts from '@/hooks/useEcharts';
//接收父组件传递的参数
//withDefaults:设置默认值
const props = withDefaults(defineProps<{
width?: string,
height: string,
optios: any
}>(), {
width: '100%',
height: '360px'
})
//定义ref属性
const commonEchartRef = ref<HTMLElement>()
onMounted(() => {
//叹号:断定commonEchartRef.value存在
const { setOptions, resize } = useEcharts(commonEchartRef.value!)
watchEffect(() => {
setOptions(props.optios)
})
//自适应
window.addEventListener('resize', () => {
resize();
})
})
</script>
<style scoped lang='scss'>
</style>
\ No newline at end of file
<template> <template>
<div style="margin-top: 20px;"> <div style="margin-top: 20px">
<el-pagination v-model:currentPage="pageData.pageNo" v-model:page-size="pageData.pageSize" <el-pagination
:page-sizes="[10, 15, 20]" :small="pageData.small" :disabled="pageData.disabled" v-model:currentPage="pageData.pageNo"
:background="pageData.background" layout="->, total, sizes, prev, pager, next, jumper" :total="total" v-model:page-size="pageData.pageSize"
@size-change="handleSizeChange" hide-on-single-page @current-change="handleCurrentChange" /> :page-sizes="[10, 15, 20]"
</div> :small="pageData.small"
</template> :disabled="pageData.disabled"
:background="pageData.background"
<script setup lang='ts'> layout="->, total, sizes, prev, pager, next, jumper"
:total="total"
let props = defineProps({ @size-change="handleSizeChange"
pageData: { hide-on-single-page
type: Object, @current-change="handleCurrentChange"
default: { />
pageNo: { </div>
type: Number, </template>
default: 1
}, <script setup lang="ts">
pageSize: { let props = defineProps({
type: Number, pageData: {
default: 10 type: Object,
}, default: {
small: { pageNo: {
type: Boolean, type: Number,
default: false default: 1,
}, },
disabled: { pageSize: {
type: Boolean, type: Number,
default: false default: 10,
}, },
background: { small: {
type: String || Boolean, type: Boolean,
default: '' || false default: false,
} },
} disabled: {
}, type: Boolean,
total: { default: false,
type: Number, },
default: 0 background: {
} type: String || Boolean,
}) default: "" || false,
},
let emits = defineEmits(['sizeChange', 'currentChange']) },
},
// 新条数 total: {
const handleSizeChange = (val: number) => { type: Number,
emits('sizeChange', val) default: 0,
} },
});
// // 新页数
const handleCurrentChange = (val: number) => { let emits = defineEmits(["sizeChange", "currentChange"]);
emits('currentChange', val)
} // 新条数
</script> const handleSizeChange = (val: number) => {
emits("sizeChange", val);
<style lang = "scss" scoped> };
</style>
\ No newline at end of file // // 新页数
const handleCurrentChange = (val: number) => {
emits("currentChange", val);
};
</script>
import {reactive} from 'vue'
import { DialogModel } from "@/type/BastType";
export default function useDialog(){
//定义弹框属性
const dialog = reactive<DialogModel>({
title:'',
visible:false,
width:630,
height:280
})
//展示
const onShow = () =>{
dialog.visible = true;
}
//关闭
const onClose = () =>{
dialog.visible =false;
}
//确定
const onConfirm = () =>{
dialog.visible = false;
}
return {
dialog,
onShow,
onClose,
onConfirm
}
}
\ No newline at end of file
import * as echarts from 'echarts'
export default function useEcharts(el:HTMLElement){
//初始化echarts
const echartsInstance = echarts.init(el);
//设置options
const setOptions = (options:any) =>{
echartsInstance.setOption(options)
}
//自适应监听
const resize = () =>{
echartsInstance.resize()
}
return{
setOptions,
resize
}
}
\ No newline at end of file
export default { export default {
// 路由国际化 // 路由国际化
route: { route: {
dashboard: '首页', dashboard: "首页",
}, },
// 登录页面国际化 // 登录页面国际化
login: { login: {
title: '星云管理系统', title: "Lic管理系统",
username: '账号', username: "账号",
password: '密码' password: "密码",
},
} };
}
\ No newline at end of file
<template> <template>
<Menu></Menu> <Menu></Menu>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Menu from '@/components/Menu.vue' import Menu from "@/components/Menu.vue";
</script> </script>
<style lang="scss" scoped>
</style>
\ No newline at end of file
<template> <template>
<div> <div></div>
</template>
</div>
</template> <script lang="ts">
export default {
<script lang="ts"> setup() {
export default { return {};
setup () { },
return {} };
} </script>
}
</script>
<style lang="scss" scoped>
</style>
\ No newline at end of file
<template> <template>
<el-breadcrumb separator="/"> <el-breadcrumb separator="/">
<el-breadcrumb-item v-for="item in tabs">{{item.meta.title}}</el-breadcrumb-item> <el-breadcrumb-item v-for="item in tabs">{{item.meta.title}}</el-breadcrumb-item>
</el-breadcrumb> </el-breadcrumb>
</template> </template>
<script setup lang='ts'> <script setup lang='ts'>
import { ref,watch,Ref} from 'vue' import { ref,watch,Ref} from 'vue'
import { useRoute,RouteLocationMatched } from 'vue-router'; import { useRoute,RouteLocationMatched } from 'vue-router';
//定义面包屑导航数据 //定义面包屑导航数据
const tabs :Ref<RouteLocationMatched[]> = ref([]); const tabs :Ref<RouteLocationMatched[]> = ref([]);
const route = useRoute(); const route = useRoute();
const getBredcurm = ()=>{ const getBredcurm = ()=>{
//获取所有有meta和title //获取所有有meta和title
let mached = route.matched.filter(item => item.meta && item.meta.title); let mached = route.matched.filter(item => item.meta && item.meta.title);
//判断第一个是否是首页,如果不是,构造一个 //判断第一个是否是首页,如果不是,构造一个
const first = mached[0]; const first = mached[0];
if(first && first.path !== '/licInformation'){ if(first && first.path !== '/licInformation'){
//构造一个 //构造一个
mached = [{path: '/licInformation',meta:{title:'首页'}} as any].concat(mached); mached = [{path: '/licInformation',meta:{title:'首页'}} as any].concat(mached);
} }
//设置面包屑导航数据 //设置面包屑导航数据
tabs.value = mached; tabs.value = mached;
} }
getBredcurm(); getBredcurm();
//路由发生变化,重新获取面包屑导航数据 //路由发生变化,重新获取面包屑导航数据
watch(()=>route.path,()=>getBredcurm()); watch(()=>route.path,()=>getBredcurm());
</script> </script>
<style scoped lang='scss'>
</style>
\ No newline at end of file
<template> <template>
<el-dropdown placement="bottom-start"> <el-dropdown placement="bottom-start">
<span class="el-dropdown-link"> <span class="el-dropdown-link">
<el-avatar :size="45" fit="contain" :src="avatar" /> <el-avatar :size="45" fit="contain" :src="avatar" />
</span> </span>
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item @click="userInfo">个人信息</el-dropdown-item> <el-dropdown-item @click="userInfo">个人信息</el-dropdown-item>
<el-dropdown-item @click="loginOut">退出登录</el-dropdown-item> <el-dropdown-item @click="loginOut">退出登录</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
</el-dropdown> </el-dropdown>
</template> </template>
<script setup lang='ts'> <script setup lang="ts">
import useInstance from '@/hooks/useInstance'; import useInstance from "@/hooks/useInstance";
import { cleanSession, getToken } from '@/utils/auth'; import { cleanSession, getToken } from "@/utils/auth";
import {store} from '@/store/index' import { store } from "@/store/index";
import { ref, reactive } from 'vue' import { ref, reactive } from "vue";
import router from '@/router'; import router from "@/router";
const { global } = useInstance() const { global } = useInstance();
const avatar = store.state.user.userAvatar const avatar = store.state.user.userAvatar;
//退出登录 //退出登录
const loginOut = async () => { const loginOut = async () => {
window.location.href = "/#/login"; let confirm = await global.$lqconfirm("确定退出登录吗?");
cleanSession(); if (confirm) {
// let confirm = await global.$myconfirm('确定退出登录吗?') //跳到登录
// if (confirm) { window.location.href = "/#/login";
// let parm = { //清空session
// token: getToken() cleanSession();
// } }
// let res = await loginOutApi(parm) };
// if (res && res.code == 200) {
// //跳到登录 //跳转个人信息
// window.location.href = "/login"; const userInfo = async () => {
// //清空session router.push({ path: "/user" });
// cleanSession(); };
// } </script>
// }
}
//还原数据
// const restore = async () => {
// let confirm = await global.$myconfirm('确定还原数据吗?')
// if (confirm) {
// let res = await restoreApi();
// if (res && res.code == 200) {
// //信息提示
// global.$message({ message: res.message, type: 'success' })
// }
// }
// }
//跳转个人信息
const userInfo = async () => {
router.push({path:'/user'})
}
</script>
<style scoped lang='scss'>
</style>
\ No newline at end of file
<template> <template>
<MenuLogo class="layout-logo" v-if="!isCollapse"></MenuLogo> <MenuLogo class="layout-logo" v-if="!isCollapse"></MenuLogo>
<el-menu :default-active="activeIdex" class="el-menu-vertical-startbos" :collapse="isCollapse" @open="handleOpen" <el-menu
@close="handleClose" background-color="#304156" router> :default-active="activeIdex"
<MenuItem :menuList="menuList"> class="el-menu-vertical-startbos"
</MenuItem> :collapse="isCollapse"
</el-menu> background-color="#304156"
</template> router
<script setup lang="ts"> >
import { reactive, computed } from 'vue' <MenuItem :menuList="menuList"> </MenuItem>
import { useRoute } from 'vue-router' </el-menu>
import { useStore } from '@/store/index' </template>
import MenuItem from './MenuItem.vue' <script setup lang="ts">
import MenuLogo from '@/layout/menu/MenuLogo.vue' import { useStore } from "@/store/index";
// setup语法糖中 定义的数据和方法,直接可以在模板中使用,无需要 return import MenuItem from "./MenuItem.vue";
const store = useStore() import MenuLogo from "@/layout/menu/MenuLogo.vue";
// store.commit('menu/setCollapse') const store = useStore();
// store.dispatch('menu/getMenuList')
// store.getters['user/getPermissions'] //当前路由
//当前路由 const route = useRoute();
const route = useRoute(); const activeIdex = computed(() => {
const activeIdex = computed(() => { const { path } = route;
const { path } = route; return path;
return path; });
}) //菜单数据
//菜单数据 const menuList = computed(() => {
const menuList = computed(() => { return store.getters["menu/getMenuList"];
return store.getters['menu/getMenuList'] });
})
const isCollapse = computed(() => {
return store.getters["menu/getCollapse"];
// let menuList = reactive([ });
// { </script>
// path: '/dashboard', <style scoped>
// component: "Layout", @keyframes logoAnimation {
// meta: { 0% {
// title: "首页", transform: scale(0);
// icon: "HomeFilled", }
// roles: ["sys:manage"]
// }, 50% {
// children: [] transform: scale(1);
// }, }
// {
// path: "/system", 100% {
// component: "Layout", transform: scale(1);
// alwaysShow: true, }
// name: "system", }
// meta: {
// title: "系统管理", .layout-logo {
// icon: "Menu", animation: logoAnimation 1s ease-out;
// roles: ["sys:manage"], }
// parentId: 0,
// }, .el-menu-vertical-startbos:not(.el-menu--collapse) {
// children: [ width: 230px;
// { min-height: 400px;
// path: "/department", }
// component: "/system/department/department",
// alwaysShow: false, .el-menu {
// name: "department", border-right: none;
// meta: { }
// title: "机构管理",
// icon: "Platform", :deep(.el-sub-menu .el-sub-menu__title) {
// roles: ["sys:dept"], color: #f4f4f5 !important;
// parentId: 17, }
// },
// }, :deep(.el-menu .el-menu-item) {
// { color: #bfcbd9;
// path: "/userList", }
// component: "/system/User/UserList",
// alwaysShow: false, /* 菜单点中文字的颜色 */
// name: "userList",
// meta: { :deep(.el-menu-item.is-active) {
// title: "用户管理", color: #409eff !important;
// icon: "el-icon-s-custom", }
// roles: ["sys:user"],
// parentId: 17, /* 当前打开菜单的所有子菜单颜色 */
// },
// }, :deep(.is-opened .el-menu-item) {
// { background-color: #1f2d3d !important;
// path: "/roleList", }
// component: "/system/Role/RoleList",
// alwaysShow: false, /* 鼠标移动菜单的颜色 */
// name: "roleList",
// meta: { :deep(.el-menu-item:hover) {
// title: "角色管理", background-color: #001528 !important;
// icon: "el-icon-s-tools", }
// roles: ["sys:role"], </style>
// parentId: 17,
// },
// },
// {
// path: "/menuList",
// component: "/system/Menu/MenuList",
// alwaysShow: false,
// name: "menuList",
// meta: {
// title: "权限管理",
// icon: "el-icon-document",
// roles: ["sys:menu"],
// parentId: 17,
// },
// },
// ],
// },
// {
// path: "/goods",
// component: "Layout",
// alwaysShow: true,
// name: "goods",
// meta: {
// title: "商品管理",
// icon: "el-icon-document",
// roles: ["sys:goods"],
// parentId: 0,
// },
// children: [
// {
// path: "/goodCategory",
// component: "/goods/goodsCategory/goodsCategoryList",
// alwaysShow: false,
// name: "goodCategory",
// meta: {
// title: "商品分类",
// icon: "el-icon-document",
// roles: ["sys:goodsCategory"],
// parentId: 34,
// },
// },
// ],
// },
// {
// path: "/systenConfig",
// component: "Layout",
// alwaysShow: true,
// name: "systenConfig",
// meta: {
// title: "系统工具",
// icon: "el-icon-document",
// roles: ["sys:systenConfig"],
// parentId: 0,
// },
// children: [
// {
// path: "/document",
// component: "/system/config/systemDocument",
// alwaysShow: false,
// name: "http://42.193.158.170:8089/swagger-ui/index.html",
// meta: {
// title: "接口文档",
// icon: "el-icon-document",
// roles: ["sys:document"],
// parentId: 42,
// },
// },
// ],
// },
// ]);
const isCollapse = computed(() => {
// return store.getters['getCollapse']
return store.getters['menu/getCollapse']
})
const handleOpen = (key: string, keyPath: string[]) => {
// console.log(key, keyPath)
}
const handleClose = (key: string, keyPath: string[]) => {
// console.log(key, keyPath)
}
</script>
<style scoped>
@keyframes logoAnimation {
0% {
transform: scale(0);
}
50% {
transform: scale(1);
}
100% {
transform: scale(1);
}
}
.layout-logo {
animation: logoAnimation 1s ease-out;
}
.el-menu-vertical-startbos:not(.el-menu--collapse) {
width: 230px;
min-height: 400px;
}
.el-menu {
border-right: none;
}
:deep(.el-sub-menu .el-sub-menu__title) {
color: #f4f4f5 !important;
}
:deep(.el-menu .el-menu-item) {
color: #bfcbd9;
}
/* 菜单点中文字的颜色 */
:deep(.el-menu-item.is-active) {
color: #409eff !important;
}
/* 当前打开菜单的所有子菜单颜色 */
:deep(.is-opened .el-menu-item) {
background-color: #1f2d3d !important;
}
/* 鼠标移动菜单的颜色 */
:deep(.el-menu-item:hover) {
background-color: #001528 !important;
}
</style>
\ No newline at end of file
<template> <template>
<div class="logo"> <div class="logo">
<img src="@/assets/logo.png" alt="logo" /> <img src="@/assets/logo.png" alt="logo" />
<span class="title">星云平台</span> <span class="title">Lic管理系统</span>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts"></script>
</script> <style lang="scss" scoped>
<style lang="scss" scoped> .logo {
.logo { background-color: #2b2f3a;
background-color: #2b2f3a; height: 50px;
height: 50px; border: none;
border: none; line-height: 50px;
line-height: 50px; display: flex;
display: flex; align-items: center;
align-items: center; padding-left: 15px;
padding-left: 15px; color: #fff;
color: #fff; img {
img { width: 32px;
width: 32px; height: 32px;
height: 32px; margin-right: 12px;
margin-right: 12px; }
} span {
span { font-weight: 600;
font-weight: 600; line-height: 50px;
line-height: 50px; font-size: 16px;
font-size: 16px; font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif; vertical-align: middle;
vertical-align: middle; }
} }
} </style>
</style>
\ No newline at end of file
import { request } from "../config"; import { request } from "../config";
import qs from "qs"; import qs from "qs";
const COMMON_PATH = ""; const COMMON_PATH = "";
export function toLogin( export function toLogin(
// account // account
data: { username: string; password: string; code: string } data: { username: string; password: string; code: string }
) { ) {
return request({ return request({
url: COMMON_PATH + "/auth/login", url: COMMON_PATH + "/auth/login",
method: "post", method: "post",
data: qs.stringify(data), data: qs.stringify(data),
}); });
} }
// export function getCode(){
// return request({
// url: COMMON_PATH + "/auth/getCaptcha",
// method: 'get',
// })
// }
import { reactive, ref } from "vue"; import { reactive, ref } from "vue";
import { ElForm } from "element-plus"; import { ElForm } from "element-plus";
import { LoginParm } from "@/services/types/user/userModel"; import { LoginParm } from "@/services/types/user/userModel";
export default function useBaseLogin() { export default function useBaseLogin() {
//表单的ref属性 //表单的ref属性
const loginFormRef = ref<InstanceType<typeof ElForm>>(); const loginFormRef = ref<InstanceType<typeof ElForm>>();
//表单绑定的数据 //表单绑定的数据
const loginModel = reactive<LoginParm>({ const loginModel = reactive<LoginParm>({
username: 'admin', username: "admin",
password: 'QWER111.', password: "123456",
code: '' code: "",
}) });
//表单验证规则 //表单验证规则
const rules = reactive({ const rules = reactive({
account: [{ account: [
required: true, {
trigger: 'change', required: true,
message: '请填写登录账户' trigger: "change",
}], message: "请填写登录账户",
password: [{ },
required: true, ],
trigger: 'change', password: [
message: '请填写登录密码' {
}], required: true,
code: [{ trigger: "change",
required: true, message: "请填写登录密码",
trigger: 'change', },
message: '请填写验证码' ],
}] code: [
}) {
return { required: true,
loginModel, trigger: "change",
rules, message: "请填写验证码",
loginFormRef },
} ],
} });
\ No newline at end of file return {
loginModel,
rules,
loginFormRef,
};
}
import { ref, onMounted } from 'vue' import { getImagApi } from "@/services/api/user/userAPI";
import { getImagApi } from '@/services/api/user/userAPI'; import { ElNotification } from "element-plus";
import { ElNotification } from 'element-plus'; import { debounce } from "@/utils/debounce_throttle";
import {debounce} from '@/utils/debounce_throttle' export default function useImage() {
export default function useImage() { //定义图片src
const imgSrc = ref("../../../../checkcode.png");
//定义图片src
const imgSrc = ref('../../../../checkcode.png'); // 获取图片
//btoa 创建一个base64编码的字符串
// 获取图片 const getImage = debounce(async () => {
//btoa 创建一个base64编码的字符串 await getImagApi()
const getImage = debounce(async () => { .then((res) => {
await getImagApi().then(res => { return res.data.data as string;
return res.data.data as string; })
}).then(data => { .then((data) => {
imgSrc.value = data; imgSrc.value = data;
}).catch((err) => { })
ElNotification({ .catch((err) => {
title:'获取验证码失败', ElNotification({
message:err.message, title: "获取验证码失败",
type:'error', message: err.message,
}) type: "error",
}) });
},1000) });
onMounted(() => { }, 1000);
getImage() onMounted(() => {
}) getImage();
return { });
imgSrc, return {
getImage imgSrc,
} getImage,
} };
\ No newline at end of file }
import { ref,getCurrentInstance } from "vue"; import { ref, getCurrentInstance } from "vue";
import { LoginParm } from "@/services/types/user/userModel"; import { LoginParm } from "@/services/types/user/userModel";
import { store } from "@/store"; import { store } from "@/store";
import { ElNotification } from 'element-plus'; import { ElNotification } from "element-plus";
import router from '@/router/index' import router from "@/router/index";
export default function useLogin(loginModel: LoginParm) {
const { proxy } = getCurrentInstance() as any; export default function useLogin(loginModel: LoginParm) {
//登录提交 const { proxy } = getCurrentInstance() as any;
const login = async () => { const num = ref(0);
//表单验证 //登录提交
proxy.$refs.loginFormRef.validate(async (valid: boolean) => { const login = async () => {
if (valid) { //表单验证
loginState.value = true proxy.$refs.loginFormRef.validate(async (valid: boolean) => {
store.dispatch('user/login', loginModel).then((res: any) => { if (valid) {
loginState.value = false loginState.value = true;
if (res.code == 200) { store
ElNotification({ .dispatch("user/login", loginModel)
title:'登录成功', .then((res: any) => {
message:'欢迎回来', if (res.code == 200) {
type:'success', ElNotification({
}) title: "登录成功",
//跳转到首页 message: "欢迎回来",
setTimeout(()=> { type: "success",
router.push({ path: '/' }) });
},1500) //跳转到首页
} else { setTimeout(() => {
ElNotification({ router.push({ path: "/" });
title:'登陆失败', loginState.value = false;
message:res.msg, }, 1000);
type:'error', } else {
}) loginState.value = false;
} num.value++;
}).catch((err) => { ElNotification({
loginState.value = false title: "登录失败",
ElNotification({ message: res.msg,
title:'登录失败', type: "error",
message:err.message, });
type:'error', }
}) })
}) .finally(() => {
} loginState.value = false;
}) });
} }
//登录状态 });
const loginState = ref(false) };
return { //登录状态
login, const loginState = ref(false);
loginState return {
} login,
} num,
\ No newline at end of file loginState,
};
}
/**
* 定义回调函数
* @author ERRUI
*/
class SocketService {
static instance: any = null;
/**
* 单例模式
*/
static get Instance() {
if (SocketService.instance) {
return SocketService.instance;
}
return (SocketService.instance = new SocketService());
}
// 和服务端连接的socket对象
ws: any = null;
// 存储回调函数
callBackMapping = {};
// 标识是否连接成功
connected = false;
// 记录重试的次数
sendRetryCount = 0;
// 重新连接尝试的次数
connectRetryCount = 0;
/**
* 心跳检测机制:20秒发一个检测消息过去
*/
sendFixHeart() {
let sendFixHeartTimer: any = null;
clearInterval(sendFixHeartTimer);
sendFixHeartTimer = setInterval(() => {
this.ws.send(JSON.stringify({}));
}, 20000);
}
/**
* websocket连接
*/
connect() {
// 连接服务器
if (!window.WebSocket) {
return console.log('您的浏览器不支持WebSocket');
}
this.ws = new WebSocket('ws://192.168.2.209:8100/api/starbos_auth/websocket/1/web');
// 连接成功的事件
this.ws.onopen = () => {
console.log('连接服务端成功了,ws状态是' + this.ws.readyState);
this.connected = true;
// 重置重新连接的次数
this.connectRetryCount = 0;
this.sendFixHeart();
};
// 当连接成功之后, 服务器关闭的情况 | 连接服务端失败
this.ws.onclose = () => {
if (this.connectRetryCount >= 10) {
this.ws.close();
console.log('重新连接服务器失败');
} else {
this.connected = false;
this.connectRetryCount++;
setTimeout(() => {
this.close();
this.connect();
console.log('连接服务端失败第' + this.connectRetryCount + '次,1秒后重试');
}, 1000);
}
};
// websocket连接错误
this.ws.onerror = function () {
console.log('Error,websocket连接错误');
};
}
send(data: any) {
// 判断此时此刻有没有连接成功
if (this.connected) {
this.sendRetryCount = 0;
this.ws.send(JSON.stringify(data));
} else {
this.sendRetryCount++;
setTimeout(() => {
this.send(data);
console.log('已经重新发送第:' + this.sendRetryCount + '次');
}, 1000);
}
}
/**
* 关闭websocket连接
*/
close() {
this.ws.close();
}
}
export default SocketService;
\ No newline at end of file
import { InjectionKey } from 'vue'; import { InjectionKey } from "vue";
import { useStore as baseUseStore, createStore, Store } from 'vuex'; import { useStore as baseUseStore, createStore, Store } from "vuex";
import menu, { MenuState } from '@/store/modules/menu' import menu, { MenuState } from "@/store/modules/menu";
import tabs, { TabsState } from '@/store/modules/tabs' import tabs, { TabsState } from "@/store/modules/tabs";
import user, { UserState } from '@/store/modules/user' import user, { UserState } from "@/store/modules/user";
import table, { TableState } from "@/store/modules/table"; import table, { TableState } from "@/store/modules/table";
import socket, { SocketState } from '@/store/modules/socket'; import { StarbosStore } from "./tools";
import { StarbosStore } from './tools';
export type RootState = {
tabs: TabsState;
export type RootState = { menu: MenuState;
tabs: TabsState, user: UserState;
menu: MenuState, table: TableState;
user: UserState, };
table: TableState, //导入所有的模块
socket: SocketState export const modules = {
} tabs: tabs,
//导入所有的模块 menu: menu,
export const modules = { user: user,
tabs: tabs, table: table,
menu: menu, };
user: user,
table: table, export const key: InjectionKey<Store<RootState>> = Symbol();
socket: socket
} export const store = createStore<RootState>({
modules,
export const key: InjectionKey<Store<RootState>> = Symbol() }) as StarbosStore;
export const store = createStore<RootState>({ // 定义自己的 `useStore` 组合式函数
modules export function useStore() {
}) as StarbosStore return baseUseStore(key) as StarbosStore;
}
// 定义自己的 `useStore` 组合式函数
export function useStore() {
return baseUseStore(key) as StarbosStore
}
import { getMenuListApi } from "@/services/api/menu/menuAPI"; import { getMenuListApi } from "@/services/api/menu/menuAPI";
import { RouteRecordRaw } from "vue-router"; import { RouteRecordRaw } from "vue-router";
import { ActionContext } from "vuex"; import { ActionContext } from "vuex";
import { RootState } from ".."; import { RootState } from "..";
import Layout from '@/layout/index.vue' import Layout from "@/layout/index.vue";
import { store } from '@/store' import { store } from "@/store";
const modules = import.meta.glob('../../views/**/*.vue') const modules = import.meta.glob("../../views/**/*.vue");
//定义state //定义state
export type MenuState = { export type MenuState = {
count: number, count: number;
collapse: boolean, collapse: boolean;
//菜单 //菜单
menuList: any; menuList: any;
} };
export const state: MenuState = { export const state: MenuState = {
count: 0, count: 0,
collapse: false, collapse: false,
menuList: [ menuList: [
{ {
path: '/licInformation', path: "/licInformation",
component: "Layout", component: "Layout",
meta: { meta: {
title: "首页", title: "Lic信息",
icon: "HomeFilled", icon: "HomeFilled",
roles: ["sys:manage"] roles: ["sys:manage"],
}, },
children: [] children: [],
} },
] ],
} };
//定义mutations //定义mutations
export const mutations = { export const mutations = {
setCount(state: MenuState, count: number) { setCount(state: MenuState, count: number) {
state.count = count; state.count = count;
}, },
//设置collapse //设置collapse
setCollapse: (state: MenuState, collapse: boolean) => { setCollapse: (state: MenuState, collapse: boolean) => {
state.collapse = collapse; state.collapse = collapse;
}, },
setMenuList: (state: MenuState, menuList: Array<RouteRecordRaw>) => { setMenuList: (state: MenuState, menuList: Array<RouteRecordRaw>) => {
state.menuList = state.menuList.concat(menuList) state.menuList = state.menuList.concat(menuList);
}, },
reSetList: (state: MenuState, menuList: Array<RouteRecordRaw>) => { reSetList: (state: MenuState, menuList: Array<RouteRecordRaw>) => {
state.menuList = state.menuList.concat(menuList) state.menuList = state.menuList.concat(menuList);
} },
} };
//定义actions //定义actions
export const actions = { export const actions = {
getMenuList({ commit }: ActionContext<MenuState, RootState>, router: any) { getMenuList({ commit }: ActionContext<MenuState, RootState>, router: any) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
getMenuListApi().then(res => { getMenuListApi()
/* res.data.forEach(item => { .then((res) => {
if (item.meta.title === '部门') { /* res.data.forEach(item => {
item.children = [] if (item.meta.title === '部门') {
} item.children = []
}) */ }
let accessedRoutes; }) */
if (res.code == 200) { let accessedRoutes;
//动态生成路由 if (res.code == 200) {
accessedRoutes = filterAsyncRoutes(res.data, router); //动态生成路由
//设置到menuList accessedRoutes = filterAsyncRoutes(res.data, router);
commit('setMenuList', accessedRoutes) //设置到menuList
} commit("setMenuList", accessedRoutes);
//返回 }
resolve(accessedRoutes); //返回
}).catch(error => { resolve(accessedRoutes);
reject(error) })
}) .catch((error) => {
}) reject(error);
} });
} });
export function filterAsyncRoutes(routes: RouteRecordRaw[], router: any) { },
const res: Array<RouteRecordRaw> = []; };
routes.forEach((route: any) => { export function filterAsyncRoutes(routes: RouteRecordRaw[], router: any) {
const tmp = { ...route } const res: Array<RouteRecordRaw> = [];
const component = tmp.component; routes.forEach((route: any) => {
if (route.component) { const tmp = { ...route };
if (component == 'Layout') { const component = tmp.component;
tmp.component = Layout; if (route.component) {
} else { if (component == "Layout") {
tmp.component = modules[`../../views${component}.vue`] tmp.component = Layout;
} } else {
} tmp.component = modules[`../../views${component}.vue`];
if (tmp.children) { }
//递归 }
tmp.children = filterAsyncRoutes(tmp.children, router) if (tmp.children) {
} //递归
router.addRoute(tmp) tmp.children = filterAsyncRoutes(tmp.children, router);
res.push(tmp) }
}) router.addRoute(tmp);
return res; res.push(tmp);
} });
//定义getters return res;
export const getters = { }
getCount(state: MenuState) { //定义getters
return state.count; export const getters = {
}, getCount(state: MenuState) {
//获取collapse return state.count;
getCollapse: (state: MenuState) => { },
return state.collapse; //获取collapse
}, getCollapse: (state: MenuState) => {
getMenuList: (state: MenuState) => { return state.collapse;
return state.menuList },
} getMenuList: (state: MenuState) => {
} return state.menuList;
export default { },
namespaced: true, };
state, export default {
mutations, namespaced: true,
actions, state,
getters mutations,
} actions,
\ No newline at end of file getters,
};
import { RootState } from "../index"
import { ActionContext } from "vuex"
//定义state类型
export type SocketState = {
data:string;
}
//定义state
export const state:SocketState = {
data:''
}
//定义mutations
export const mutations = {
setData(state:SocketState,data:string){
state.data = data
localStorage.setItem('socketData',data)
}
}
//定义actions
export const actions = {
}
//定义getters
export const getters = {
getData(state:SocketState){
return state.data
}
}
export default {
namespaced: true,
state,
mutations,
actions,
getters
}
\ No newline at end of file
import { getTableList } from '@/services/api/customTable' import { getTableList } from "@/services/api/customTable";
import { ref } from 'vue' import { ref } from "vue";
import { useRoute } from 'vue-router' import { useRoute } from "vue-router";
export function tableLogic(props: Readonly<any>) { export function tableLogic(props: Readonly<any>) {
const tableData = ref([]) const tableData = ref([]);
const apiKey: any = useRoute().meta.apiKey const apiKey: any = useRoute().meta.apiKey;
const completeApi = props.tableConfigData.apiKey + props.tableConfigData.tableApi const completeApi =
props.tableConfigData.apiKey + props.tableConfigData.tableApi;
function init() {
getTableList(completeApi ?? apiKey).then((res: any) => { function init() {
if (res.code === 200) { getTableList(completeApi ?? apiKey).then((res: any) => {
console.log(res) if (res.code === 200) {
if (props.tableConfigData.dataKey) { if (props.tableConfigData.dataKey) {
tableData.value = res.data[props.tableConfigData.dataKey] tableData.value = res.data[props.tableConfigData.dataKey];
} else { } else {
tableData.value = res.data tableData.value = res.data;
} }
} }
}) });
} }
init() init();
return { return {
tableData, tableData,
init init,
} };
} }
差异被折叠。
interface Scope {
interface Scope{ row: any;
row: any; $index: number;
$index: number; cellIndex: number;
cellIndex: number }
}
export interface FormItem {
export interface FormItem{ label: string;
label: string; prop: string;
prop: string; type: "" | "input" | "radio" | "select" | "switch";
type: '' | 'input' | 'radio' | 'select' | 'switch'; selectProp?: {
selectProp?: { value: string;
value: string; label: string;
label: string; };
}, hidden?: boolean;
hidden?: boolean; inputType?: string;
inputType?: string; viewType?: "field" | "avater" | "module"; // 表格渲染 field直接渲染 avatar渲染头像 module自定义渲染
viewType?: 'field' | 'avater' | 'module', // 表格渲染 field直接渲染 avatar渲染头像 module自定义渲染 width?: string;
width?: string; fixed?: "left" | "right";
fixed?: 'left' | 'right', sortable?: boolean;
sortable?: boolean }
}
interface TableConfigData {
interface TableConfigData{ title: string;
title: string; tableTitle: FormItem[];
tableTitle: FormItem[]; drawerformData: object;
drawerformData: object; rules?: {
rules?: { [key: string]: {
[key:string]: { required: boolean;
required: boolean; message: string;
message: string; trigger: "blur";
trigger: 'blur'; }[];
}[] };
}; btnObj: {
btnObj: { isAdd: boolean;
width: string; isDelete: boolean;
isAdd: boolean; width?: string;
isDelete: boolean; };
}, apiKey?: string;
apiKey?: string; tableApi?: string;
tableApi?: string; dataKey?: string;
dataKey?: string; }
}
export { Scope, TableConfigData };
export { Scope, TableConfigData }
export enum EditType{
ADD = '0', //代表新增
EDIT = '1' //代表编辑
}
//定义弹框的标题
export enum Title {
ADD = '新增',
EDIT = '编辑'
}
//弹框属性类型
export type DialogModel = {
title:string,
visible:boolean,
height:number,
width:number
}
//返回值类型
export interface Result<T = any> {
code: number;
msg: string;
data: T;
}
//返回的状态码
export enum StatusCode {
NoAuth = 600,//无权限
Success = 200 //返回成功
}
\ No newline at end of file
// Generated by 'unplugin-auto-import' // Generated by 'unplugin-auto-import'
// We suggest you to commit this file into source control export {}
declare global { declare global {
const EffectScope: typeof import('vue')['EffectScope']
const computed: typeof import('vue')['computed'] const computed: typeof import('vue')['computed']
const createApp: typeof import('vue')['createApp'] const createApp: typeof import('vue')['createApp']
const createLogger: typeof import('vuex')['createLogger']
const createNamespacedHelpers: typeof import('vuex')['createNamespacedHelpers']
const createStore: typeof import('vuex')['createStore']
const customRef: typeof import('vue')['customRef'] const customRef: typeof import('vue')['customRef']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent'] const defineComponent: typeof import('vue')['defineComponent']
const effectScope: typeof import('vue')['effectScope'] const effectScope: typeof import('vue')['effectScope']
const EffectScope: typeof import('vue')['EffectScope']
const getCurrentInstance: typeof import('vue')['getCurrentInstance'] const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope'] const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h'] const h: typeof import('vue')['h']
const inject: typeof import('vue')['inject'] const inject: typeof import('vue')['inject']
const isProxy: typeof import('vue')['isProxy']
const isReactive: typeof import('vue')['isReactive']
const isReadonly: typeof import('vue')['isReadonly'] const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef'] const isRef: typeof import('vue')['isRef']
const mapActions: typeof import('vuex')['mapActions']
const mapGetters: typeof import('vuex')['mapGetters']
const mapMutations: typeof import('vuex')['mapMutations']
const mapState: typeof import('vuex')['mapState']
const markRaw: typeof import('vue')['markRaw'] const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick'] const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated'] const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount'] const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onDeactivated: typeof import('vue')['onDeactivated'] const onDeactivated: typeof import('vue')['onDeactivated']
...@@ -34,6 +45,7 @@ declare global { ...@@ -34,6 +45,7 @@ declare global {
const readonly: typeof import('vue')['readonly'] const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref'] const ref: typeof import('vue')['ref']
const resolveComponent: typeof import('vue')['resolveComponent'] const resolveComponent: typeof import('vue')['resolveComponent']
const resolveDirective: typeof import('vue')['resolveDirective']
const shallowReactive: typeof import('vue')['shallowReactive'] const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly'] const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef'] const shallowRef: typeof import('vue')['shallowRef']
...@@ -45,8 +57,13 @@ declare global { ...@@ -45,8 +57,13 @@ declare global {
const useAttrs: typeof import('vue')['useAttrs'] const useAttrs: typeof import('vue')['useAttrs']
const useCssModule: typeof import('vue')['useCssModule'] const useCssModule: typeof import('vue')['useCssModule']
const useCssVars: typeof import('vue')['useCssVars'] const useCssVars: typeof import('vue')['useCssVars']
const useLink: typeof import('vue-router')['useLink']
const useRoute: typeof import('vue-router')['useRoute']
const useRouter: typeof import('vue-router')['useRouter']
const useSlots: typeof import('vue')['useSlots'] const useSlots: typeof import('vue')['useSlots']
const useStore: typeof import('vuex')['useStore']
const watch: typeof import('vue')['watch'] const watch: typeof import('vue')['watch']
const watchEffect: typeof import('vue')['watchEffect'] const watchEffect: typeof import('vue')['watchEffect']
const watchPostEffect: typeof import('vue')['watchPostEffect']
const watchSyncEffect: typeof import('vue')['watchSyncEffect']
} }
export {}
// generated by unplugin-vue-components // generated by unplugin-vue-components
// We suggest you to commit this file into source control // We suggest you to commit this file into source control
// Read more: https://github.com/vuejs/vue-next/pull/3399 // Read more: https://github.com/vuejs/core/pull/3399
import '@vue/runtime-core' import '@vue/runtime-core'
export {}
declare module '@vue/runtime-core' { declare module '@vue/runtime-core' {
export interface GlobalComponents { export interface GlobalComponents {
DropdownCheck: typeof import('./../components/dropdownCheck/dropdownCheck.vue')['default']
ElAlert: typeof import('element-plus/es')['ElAlert']
ElAside: typeof import('element-plus/es')['ElAside'] ElAside: typeof import('element-plus/es')['ElAside']
ElAvatar: typeof import('element-plus/es')['ElAvatar'] ElAvatar: typeof import('element-plus/es')['ElAvatar']
ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb'] ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
...@@ -30,8 +34,8 @@ declare module '@vue/runtime-core' { ...@@ -30,8 +34,8 @@ declare module '@vue/runtime-core' {
ElMenu: typeof import('element-plus/es')['ElMenu'] ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption'] ElOption: typeof import('element-plus/es')['ElOption']
ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm']
ElPagination: typeof import('element-plus/es')['ElPagination'] ElPagination: typeof import('element-plus/es')['ElPagination']
ElPopconfirm: typeof import('element-plus/es')['ElPopconfirm']
ElRadio: typeof import('element-plus/es')['ElRadio'] ElRadio: typeof import('element-plus/es')['ElRadio']
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
ElRow: typeof import('element-plus/es')['ElRow'] ElRow: typeof import('element-plus/es')['ElRow']
...@@ -41,13 +45,19 @@ declare module '@vue/runtime-core' { ...@@ -41,13 +45,19 @@ declare module '@vue/runtime-core' {
ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTabPane: typeof import('element-plus/es')['ElTabPane'] ElTabPane: typeof import('element-plus/es')['ElTabPane']
ElTabs: typeof import('element-plus/es')['ElTabs'] ElTabs: typeof import('element-plus/es')['ElTabs']
ElTag: typeof import('element-plus/es')['ElTag']
ElTree: typeof import('element-plus/es')['ElTree'] ElTree: typeof import('element-plus/es')['ElTree']
ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect'] ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
ElUpload: typeof import('element-plus/es')['ElUpload'] ElUpload: typeof import('element-plus/es')['ElUpload']
Form: typeof import('./components/Form.vue')['default'] InputTable: typeof import('./../components/inputTable/index.vue')['default']
MyForm: typeof import('./../components/form/MyForm.vue')['default']
Pagination: typeof import('./../components/pagination/index.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
SvgIcon: typeof import('./../components/SvgIcon/index.vue')['default']
SysDialog: typeof import('./../components/SysDialog.vue')['default']
}
export interface ComponentCustomProperties {
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
} }
} }
export {}
<template> <template>
<el-dialog v-model="props.mirrorDialog" :title="title" width="30%" :before-close="handleClose"> <el-dialog
<template #title> v-model="props.mirrorDialog"
<div style="display: flex; justify-content: flex-start; align-items: center;"> :title="title"
<div>{{ title }}</div> width="30%"
<el-alert style="width: 50%; margin-left: 40px;" title="选择镜像名后才能选择版本号" type="warning" :before-close="handleClose"
:closable="false" /> >
</div> <template #title>
</template> <div
style="display: flex; justify-content: flex-start; align-items: center"
<el-form ref="formRef" :model="formData" label-width="100px" :rules="rules"> >
<el-form-item prop="name" label="镜像名"> <div>{{ title }}</div>
<el-select v-model="formData.name" placeholder="请选择镜像名" @change="handleServiceChange"> <el-alert
<el-option v-for="item in serviceList" :key="item.id" :label="item.name" :value="item.name" /> style="width: 50%; margin-left: 40px"
</el-select> title="选择镜像名后才能选择版本号"
</el-form-item> type="warning"
<el-form-item prop="contextPath" label="服务路径"> :closable="false"
<el-input v-model="formData.contextPath" placeholder="请输入服务路径" /> />
</el-form-item> </div>
<el-form-item prop="version" label="版本"> </template>
<el-select v-model="formData.id" :disabled="!versionList" placeholder="请填写对应镜像名选择版本"
@change="handleChange"> <el-form ref="formRef" :model="formData" label-width="100px" :rules="rules">
<el-option v-for="item in versionList" :key="item.id" :label="item.version" :value="item.id" /> <el-form-item prop="name" label="镜像名">
</el-select> <el-select
</el-form-item> v-model="formData.name"
</el-form> placeholder="请选择镜像名"
@change="handleServiceChange"
<template #footer> >
<el-button @click="handleClose">取消</el-button> <el-option
<el-button type="primary" @click="onConfirm">确定</el-button> v-for="item in serviceList"
</template> :key="item.id"
</el-dialog> :label="item.name"
</template> :value="item.name"
/>
<script setup lang='ts'> </el-select>
import { ref } from 'vue' </el-form-item>
import { getImageService, getImageVersion } from '@/services/api/imageService/index'; <el-form-item prop="contextPath" label="服务路径">
<el-input v-model="formData.contextPath" placeholder="请输入服务路径" />
const props = defineProps({ </el-form-item>
mirrorDialog: { <el-form-item prop="version" label="版本">
type: Boolean, <el-select
require: true v-model="formData.id"
} :disabled="!versionList"
}) placeholder="请填写对应镜像名选择版本"
@change="handleChange"
const emits = defineEmits(['update:mirrorDialog', 'mirrorData']) >
<el-option
const formData = ref({ v-for="item in versionList"
id: '', :key="item.id"
name: '', :label="item.version"
contextPath: '', :value="item.id"
version: '', />
}) </el-select>
</el-form-item>
const versionList = ref([]) as any </el-form>
const serviceList = ref([]) as any
<template #footer>
const formRef = ref() <el-button @click="handleClose">取消</el-button>
const title = ref('新增服务镜像') <el-button type="primary" @click="onConfirm">确定</el-button>
</template>
const rules = ref({ </el-dialog>
name: [{ required: true, message: '请输入镜像名', trigger: 'blur' }], </template>
// contextPath: [{ required: true, message: '请输入服务路径', trigger: 'blur' }],
}) <script setup lang="ts">
import { ref } from "vue";
const handleServiceChange = async () => { import {
if (formData.value.name) { getImageService,
let imageId; getImageVersion,
serviceList.value.map((item: any) => { } from "@/services/api/imageService/index";
if (item.name == formData.value.name)
imageId = item.id const props = defineProps({
}) mirrorDialog: {
const res: any = await getImageVersion({ imageId }) type: Boolean,
if (res.code === 200) versionList.value = res.data require: true,
} },
} });
const handleChange = (e: any) => { const emits = defineEmits(["update:mirrorDialog", "mirrorData"]);
versionList.value.map((item: any) => {
if (item.id == e) { const formData = ref({
formData.value.version = item.version id: "",
} name: "",
}) contextPath: "",
} version: "",
});
const initService = async () => {
const res: any = await getImageService({ pageSize: 100 }) const versionList = ref([]) as any;
if (res.code === 200) { const serviceList = ref([]) as any;
serviceList.value = res.data.records
} const formRef = ref();
} const title = ref("新增服务镜像");
const handleClose = () => { const rules = ref({
formRef.value?.resetFields() name: [{ required: true, message: "请输入镜像名", trigger: "blur" }],
formData.value = { // contextPath: [{ required: true, message: '请输入服务路径', trigger: 'blur' }],
id: '', });
name: '',
contextPath: '', const handleServiceChange = async () => {
version: '', if (formData.value.name) {
} let imageId;
emits('update:mirrorDialog', false) serviceList.value.map((item: any) => {
} if (item.name == formData.value.name) imageId = item.id;
});
const onConfirm = () => { const res: any = await getImageVersion({ imageId });
formRef.value?.validate((valid: Boolean, fields: any) => { if (res.code === 200) versionList.value = res.data;
if (valid) { }
emits('mirrorData', formData.value) };
} else {
console.log('error submit!', fields) const handleChange = (e: any) => {
} versionList.value.map((item: any) => {
}) if (item.id == e) {
} formData.value.version = item.version;
}
defineExpose({ });
formData, };
title,
initService, const initService = async () => {
handleClose const res: any = await getImageService({ pageSize: 100 });
}) if (res.code === 200) {
</script> serviceList.value = res.data.records;
}
<style lang = "scss" scoped> };
</style>
\ No newline at end of file const handleClose = () => {
formRef.value?.resetFields();
formData.value = {
id: "",
name: "",
contextPath: "",
version: "",
};
emits("update:mirrorDialog", false);
};
const onConfirm = () => {
formRef.value?.validate((valid: Boolean, fields: any) => {
if (valid) {
emits("mirrorData", formData.value);
} else {
console.log("error submit!", fields);
}
});
};
defineExpose({
formData,
title,
initService,
handleClose,
});
</script>
<template>
<div class="app-container"></div>
</template>
<script lang="ts">
export default {
name: 'Index'
}
</script>
<style lang="scss">
</style>
<template>
<div class="router">
<el-row :gutter="5" style="margin-bottom:5px;">
<el-col :span="10">
<el-card>
<el-tabs v-model="activeName">
<el-tab-pane label="待办事项" name="0"></el-tab-pane>
<el-tab-pane label="已办事项" name="1"></el-tab-pane>
<el-tab-pane label="待阅事项" name="2"></el-tab-pane>
</el-tabs>
<el-empty description="无事项"/>
</el-card>
</el-col>
<el-col :span="14">
<el-card>
<el-tabs v-model="activeName2">
<el-tab-pane label="我发起的流程" name="0"></el-tab-pane>
<el-tab-pane label="我已审的流程" name="1"></el-tab-pane>
</el-tabs>
<el-empty description="无流程"/>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import {ref,reactive} from 'vue'
const activeName = ref('0')
const activeName2 = ref('0')
const activeName3 = ref('0')
const missions = reactive<Array<any>>([
{
name:'任务A',
description:'您将要执行任务A,去前往中非国际***公司窃取目标数据',
client:'黄*林'
},
{
name:'任务B',
description:'去tx获取内部开发数据',
client:'马*特'
}
])
</script>
<style></style>
\ No newline at end of file
<template> <template>
<el-dialog v-model="props.imageServiceDialog" :title="title" width="30%" :before-close="handleClose"> <el-dialog
<el-form ref="formRef" :model="formData" label-width="100px" :rules="rules"> v-model="props.imageServiceDialog"
<el-form-item prop="name" label="镜像名"> :title="title"
<el-input v-model="formData.name" placeholder="请输入镜像名" /> width="30%"
</el-form-item> :before-close="handleClose"
<el-form-item prop="contextPath" label="服务路径"> >
<el-input v-model="formData.contextPath" placeholder="请输入服务路径" /> <el-form ref="formRef" :model="formData" label-width="100px" :rules="rules">
</el-form-item> <el-form-item prop="name" label="镜像名">
<el-form-item prop="describe" label="描述"> <el-input v-model="formData.name" placeholder="请输入镜像名" />
<el-input v-model="formData.describe" placeholder="请输入描述" type="textarea" /> </el-form-item>
</el-form-item> <el-form-item prop="contextPath" label="服务路径">
</el-form> <el-input v-model="formData.contextPath" placeholder="请输入服务路径" />
</el-form-item>
<template #footer> <el-form-item prop="describe" label="描述">
<el-button @click="handleClose">取消</el-button> <el-input
<el-button type="primary" @click="onConfirm">确定</el-button> v-model="formData.describe"
</template> placeholder="请输入描述"
</el-dialog> type="textarea"
</template> />
</el-form-item>
<script setup lang='ts'> </el-form>
import { ref } from 'vue'
import { ruleProps } from '../interface/index' <template #footer>
<el-button @click="handleClose">取消</el-button>
const props = defineProps({ <el-button type="primary" @click="onConfirm">确定</el-button>
imageServiceDialog: { </template>
type: Boolean, </el-dialog>
require: true </template>
}
}) <script setup lang="ts">
import { ref } from "vue";
const emits = defineEmits(['update:imageServiceDialog', 'imageServiceData']) import { ruleProps } from "../interface/index";
const formData = ref<ruleProps>({ const props = defineProps({
id: '', imageServiceDialog: {
name: '', type: Boolean,
contextPath: '', require: true,
describe: '', },
}) });
const formRef = ref() const emits = defineEmits(["update:imageServiceDialog", "imageServiceData"]);
const title = ref('新增服务镜像')
const formData = ref<ruleProps>({
const rules = ref({ id: "",
name: [{ required: true, message: '请输入镜像名', trigger: 'blur' }], name: "",
// contextPath: [{ required: true, message: '请输入服务路径', trigger: 'blur' }], contextPath: "",
}) describe: "",
});
const handleClose = () => {
formRef.value?.resetFields() const formRef = ref();
formData.value = { const title = ref("新增服务镜像");
id: '',
name: '', const rules = ref({
contextPath: '', name: [{ required: true, message: "请输入镜像名", trigger: "blur" }],
describe: '', // contextPath: [{ required: true, message: '请输入服务路径', trigger: 'blur' }],
} });
emits('update:imageServiceDialog', false)
} const handleClose = () => {
formRef.value?.resetFields();
const onConfirm = () => { formData.value = {
formRef.value?.validate((valid: Boolean, fields: any) => { id: "",
if (valid) { name: "",
emits('imageServiceData', formData.value) contextPath: "",
} else { describe: "",
console.log('error submit!', fields) };
} emits("update:imageServiceDialog", false);
}) };
}
const onConfirm = () => {
defineExpose({ formRef.value?.validate((valid: Boolean, fields: any) => {
formData, if (valid) {
title emits("imageServiceData", formData.value);
}) } else {
</script> console.log("error submit!", fields);
}
<style lang = "scss" scoped> });
</style> };
\ No newline at end of file
defineExpose({
formData,
title,
});
</script>
<template> <template>
<div class='app-container' v-loading="loading"> <div class="app-container" v-loading="loading">
<el-button type="primary" icon="plus" style="margin-bottom: 10px;" @click="addData"> <el-button
新增服务镜像</el-button> type="primary"
icon="plus"
<el-table :data="tableData" border stripe> style="margin-bottom: 10px"
<el-table-column v-for="(item, i ) in labelList" :key="i" :label="item.label" :prop="item.prop" @click="addData"
align="center" /> >
<el-table-column label="操作" align="center" width="255" fixed="right"> 新增服务镜像</el-button
<template #default="scope"> >
<el-button link type="primary" size="small" @click="imageVersion(scope.row.id)">服务镜像版本
</el-button> <el-table :data="tableData" border stripe>
<el-divider direction="vertical" /> <el-table-column
<el-button link type="primary" size="small" @click="editData(scope.row)">编辑 v-for="(item, i) in labelList"
</el-button> :key="i"
<el-divider direction="vertical" /> :label="item.label"
<el-button link type="danger" size="small" @click="deleteData(scope.row.id)">删除</el-button> :prop="item.prop"
</template> align="center"
</el-table-column> />
</el-table> <el-table-column label="操作" align="center" width="255" fixed="right">
<pagination :page-data="listQuery" :total="listQuery.total" @size-change="sizeChange" <template #default="scope">
@current-change="currentChange" /> <el-button
</div> link
<image-service-form ref="imageServiceFormRef" v-model:image-service-dialog="imageServiceDialog" type="primary"
@image-service-data="getImageServiceData" /> size="small"
<image-service-table ref="imageVersionRef" v-model:image-version-table-dialog="imageVersionTableDialog" /> @click="imageVersion(scope.row.id)"
</template> >服务镜像版本
</el-button>
<script setup lang='ts'> <el-divider direction="vertical" />
import { ref, reactive } from 'vue' <el-button
import { ruleProps } from './interface/index' link
import { type="primary"
getImageService, size="small"
addImageService, @click="editData(scope.row)"
updateImageService, >编辑
deleteImageService </el-button>
} from '@/services/api/imageService/index'; <el-divider direction="vertical" />
import { ElMessage, ElMessageBox } from 'element-plus'; <el-button
import imageServiceForm from './components/imageServiceForm.vue'; link
import imageServiceTable from './components/imageServiceTable.vue'; type="danger"
import pagination from '@/components/pagination/index.vue' size="small"
@click="deleteData(scope.row.id)"
const labelList = [ >删除</el-button
{ label: '镜像名', prop: 'name' }, >
{ label: '服务路径', prop: 'contextPath' }, </template>
{ label: '描述', prop: 'describe' }, </el-table-column>
] </el-table>
const imageServiceDialog = ref(false) <pagination
const imageVersionTableDialog = ref(false) :page-data="listQuery"
const loading = ref(true) :total="listQuery.total"
const imageServiceFormRef = ref() @size-change="sizeChange"
const imageVersionRef = ref() @current-change="currentChange"
/>
const tableData = ref<ruleProps[]>() </div>
const listQuery = reactive({ <image-service-form
pageNo: 1, ref="imageServiceFormRef"
pageSize: 10, v-model:image-service-dialog="imageServiceDialog"
total: 0 @image-service-data="getImageServiceData"
}) />
<image-service-table
// 每页新条数 ref="imageVersionRef"
const sizeChange = (val: number) => { v-model:image-version-table-dialog="imageVersionTableDialog"
listQuery.pageSize = val />
init() </template>
}
<script setup lang="ts">
// 新页数 import { ref, reactive } from "vue";
const currentChange = (val: number) => { import { ruleProps } from "./interface/index";
listQuery.pageNo = val import {
init() getImageService,
} addImageService,
updateImageService,
const imageVersion = (id: number) => { deleteImageService,
imageVersionRef.value.imageVersionId = id } from "@/services/api/imageService/index";
imageVersionRef.value.initVersion(id) import { ElMessage, ElMessageBox } from "element-plus";
imageVersionTableDialog.value = true import imageServiceForm from "./components/imageServiceForm.vue";
} import imageServiceTable from "./components/imageServiceTable.vue";
import pagination from "@/components/pagination/index.vue";
const addData = () => {
imageServiceFormRef.value.title = '新增服务镜像'; const labelList = [
imageServiceDialog.value = true; { label: "镜像名", prop: "name" },
} { label: "服务路径", prop: "contextPath" },
{ label: "描述", prop: "describe" },
const editData = (row: any) => { ];
imageServiceFormRef.value.formData = row const imageServiceDialog = ref(false);
imageServiceFormRef.value.title = '编辑服务镜像' const imageVersionTableDialog = ref(false);
imageServiceDialog.value = true const loading = ref(true);
} const imageServiceFormRef = ref();
const deleteData = (id: number) => { const imageVersionRef = ref();
ElMessageBox.confirm('确定删除吗?', '温馨提示', {
confirmButtonText: '确定', const tableData = ref<ruleProps[]>();
cancelButtonText: '取消', const listQuery = reactive({
type: 'warning', pageNo: 1,
}).then(async () => { pageSize: 10,
const res: any = await deleteImageService(id) total: 0,
if (res.code === 200) { });
ElMessage.success('删除成功')
init() // 每页新条数
} const sizeChange = (val: number) => {
}) listQuery.pageSize = val;
} init();
};
const getImageServiceData = async (formData: ruleProps) => {
if (!formData.id) { // 新页数
const res: any = await addImageService(formData) const currentChange = (val: number) => {
if (res.code === 200) { listQuery.pageNo = val;
ElMessage.success('添加成功') init();
init() };
imageServiceDialog.value = false
} const imageVersion = (id: number) => {
} else { imageVersionRef.value.imageVersionId = id;
const res: any = await updateImageService(formData) imageVersionRef.value.initVersion(id);
if (res.code === 200) { imageVersionTableDialog.value = true;
ElMessage.success('修改成功') };
imageServiceDialog.value = false
init() const addData = () => {
} imageServiceFormRef.value.title = "新增服务镜像";
} imageServiceDialog.value = true;
} };
const init = async () => { const editData = (row: any) => {
loading.value = true imageServiceFormRef.value.formData = row;
const res: any = await getImageService(listQuery) imageServiceFormRef.value.title = "编辑服务镜像";
if (res.code === 200) { imageServiceDialog.value = true;
loading.value = false };
tableData.value = res.data.records const deleteData = (id: number) => {
listQuery.total = res.data.total ElMessageBox.confirm("确定删除吗?", "温馨提示", {
} confirmButtonText: "确定",
} cancelButtonText: "取消",
type: "warning",
init() }).then(async () => {
const res: any = await deleteImageService(id);
</script> if (res.code === 200) {
ElMessage.success("删除成功");
<style lang = "scss" scoped> init();
</style> }
\ No newline at end of file });
};
const getImageServiceData = async (formData: ruleProps) => {
if (!formData.id) {
const res: any = await addImageService(formData);
if (res.code === 200) {
ElMessage.success("添加成功");
init();
imageServiceDialog.value = false;
}
} else {
const res: any = await updateImageService(formData);
if (res.code === 200) {
ElMessage.success("修改成功");
imageServiceDialog.value = false;
init();
}
}
};
const init = async () => {
loading.value = true;
const res: any = await getImageService(listQuery);
if (res.code === 200) {
loading.value = false;
tableData.value = res.data.records;
listQuery.total = res.data.total;
}
};
init();
</script>
<template>
</template>
<script setup lang="ts">
</script>
<style lang="scss">
</style>
<template> <template>
<div class="logincontainer"> <div class="logincontainer">
<el-form <el-form
class="loginForm" class="loginForm"
:model="loginModel" :model="loginModel"
ref="loginFormRef" ref="loginFormRef"
:rules="rules" :rules="rules"
:inline="false" :inline="false"
> >
<el-form-item> <el-form-item>
<div class="loginTitle">星云管理系统</div> <div class="loginTitle">集成管理系统</div>
</el-form-item> </el-form-item>
<el-form-item prop="username"> <el-form-item prop="username">
<el-input <el-input
placeholder="请输入账户" placeholder="请输入账户"
size="large" size="large"
v-model="loginModel.username" v-model="loginModel.username"
> >
<template #prefix> <template #prefix>
<el-icon class="el-input__icon"> <el-icon class="el-input__icon">
<component :is="'avatar'" /> <component :is="'avatar'" />
</el-icon> </el-icon>
</template> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="password"> <el-form-item prop="password">
<el-input <el-input
type="password" type="password"
size="large" size="large"
placeholder="请输入密码" placeholder="请输入密码"
v-model="loginModel.password" v-model="loginModel.password"
> >
<template #prefix> <template #prefix>
<el-icon class="el-input__icon"> <el-icon class="el-input__icon">
<component :is="'lock'" /> <component :is="'lock'" />
</el-icon> </el-icon>
</template> </template>
</el-input> </el-input>
</el-form-item> </el-form-item>
<el-form-item prop="code"> <el-form-item prop="code">
<el-row :gutter="24"> <div class="code">
<el-col :span="16"> <el-input
<el-input placeholder="请输入验证码"
placeholder="请输入验证码" size="large"
size="large" v-model="loginModel.code"
v-model="loginModel.code" maxlength="4"
maxlength="4" @keyup.enter.native="toLogin"
@keyup.enter.native="login" spellcheck="false"
spellcheck="false" style="width: 249px !important"
> >
<template #prefix> <template #prefix>
<el-icon class="el-input__icon"> <el-icon class="el-input__icon">
<circle-check /> <circle-check />
</el-icon> </el-icon>
</template> </template>
</el-input> </el-input>
</el-col> <img :src="imgSrc" @click="getImage" />
<el-col :span="2"></el-col> </div>
<el-col :span="4"> </el-form-item>
<img :src="imgSrc" @click="getImage" /> <el-form-item>
</el-col> <el-button
</el-row> class="mybtn"
</el-form-item> @click="login"
<el-form-item> type="primary"
<el-button size="large"
class="mybtn" :loading="loginState"
@click="login" >登录</el-button
type="primary" >
size="large" </el-form-item>
:loading="loginState" </el-form>
>登录</el-button </div>
> </template>
</el-form-item> <script setup lang="ts">
</el-form> import { watch } from "vue";
</div> import useImage from "@/services/business/login/useImage";
</template> import useBaseLogin from "@/services/business/login/useBaseLogin";
<script setup lang="ts"> import useLogin from "@/services/business/login/useLogin";
import useImage from "@/services/business/login/useImage";
import useBaseLogin from "@/services/business/login/useBaseLogin"; //基础数据
import useLogin from "@/services/business/login/useLogin"; const { loginModel, rules, loginFormRef } = useBaseLogin();
//基础数据
const { loginModel, rules, loginFormRef } = useBaseLogin(); //验证码
const { imgSrc, getImage } = useImage();
//验证码
const { imgSrc, getImage } = useImage(); //登录
const { login, loginState, num } = useLogin(loginModel);
//登录
const { login, loginState } = useLogin(loginModel); const toLogin = () => {
</script> if (!loginState.value) login();
<style scoped lang="scss"> };
.logincontainer {
height: 100%; watch(num, () => getImage(), { deep: true });
display: flex; </script>
justify-content: center; <style scoped lang="scss">
align-items: center; .logincontainer {
background-image: url("../../assets/login-background.jpg"); height: 100%;
.loginForm { display: flex;
height: 320px; justify-content: center;
width: 400px; align-items: center;
border-radius: 10px; background-image: url("../../assets/login-background.jpg");
padding: 20px 35px;
background-color: white; .loginForm {
box-shadow: 0 0 25px #cac6c6; height: 320px;
.loginTitle { width: 400px;
margin: 0 auto; border-radius: 10px;
font-size: 24px; padding: 20px 35px;
font-weight: 600; background-color: white;
display: flex; box-shadow: 0 0 25px #cac6c6;
justify-content: center;
align-items: center; .loginTitle {
} margin: 0 auto;
.mybtn { font-size: 24px;
width: 100%; font-weight: 600;
} display: flex;
.el-icon { justify-content: center;
height: 2.8em; align-items: center;
margin-left: -5px; }
}
} .mybtn {
} width: 100%;
</style> }
.el-icon {
height: 2.8em;
margin-left: -5px;
}
.code {
width: 100%;
padding: 0 6px;
display: flex;
justify-content: space-between;
margin-bottom: 6px;
}
}
}
</style>
<template> <template>
<div class="app-container"> <div class="app-container">
<Custom-table <Custom-table :tableConfigData="tableConfigData" @handle-show="handleShow">
:tableConfigData="tableConfigData" <template v-slot:drawer>
@handle-show="handleShow" <el-form-item
> v-for="(item, index) in tableConfigData.tableTitle"
<template v-slot:drawer> :key="index"
<el-form-item :label="item.label"
v-for="(item, index) in tableConfigData.tableTitle" :prop="item.prop"
:key="index" >
:label="item.label" <custom-form-item
:prop="item.prop" v-model:modValue="tableConfigData.drawerformData[item.prop]"
> :type="item.type"
<custom-form-item :inputType="item.inputValue"
v-model:modValue="tableConfigData.drawerformData[item.prop]" :options="tableData"
:type="item.type" :selectProp="item.selectProp"
:inputType="item.inputValue" >
:options="tableData" <template v-slot:radios>
:selectProp="item.selectProp" <el-radio :label="0">一级菜单</el-radio>
> <el-radio :label="1">子菜单</el-radio>
<template v-slot:radios> </template>
<el-radio :label="0">一级菜单</el-radio> </custom-form-item>
<el-radio :label="1">子菜单</el-radio> </el-form-item>
</template> </template>
</custom-form-item> </Custom-table>
</el-form-item> </div>
</template> </template>
</Custom-table>
</div> <script lang="ts">
</template> import { ref, Ref, reactive } from "vue";
import { Scope } from "@/table/type";
<script lang="ts"> import CustomFormItem from "@/table/components/edit.vue";
import { ref, Ref, reactive } from 'vue' import { menuConfigData } from "./tableConfigData/menuManage";
import { Scope } from '@/table/type' export default {
import CustomFormItem from '@/table/components/edit.vue' name: "MenuManage",
import { menuConfigData } from './tableConfigData/menuManage' components: {
export default { "custom-form-item": CustomFormItem,
name: 'MenuManage', },
components: { setup() {
'custom-form-item': CustomFormItem // 列表数据
}, const tableConfigData: any = reactive(menuConfigData);
setup() { const tableData: Ref<any[]> = ref([]);
// 列表数据 const handleShow = ref(
const tableConfigData = reactive(menuConfigData) (params: { key: string; tableData: object[]; scope?: Scope }) => {
const tableData: Ref<any[]> = ref([]) tableData.value = params.tableData;
const handleShow = ref((params: { key: string, tableData: object[], scope?: Scope }) => { const key = params.key;
tableData.value = params.tableData switch (key) {
const key = params.key case "新增":
switch (key) { tableConfigData.drawerformData = {
case '新增': id: "",
tableConfigData.drawerformData = { type: 0,
id: '', title: "",
type: 0, component: "",
title: '', path: "",
component: '', sortNo: 0,
path: '', apiKey: "",
sortNo: 0, parentId: "",
apiKey: '', icon: "",
parentId: '', is_show: true,
icon: '', };
is_show: true break;
} case "编辑": {
break if (!params.scope) return false;
case '编辑': { const row = params.scope.row;
if (!params.scope) return false tableConfigData.drawerformData = {
const row = params.scope.row id: row.id,
tableConfigData.drawerformData = { type: row.type,
id: row.id, title: row.title,
type: row.type, component: row.component,
title: row.title, path: row.path,
component: row.component, sortNo: row.sortNo,
path: row.path, apiKey: row.apiKey,
sortNo: row.sortNo, parentId: row.parentId,
apiKey: row.apiKey, icon: row.icon,
parentId: row.parentId, is_show: row.is_show,
icon: row.icon, };
is_show: row.is_show break;
} }
break }
} }
} );
}) return {
return { tableConfigData,
tableConfigData, handleShow,
handleShow, tableData,
tableData };
} },
} };
} </script>
</script>
<style lang="scss">
</style>
<template> <template>
<div class="app-container"> <div class="app-container">
<Custom-table <Custom-table :tableConfigData="tableConfigData" @handle-show="handleShow">
:tableConfigData="tableConfigData" <template v-slot:tableButton="scope">
@handle-show="handleShow" <el-button
> type="primary"
<template v-slot:tableButton="scope"> size="small"
<el-button type="primary" size="small" @click="drawerData.handleShow(scope)">授权</el-button> @click="drawerData.handleShow(scope)"
</template> >授权</el-button
<template v-slot:drawer> >
<el-form-item </template>
v-for="(item, index) in editData" <template v-slot:drawer>
:key="index" <el-form-item
:label="item.label" v-for="(item, index) in editData"
:prop="item.prop" :key="index"
> :label="item.label"
<custom-form-item :prop="item.prop"
v-model:modValue="tableConfigData.drawerformData[item.prop]" >
:type="item.type" <custom-form-item
:inputType="item.inputValue" v-model:modValue="tableConfigData.drawerformData[item.prop]"
:options="tableData" :type="item.type"
:selectProp="item.selectProp" :inputType="item.inputValue"
> :options="tableData"
</custom-form-item> :selectProp="item.selectProp"
</el-form-item> >
</template> </custom-form-item>
</Custom-table> </el-form-item>
<el-drawer </template>
v-model="drawerData.drawerShow" </Custom-table>
title="授权" <el-drawer
direction="rtl" v-model="drawerData.drawerShow"
:before-close="drawerData.handleClose" title="授权"
> direction="rtl"
<el-tree ref="tree" :data="drawerData.treeData" node-key="key" :default-expand-all="true" :check-strictly="true" show-checkbox /> :before-close="drawerData.handleClose"
<el-button type="primary" @click="drawerData.onSubmit(ruleFormRef)">保存</el-button> >
<el-button @click="drawerData.handleClose">取消</el-button> <el-tree
</el-drawer> ref="tree"
</div> :data="drawerData.treeData"
</template> node-key="key"
:default-expand-all="true"
<script lang="ts"> :check-strictly="true"
import { ref, Ref, reactive } from 'vue' show-checkbox
import { Scope } from '@/table/type' />
import { roleConfigData } from './tableConfigData/roleManage' <el-button type="primary" @click="drawerData.onSubmit()">保存</el-button>
import { getQueryRoleMenu, getQueryTreeList, saveRole } from '@/services/api/role/roleAPI' <el-button @click="drawerData.handleClose">取消</el-button>
import type { ElTree } from 'element-plus'; </el-drawer>
import { ElNotification } from 'element-plus' </div>
export default { </template>
name: 'MenuManage',
setup() { <script lang="ts">
// type: 编辑的输入类型不填表示不加入编辑功能 inputType: input类型 import { ref, Ref, reactive } from "vue";
const tableConfigData = reactive(roleConfigData) import { Scope } from "@/table/type";
import { roleConfigData } from "./tableConfigData/roleManage";
const editData: Ref<any[]> = ref([]) import {
getQueryRoleMenu,
tableConfigData.tableTitle.forEach(item => { getQueryTreeList,
if (item.type) { saveRole,
editData.value.push(item) } from "@/services/api/role/roleAPI";
} import type { ElTree } from "element-plus";
}) import { ElNotification } from "element-plus";
const tableData: Ref<any[]> = ref([]) export default {
const handleShow = ref((params: { key: string, tableData: object[], scope?: Scope }) => { name: "MenuManage",
tableData.value = params.tableData setup() {
const key = params.key // type: 编辑的输入类型不填表示不加入编辑功能 inputType: input类型
switch (key) { const tableConfigData: any = reactive(roleConfigData);
case '新增':
tableConfigData.drawerformData = { const editData: Ref<any[]> = ref([]);
id: '',
roleCode: '', tableConfigData.tableTitle.forEach((item: any) => {
roleName: '', if (item.type) {
roleDesc: '' editData.value.push(item);
} }
break });
case '编辑': { const tableData: Ref<any[]> = ref([]);
if (!params.scope) return false const handleShow = ref(
const row = params.scope.row (params: { key: string; tableData: object[]; scope?: Scope }) => {
tableConfigData.drawerformData = { tableData.value = params.tableData;
id: row.id, const key = params.key;
roleCode: row.roleCode, switch (key) {
roleName: row.roleName, case "新增":
roleDesc: row.roleDesc tableConfigData.drawerformData = {
} id: "",
break roleCode: "",
} roleName: "",
} roleDesc: "",
}) };
const tree = ref<InstanceType<typeof ElTree>>() break;
case "编辑": {
const permissionParams: { permissionIds: Array<any>, lastPermissionIds: Array<any>, roleId: string} = { if (!params.scope) return false;
permissionIds: [], const row = params.scope.row;
lastPermissionIds: [], tableConfigData.drawerformData = {
roleId: '' id: row.id,
} roleCode: row.roleCode,
// 授权抽屉数据 roleName: row.roleName,
const drawerData = reactive({ roleDesc: row.roleDesc,
drawerShow: false, };
treeData: [], break;
handleClose: () => { }
drawerData.drawerShow = false }
}, }
handleShow: (scope: Scope) => { );
drawerData.drawerShow = true const tree = ref<InstanceType<typeof ElTree>>();
permissionParams.roleId = scope.row.id
getQueryRoleMenu({ id: scope.row.id }).then((res: any) => { const permissionParams: {
if (res.code === 200) { permissionIds: Array<any>;
permissionParams.lastPermissionIds = res.data lastPermissionIds: Array<any>;
tree.value!.setCheckedKeys(res.data as Node[], true) roleId: string;
} } = {
}) permissionIds: [],
}, lastPermissionIds: [],
onSubmit: () => { roleId: "",
permissionParams.permissionIds = tree.value!.getCheckedKeys(false) };
saveRole(permissionParams).then((res: any) => { // 授权抽屉数据
if (res.code === 200) { const drawerData = reactive({
drawerData.handleClose() drawerShow: false,
ElNotification({ treeData: [],
title: '温馨提示', handleClose: () => {
message: '保存成功!', drawerData.drawerShow = false;
type: 'success' },
}) handleShow: (scope: Scope) => {
} drawerData.drawerShow = true;
}) permissionParams.roleId = scope.row.id;
} getQueryRoleMenu({ id: scope.row.id }).then((res: any) => {
}) if (res.code === 200) {
getQueryTreeList().then((res: any) => { permissionParams.lastPermissionIds = res.data;
if (res.code === 200) { tree.value!.setCheckedKeys(res.data, true);
drawerData.treeData = res.data.treeList }
} });
}) },
onSubmit: () => {
return { permissionParams.permissionIds = tree.value!.getCheckedKeys(false);
handleShow, saveRole(permissionParams).then((res: any) => {
tableConfigData, if (res.code === 200) {
tableData, drawerData.handleClose();
editData, ElNotification({
drawerData, title: "温馨提示",
tree message: "保存成功!",
} type: "success",
} });
} }
</script> });
},
<style lang="scss"> });
getQueryTreeList().then((res: any) => {
</style> if (res.code === 200) {
drawerData.treeData = res.data.treeList;
}
});
return {
handleShow,
tableConfigData,
tableData,
editData,
drawerData,
tree,
};
},
};
</script>
import { TableConfigData } from "@/table/type"; import { TableConfigData } from "@/table/type";
const roleConfigData: TableConfigData = { const roleConfigData: TableConfigData = {
title: '角色', title: "角色",
tableTitle: [ tableTitle: [
{ {
label: '角色编码', label: "角色编码",
prop: 'roleCode', prop: "roleCode",
type: 'input' type: "input",
}, },
{ {
label: '角色名称', label: "角色名称",
prop: 'roleName', prop: "roleName",
type: 'input' type: "input",
}, },
{ {
label: '角色描述', label: "角色描述",
prop: 'roleDesc', prop: "roleDesc",
type: 'input', type: "input",
inputType: 'textarea' inputType: "textarea",
}, },
{ {
label: '创建时间', label: "创建时间",
prop: 'fdate', prop: "fdate",
type: '' type: "",
} },
], ],
drawerformData: { drawerformData: {
id: '', id: "",
roleCode: '', roleCode: "",
roleName: '', roleName: "",
roleDesc: '' roleDesc: "",
}, },
rules: { rules: {
roleCode: [ roleCode: [{ required: true, message: "请输入角色编码", trigger: "blur" }],
{ required: true, message: '请输入角色编码', trigger: 'blur' } roleName: [{ required: true, message: "请输入角色名称", trigger: "blur" }],
], },
roleName: [ btnObj: {
{ required: true, message: '请输入角色名称', trigger: 'blur' } width: "200",
] isAdd: true,
}, isDelete: true,
btnObj: { },
width: '200', apiKey: "role",
isAdd: true, tableApi: "/list",
isDelete: true dataKey: "records",
}, };
apiKey: 'role',
tableApi: '/list', export { roleConfigData };
dataKey: 'records'
}
export { roleConfigData }
import { defineConfig } from "vite"; import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue"; import vue from "@vitejs/plugin-vue";
// vite 提供的操作env配置变量的方法loadEnv
import { loadEnv } from "vite"; import { loadEnv } from "vite";
// nodejs写法,获取项目目录 import { resolve } from "path";
import path from "path";
//按需要加载 //按需要加载
// import AutoImport from 'unplugin-auto-import/vite' import AutoImport from "unplugin-auto-import/vite";
// import Components from 'unplugin-vue-components/vite' import Components from "unplugin-vue-components/vite";
// import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
// import Icons from 'unplugin-icons/vite' import Icons from "unplugin-icons/vite";
// import IconsResolver from 'unplugin-icons/resolver' import IconsResolver from "unplugin-icons/resolver";
import Inspect from "vite-plugin-inspect"; import Inspect from "vite-plugin-inspect";
import { createSvgIconsPlugin } from "vite-plugin-svg-icons"; import { createSvgIconsPlugin } from "vite-plugin-svg-icons";
const pathSrc = path.resolve(__dirname, "src");
// https://vitejs.dev/config/ const pathSrc = resolve(__dirname, "src/types");
export default ({ command, mode }) => { export default ({ command, mode }) => {
const env = loadEnv(mode, process.cwd());
return defineConfig({ return defineConfig({
plugins: [ plugins: [
vue(), vue(),
createSvgIconsPlugin({ createSvgIconsPlugin({
// 指定需要缓存的图标文件夹 iconDirs: [resolve(process.cwd(), "src/assets/icons")],
iconDirs: [path.resolve(process.cwd(), "src/assets/icons")],
// 指定symbolId格式
symbolId: "icon-[dir]-[name]", symbolId: "icon-[dir]-[name]",
}), }),
// AutoImport({ AutoImport({
// // Auto import functions from Vue, e.g. ref, reactive, toRef... imports: ["vue", "vuex", "vue-router"],
// // 自动导入 Vue 相关函数,如:ref, reactive, toRef 等
// imports: ['vue'],
// // Auto import functions from Element Plus, e.g. ElMessage, ElMessageBox... (with style)
// // 自动导入 Element Plus 相关函数,如:ElMessage, ElMessageBox... (带样式)
// resolvers: [
// ElementPlusResolver(),
// // Auto import icon components
// // 自动导入图标组件
// IconsResolver({
// prefix: 'Icon',
// }),
// ],
// dts: path.resolve(pathSrc, 'auto-imports.d.ts'),
// }),
// Components({ resolvers: [
// resolvers: [ ElementPlusResolver(),
// // Auto register icon components IconsResolver({
// // 自动注册图标组件 prefix: "Icon",
// IconsResolver({ }),
// enabledCollections: ['ep'], ],
// }), dts: resolve(pathSrc, "auto-imports.d.ts"),
// // Auto register Element Plus components }),
// // 自动导入 Element Plus 组件 Components({
// ElementPlusResolver(), resolvers: [
// ], // 自动注册图标组件
IconsResolver({
// dts: path.resolve(pathSrc, 'components.d.ts'), enabledCollections: ["ep"],
// }), }),
// 自动导入 Element Plus 组件
// Icons({ ElementPlusResolver(),
// autoInstall: true, ],
// }),
dts: resolve(pathSrc, "components.d.ts"),
}),
Icons({
autoInstall: true,
}),
Inspect(), Inspect(),
], ],
// 服务器配置 // 服务器配置
...@@ -77,10 +58,6 @@ export default ({ command, mode }) => { ...@@ -77,10 +58,6 @@ export default ({ command, mode }) => {
https: false, // 默认用http方式 https: false, // 默认用http方式
open: true, // 在开发服务器启动时自动在浏览器中打开应用程序 open: true, // 在开发服务器启动时自动在浏览器中打开应用程序
proxy: { proxy: {
// 代理配置
// 字符串简写写法
// '/foo': '',
// 选项写法
"/lic": { "/lic": {
target: "http://192.168.1.252:8090", target: "http://192.168.1.252:8090",
}, },
...@@ -91,7 +68,7 @@ export default ({ command, mode }) => { ...@@ -91,7 +68,7 @@ export default ({ command, mode }) => {
}, },
resolve: { resolve: {
alias: { alias: {
"@": pathSrc, "@": "/src",
}, },
}, },
css: { css: {
...@@ -100,10 +77,13 @@ export default ({ command, mode }) => { ...@@ -100,10 +77,13 @@ export default ({ command, mode }) => {
scss: { scss: {
charset: false, //防止样式出现警告,中文 charset: false, //防止样式出现警告,中文
additionalData: '@use "@/assets/styles/global.scss";', additionalData: '@use "@/assets/styles/global.scss";',
implementation: "sass-embedded",
silenceDeprecations: ["legacy-js-api"],
}, },
}, },
}, },
build: { build: {
minify: "terser", // 默认压缩方式
// 分块打包配置 // 分块打包配置
chunkSizeWarningLimit: 1500, // 分块打包,分解块,将大块分解成更小的块 chunkSizeWarningLimit: 1500, // 分块打包,分解块,将大块分解成更小的块
rollupOptions: { rollupOptions: {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论