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

更新依赖,去除冗余代码

上级 87c17e4a
# 开发环境 # 开发环境
VITE_APP_TITLE = "星云平台测试" VITE_APP_TITLE = "Lic管理系统"
VITE_APP_PORT = 3003 VITE_APP_PORT = 3003
# 请求接口 # 请求接口
......
#生产环境 #生产环境
VITE_APP_TITLE = "星云平台" VITE_APP_TITLE = "Lic平台"
VITE_APP_PORT = 3002 VITE_APP_PORT = 3002
# 请求接口 # 请求接口
......
# starbos-ui
#### Description
星支平台前端框架,
#### Software Architecture #### Software Architecture
Software architecture description Software architecture description
#### Installation #### Installation
...@@ -25,10 +21,9 @@ Software architecture description ...@@ -25,10 +21,9 @@ Software architecture description
3. Commit your code 3. Commit your code
4. Create Pull Request 4. Create Pull Request
#### Gitee Feature #### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md 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) 2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) 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) 4. The most valuable open source project [GVP](https://gitee.com/gvp)
......
# 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 yarn lint
``` ```
### 自定义配置 ### 自定义配置
See [Configuration Reference](https://cli.vuejs.org/config/). 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"绑定的形式
上线会报错
修改为如下方式
:model-value="visible"
-->
<template> <template>
<el-dialog <el-dialog
:title='title' :title="title"
:model-value="visible" :model-value="visible"
:before-close="onClose" :before-close="onClose"
append-to-body append-to-body
:width="width + 'px'" :width="width + 'px'"
> >
<div class="container" :style="{height:height + 'px'}"> <div class="container" :style="{ height: height + 'px' }">
<slot name="content"></slot> <slot name="content"></slot>
</div> </div>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button type='danger' @click="onClose">取消</el-button> <el-button type="danger" @click="onClose">取消</el-button>
<el-button type="primary" @click="onConfirm">确定</el-button> <el-button type="primary" @click="onConfirm">确定</el-button>
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
<script setup lang='ts'> <script setup lang="ts">
import { ref, reactive } from 'vue' defineProps({
const props = defineProps({ title: {
title: {//弹框标题 //弹框标题
type: String, type: String,
default: '标题' default: "标题",
}, },
visible: { //控制弹框的展示和影藏 visible: {
//控制弹框的展示和影藏
type: Boolean, type: Boolean,
default: false default: false,
}, },
width: { width: {
type: Number, type: Number,
default: 600 default: 600,
}, },
height: { height: {
type: Number, type: Number,
default: 250 default: 250,
} },
}) });
const emit = defineEmits(['onClose','onConfirm']) const emit = defineEmits(["onClose", "onConfirm"]);
//定义弹框的关闭 //定义弹框的关闭
const onClose = () =>{ const onClose = () => {
emit('onClose') emit("onClose");
} };
//定义弹框的确定 //定义弹框的确定
const onConfirm = () =>{ const onConfirm = () => {
emit('onConfirm') emit("onConfirm");
} };
</script> </script>
<style lang="scss" scope> <style lang="scss" scope>
.container { .container {
......
<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]"
:small="pageData.small"
:disabled="pageData.disabled"
:background="pageData.background"
layout="->, total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
hide-on-single-page
@current-change="handleCurrentChange"
/>
</div> </div>
</template> </template>
<script setup lang='ts'> <script setup lang="ts">
let props = defineProps({ let props = defineProps({
pageData: { pageData: {
type: Object, type: Object,
default: { default: {
pageNo: { pageNo: {
type: Number, type: Number,
default: 1 default: 1,
}, },
pageSize: { pageSize: {
type: Number, type: Number,
default: 10 default: 10,
}, },
small: { small: {
type: Boolean, type: Boolean,
default: false default: false,
}, },
disabled: { disabled: {
type: Boolean, type: Boolean,
default: false default: false,
}, },
background: { background: {
type: String || Boolean, type: String || Boolean,
default: '' || false default: "" || false,
} },
} },
}, },
total: { total: {
type: Number, type: Number,
default: 0 default: 0,
} },
}) });
let emits = defineEmits(['sizeChange', 'currentChange']) let emits = defineEmits(["sizeChange", "currentChange"]);
// 新条数 // 新条数
const handleSizeChange = (val: number) => { const handleSizeChange = (val: number) => {
emits('sizeChange', val) emits("sizeChange", val);
} };
// // 新页数 // // 新页数
const handleCurrentChange = (val: number) => { const handleCurrentChange = (val: number) => {
emits('currentChange', val) emits("currentChange", val);
} };
</script> </script>
<style lang = "scss" scoped>
</style>
\ No newline at end of file
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
...@@ -3,9 +3,5 @@ ...@@ -3,9 +3,5 @@
</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>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
export default { export default {
setup () { setup() {
return {} return {};
} },
} };
</script> </script>
<style lang="scss" scoped>
</style>
\ No newline at end of file
...@@ -26,6 +26,3 @@ getBredcurm(); ...@@ -26,6 +26,3 @@ getBredcurm();
//路由发生变化,重新获取面包屑导航数据 //路由发生变化,重新获取面包屑导航数据
watch(()=>route.path,()=>getBredcurm()); watch(()=>route.path,()=>getBredcurm());
</script> </script>
<style scoped lang='scss'>
</style>
\ No newline at end of file
...@@ -11,49 +11,29 @@ ...@@ -11,49 +11,29 @@
</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 () => {
let confirm = await global.$lqconfirm("确定退出登录吗?");
if (confirm) {
//跳到登录
window.location.href = "/#/login"; window.location.href = "/#/login";
//清空session
cleanSession(); cleanSession();
// let confirm = await global.$myconfirm('确定退出登录吗?') }
// if (confirm) { };
// let parm = {
// token: getToken()
// }
// let res = await loginOutApi(parm)
// if (res && res.code == 200) {
// //跳到登录
// window.location.href = "/login";
// //清空session
// cleanSession();
// }
// }
}
//还原数据
// 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 () => { const userInfo = async () => {
router.push({path:'/user'}) router.push({ path: "/user" });
} };
</script> </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"
background-color="#304156"
router
>
<MenuItem :menuList="menuList"> </MenuItem>
</el-menu> </el-menu>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, computed } from 'vue' import { useStore } from "@/store/index";
import { useRoute } from 'vue-router' import MenuItem from "./MenuItem.vue";
import { useStore } from '@/store/index' import MenuLogo from "@/layout/menu/MenuLogo.vue";
import MenuItem from './MenuItem.vue' const store = useStore();
import MenuLogo from '@/layout/menu/MenuLogo.vue'
// setup语法糖中 定义的数据和方法,直接可以在模板中使用,无需要 return
const store = useStore()
// store.commit('menu/setCollapse')
// 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"];
}) });
// let menuList = reactive([
// {
// path: '/dashboard',
// component: "Layout",
// meta: {
// title: "首页",
// icon: "HomeFilled",
// roles: ["sys:manage"]
// },
// children: []
// },
// {
// path: "/system",
// component: "Layout",
// alwaysShow: true,
// name: "system",
// meta: {
// title: "系统管理",
// icon: "Menu",
// roles: ["sys:manage"],
// parentId: 0,
// },
// children: [
// {
// path: "/department",
// component: "/system/department/department",
// alwaysShow: false,
// name: "department",
// meta: {
// title: "机构管理",
// icon: "Platform",
// roles: ["sys:dept"],
// parentId: 17,
// },
// },
// {
// path: "/userList",
// component: "/system/User/UserList",
// alwaysShow: false,
// name: "userList",
// meta: {
// title: "用户管理",
// icon: "el-icon-s-custom",
// roles: ["sys:user"],
// parentId: 17,
// },
// },
// {
// path: "/roleList",
// component: "/system/Role/RoleList",
// alwaysShow: false,
// name: "roleList",
// meta: {
// title: "角色管理",
// icon: "el-icon-s-tools",
// roles: ["sys:role"],
// 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(() => { const isCollapse = computed(() => {
// return store.getters['getCollapse'] return store.getters["menu/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> </script>
<style scoped> <style scoped>
@keyframes logoAnimation { @keyframes logoAnimation {
......
<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;
......
...@@ -12,10 +12,3 @@ export function toLogin( ...@@ -12,10 +12,3 @@ export function toLogin(
data: qs.stringify(data), data: qs.stringify(data),
}); });
} }
// export function getCode(){
// return request({
// url: COMMON_PATH + "/auth/getCaptcha",
// method: 'get',
// })
// }
...@@ -7,31 +7,37 @@ export default function useBaseLogin() { ...@@ -7,31 +7,37 @@ export default function useBaseLogin() {
//表单绑定的数据 //表单绑定的数据
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, required: true,
trigger: 'change', trigger: "change",
message: '请填写登录账户' message: "请填写登录账户",
}], },
password: [{ ],
password: [
{
required: true, required: true,
trigger: 'change', trigger: "change",
message: '请填写登录密码' message: "请填写登录密码",
}], },
code: [{ ],
code: [
{
required: true, required: true,
trigger: 'change', trigger: "change",
message: '请填写验证码' message: "请填写验证码",
}] },
}) ],
});
return { return {
loginModel, loginModel,
rules, rules,
loginFormRef 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 //定义图片src
const imgSrc = ref('../../../../checkcode.png'); const imgSrc = ref("../../../../checkcode.png");
// 获取图片 // 获取图片
//btoa 创建一个base64编码的字符串 //btoa 创建一个base64编码的字符串
const getImage = debounce(async () => { const getImage = debounce(async () => {
await getImagApi().then(res => { await getImagApi()
.then((res) => {
return res.data.data as string; return res.data.data as string;
}).then(data => {
imgSrc.value = data;
}).catch((err) => {
ElNotification({
title:'获取验证码失败',
message:err.message,
type:'error',
}) })
.then((data) => {
imgSrc.value = data;
}) })
},1000) .catch((err) => {
ElNotification({
title: "获取验证码失败",
message: err.message,
type: "error",
});
});
}, 1000);
onMounted(() => { onMounted(() => {
getImage() getImage();
}) });
return { return {
imgSrc, imgSrc,
getImage getImage,
} };
} }
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) { export default function useLogin(loginModel: LoginParm) {
const { proxy } = getCurrentInstance() as any; const { proxy } = getCurrentInstance() as any;
const num = ref(0);
//登录提交 //登录提交
const login = async () => { const login = async () => {
//表单验证 //表单验证
proxy.$refs.loginFormRef.validate(async (valid: boolean) => { proxy.$refs.loginFormRef.validate(async (valid: boolean) => {
if (valid) { if (valid) {
loginState.value = true loginState.value = true;
store.dispatch('user/login', loginModel).then((res: any) => { store
loginState.value = false .dispatch("user/login", loginModel)
.then((res: any) => {
if (res.code == 200) { if (res.code == 200) {
ElNotification({ ElNotification({
title:'登录成功', title: "登录成功",
message:'欢迎回来', message: "欢迎回来",
type:'success', type: "success",
}) });
//跳转到首页 //跳转到首页
setTimeout(()=> { setTimeout(() => {
router.push({ path: '/' }) router.push({ path: "/" });
},1500) loginState.value = false;
}, 1000);
} else { } else {
loginState.value = false;
num.value++;
ElNotification({ ElNotification({
title:'登陆失败', title: "登录失败",
message:res.msg, message: res.msg,
type:'error', type: "error",
}) });
}
}).catch((err) => {
loginState.value = false
ElNotification({
title:'登录失败',
message:err.message,
type:'error',
})
})
} }
}) })
.finally(() => {
loginState.value = false;
});
} }
});
};
//登录状态 //登录状态
const loginState = ref(false) const loginState = ref(false);
return { return {
login, login,
loginState num,
} 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 = { export type RootState = {
tabs: TabsState, tabs: TabsState;
menu: MenuState, menu: MenuState;
user: UserState, user: UserState;
table: TableState, table: TableState;
socket: SocketState };
}
//导入所有的模块 //导入所有的模块
export const modules = { export const modules = {
tabs: tabs, tabs: tabs,
menu: menu, menu: menu,
user: user, user: user,
table: table, table: table,
socket: socket };
}
export const key: InjectionKey<Store<RootState>> = Symbol() export const key: InjectionKey<Store<RootState>> = Symbol();
export const store = createStore<RootState>({ export const store = createStore<RootState>({
modules modules,
}) as StarbosStore }) as StarbosStore;
// 定义自己的 `useStore` 组合式函数 // 定义自己的 `useStore` 组合式函数
export function useStore() { export function useStore() {
return baseUseStore(key) as StarbosStore return baseUseStore(key) as StarbosStore;
} }
...@@ -2,32 +2,32 @@ import { getMenuListApi } from "@/services/api/menu/menuAPI"; ...@@ -2,32 +2,32 @@ 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) {
...@@ -38,18 +38,19 @@ export const mutations = { ...@@ -38,18 +38,19 @@ export const mutations = {
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()
.then((res) => {
/* res.data.forEach(item => { /* res.data.forEach(item => {
if (item.meta.title === '部门') { if (item.meta.title === '部门') {
item.children = [] item.children = []
...@@ -60,35 +61,36 @@ export const actions = { ...@@ -60,35 +61,36 @@ export const actions = {
//动态生成路由 //动态生成路由
accessedRoutes = filterAsyncRoutes(res.data, router); accessedRoutes = filterAsyncRoutes(res.data, router);
//设置到menuList //设置到menuList
commit('setMenuList', accessedRoutes) commit("setMenuList", accessedRoutes);
} }
//返回 //返回
resolve(accessedRoutes); resolve(accessedRoutes);
}).catch(error => {
reject(error)
})
}) })
} .catch((error) => {
} reject(error);
});
});
},
};
export function filterAsyncRoutes(routes: RouteRecordRaw[], router: any) { export function filterAsyncRoutes(routes: RouteRecordRaw[], router: any) {
const res: Array<RouteRecordRaw> = []; const res: Array<RouteRecordRaw> = [];
routes.forEach((route: any) => { routes.forEach((route: any) => {
const tmp = { ...route } const tmp = { ...route };
const component = tmp.component; const component = tmp.component;
if (route.component) { if (route.component) {
if (component == 'Layout') { if (component == "Layout") {
tmp.component = Layout; tmp.component = Layout;
} else { } else {
tmp.component = modules[`../../views${component}.vue`] tmp.component = modules[`../../views${component}.vue`];
} }
} }
if (tmp.children) { if (tmp.children) {
//递归 //递归
tmp.children = filterAsyncRoutes(tmp.children, router) tmp.children = filterAsyncRoutes(tmp.children, router);
} }
router.addRoute(tmp) router.addRoute(tmp);
res.push(tmp) res.push(tmp);
}) });
return res; return res;
} }
//定义getters //定义getters
...@@ -101,13 +103,13 @@ export const getters = { ...@@ -101,13 +103,13 @@ export const getters = {
return state.collapse; return state.collapse;
}, },
getMenuList: (state: MenuState) => { getMenuList: (state: MenuState) => {
return state.menuList return state.menuList;
} },
} };
export default { export default {
namespaced: true, namespaced: true,
state, state,
mutations, mutations,
actions, actions,
getters getters,
} };
\ No newline at end of file
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() { function init() {
getTableList(completeApi ?? apiKey).then((res: any) => { getTableList(completeApi ?? apiKey).then((res: any) => {
if (res.code === 200) { if (res.code === 200) {
console.log(res)
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,
} };
} }
...@@ -4,13 +4,26 @@ ...@@ -4,13 +4,26 @@
<el-form :model="formData"> <el-form :model="formData">
<el-form-item label="搜索"> <el-form-item label="搜索">
<el-row :gutter="10"> <el-row :gutter="10">
<el-col :span="18"><el-input v-model="formData.keyword" :placeholder="`请输入${tableConfigData.title}`" @change="searchList" /></el-col> <el-col :span="18"
<el-col :span="6"><el-button type="primary" @click="searchList">搜索</el-button></el-col> ><el-input
v-model="formData.keyword"
:placeholder="`请输入${tableConfigData.title}`"
@change="searchList"
/></el-col>
<el-col :span="6"
><el-button type="primary" @click="searchList"
>搜索</el-button
></el-col
>
</el-row> </el-row>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="button-content margin-bottom-10"> <div class="button-content margin-bottom-10">
<el-button v-if="tableConfigData.btnObj.isAdd" type="primary" @click="drawerData.handleShow('新增')"> <el-button
v-if="tableConfigData.btnObj.isAdd"
type="primary"
@click="drawerData.handleShow('新增')"
>
<el-icon><Plus /></el-icon> <el-icon><Plus /></el-icon>
新增 新增
</el-button> </el-button>
...@@ -31,7 +44,8 @@ ...@@ -31,7 +44,8 @@
:prop="item.prop" :prop="item.prop"
:label="item.label" :label="item.label"
:sortable="item.sortable" :sortable="item.sortable"
:width="item.width ?? '180'" /> :width="item.width"
/>
<el-table-column <el-table-column
align="center" align="center"
label="操作" label="操作"
...@@ -41,8 +55,20 @@ ...@@ -41,8 +55,20 @@
<template #default="scope"> <template #default="scope">
<!-- 自定义按钮插槽 --> <!-- 自定义按钮插槽 -->
<slot name="tableButton" v-bind="scope" /> <slot name="tableButton" v-bind="scope" />
<el-button v-if="tableConfigData.btnObj.isAdd" type="primary" size="small" @click="drawerData.handleShow('编辑', scope)">编辑</el-button> <el-button
<el-button v-if="tableConfigData.btnObj.isDelete" type="danger" size="small" @click="drawerData.delete(scope)">删除</el-button> v-if="tableConfigData.btnObj.isAdd"
type="primary"
size="small"
@click="drawerData.handleShow('编辑', scope)"
>编辑</el-button
>
<el-button
v-if="tableConfigData.btnObj.isDelete"
type="danger"
size="small"
@click="drawerData.delete(scope)"
>删除</el-button
>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
...@@ -54,10 +80,17 @@ ...@@ -54,10 +80,17 @@
:before-close="drawerData.handleClose" :before-close="drawerData.handleClose"
> >
<el-card v-if="drawerData.drawerShow"> <el-card v-if="drawerData.drawerShow">
<el-form ref="ruleFormRef" :model="tableConfigData.drawerformData" :rules="tableConfigData.rules" label-width="80px"> <el-form
ref="ruleFormRef"
:model="tableConfigData.drawerformData"
:rules="tableConfigData.rules"
label-width="80px"
>
<slot name="drawer" /> <slot name="drawer" />
<el-form-item> <el-form-item>
<el-button type="primary" @click="drawerData.onSubmit(ruleFormRef)">保存</el-button> <el-button type="primary" @click="drawerData.onSubmit(ruleFormRef)"
>保存</el-button
>
<el-button @click="drawerData.handleClose">取消</el-button> <el-button @click="drawerData.handleClose">取消</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
...@@ -66,95 +99,108 @@ ...@@ -66,95 +99,108 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { searchLogic } from './business/search' import { searchLogic } from "./business/search";
import { tableLogic } from './business/table' import { tableLogic } from "./business/table";
import { ref, reactive, PropType } from 'vue' import { ref, reactive, PropType } from "vue";
import { Scope, TableConfigData } from './type' import { Scope, TableConfigData } from "./type";
import { FormInstance, ElNotification, ElMessage, ElMessageBox } from 'element-plus' import {
import { tableDelete, tableSave } from '@/services/api/customTable' FormInstance,
ElNotification,
ElMessage,
ElMessageBox,
} from "element-plus";
import { tableDelete, tableSave } from "@/services/api/customTable";
export default { export default {
name: 'CustomTable', name: "CustomTable",
emits: ['handleShow'], emits: ["handleShow"],
props: { props: {
tableConfigData: { tableConfigData: {
type: Object as PropType<TableConfigData>, type: Object as PropType<TableConfigData>,
required: true required: true,
} },
}, },
setup(props, context) { setup(props, context) {
const tableConfigData: TableConfigData = props.tableConfigData const tableConfigData: TableConfigData = props.tableConfigData;
// 搜索框 // 搜索框
const searchData = searchLogic((value: string) => { const searchData = searchLogic((value: string) => {
console.log(value) console.log(value);
}) });
const data = tableLogic(props) const data = tableLogic(props);
const ruleFormRef = ref<FormInstance>() const ruleFormRef = ref<FormInstance>();
// 抽屉公共数据与方法 用于新增、编辑等修改 // 抽屉公共数据与方法 用于新增、编辑等修改
const drawerData = reactive({ const drawerData = reactive({
drawerShow: false, drawerShow: false,
clickKey: '新增', clickKey: "新增",
// 关闭弹窗 // 关闭弹窗
handleClose() { handleClose() {
drawerData.drawerShow = false drawerData.drawerShow = false;
}, },
// 打开编辑或新增 // 打开编辑或新增
handleShow(key: string, scope: Scope) { handleShow(key: string, scope?: Scope) {
// 将列表数据派发至父组件 // 将列表数据派发至父组件
context.emit('handleShow', { key: key, tableData: data.tableData.value, scope }) context.emit("handleShow", {
drawerData.drawerShow = true key: key,
drawerData.clickKey = key tableData: data.tableData.value,
scope,
});
drawerData.drawerShow = true;
drawerData.clickKey = key;
}, },
// 删除表格某一行 // 删除表格某一行
delete(scope: Scope) { delete(scope: Scope) {
ElMessageBox.confirm('确定删除吗?', '温馨提示', { ElMessageBox.confirm("确定删除吗?", "温馨提示", {
confirmButtonText: '确定', confirmButtonText: "确定",
cancelButtonText: '取消', cancelButtonText: "取消",
type: 'warning', type: "warning",
}).then(() => { }).then(() => {
tableDelete(tableConfigData.apiKey + '/delete', { id: scope.row.id }).then((res: any) => { tableDelete(tableConfigData.apiKey + "/delete", {
id: scope.row.id,
}).then((res: any) => {
if (res.code === 200) { if (res.code === 200) {
ElMessage({ ElMessage({
type: 'success', type: "success",
message: '删除成功', message: "删除成功",
}) });
// 重新加载表格数据 // 重新加载表格数据
data.init() data.init();
} }
}) });
}) });
}, },
// 接口新增和保持 // 接口新增和保持
async onSubmit(formEl: FormInstance | undefined) { async onSubmit(formEl: FormInstance | undefined) {
// 保存 // 保存
await formEl?.validate(valid => { await formEl?.validate((valid) => {
if (valid) { if (valid) {
const apiName = drawerData.clickKey === '新增' ? '/add' : '/edit' const apiName = drawerData.clickKey === "新增" ? "/add" : "/edit";
tableSave(tableConfigData.apiKey + apiName, apiName === '/add' ? 'post' : 'put', tableConfigData.drawerformData).then((res: any) => { tableSave(
tableConfigData.apiKey + apiName,
apiName === "/add" ? "post" : "put",
tableConfigData.drawerformData
).then((res: any) => {
if (res.code === 200) { if (res.code === 200) {
ElNotification({ ElNotification({
title: '温馨提示', title: "温馨提示",
message: '保存成功!', message: "保存成功!",
type: 'success' type: "success",
}) });
drawerData.handleClose() drawerData.handleClose();
data.init() data.init();
}
})
} }
}) });
} }
}) });
},
});
return { return {
...searchData, ...searchData,
tableData: data.tableData, tableData: data.tableData,
drawerData, drawerData,
ruleFormRef ruleFormRef,
} };
} },
} };
</script> </script>
<style> <style></style>
</style>
\ No newline at end of file
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: {
width: string;
isAdd: boolean; isAdd: boolean;
isDelete: boolean; isDelete: boolean;
}, width?: string;
};
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
v-model="props.mirrorDialog"
:title="title"
width="30%"
:before-close="handleClose"
>
<template #title> <template #title>
<div style="display: flex; justify-content: flex-start; align-items: center;"> <div
style="display: flex; justify-content: flex-start; align-items: center"
>
<div>{{ title }}</div> <div>{{ title }}</div>
<el-alert style="width: 50%; margin-left: 40px;" title="选择镜像名后才能选择版本号" type="warning" <el-alert
:closable="false" /> style="width: 50%; margin-left: 40px"
title="选择镜像名后才能选择版本号"
type="warning"
:closable="false"
/>
</div> </div>
</template> </template>
<el-form ref="formRef" :model="formData" label-width="100px" :rules="rules"> <el-form ref="formRef" :model="formData" label-width="100px" :rules="rules">
<el-form-item prop="name" label="镜像名"> <el-form-item prop="name" label="镜像名">
<el-select v-model="formData.name" placeholder="请选择镜像名" @change="handleServiceChange"> <el-select
<el-option v-for="item in serviceList" :key="item.id" :label="item.name" :value="item.name" /> v-model="formData.name"
placeholder="请选择镜像名"
@change="handleServiceChange"
>
<el-option
v-for="item in serviceList"
:key="item.id"
:label="item.name"
:value="item.name"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item prop="contextPath" label="服务路径"> <el-form-item prop="contextPath" label="服务路径">
<el-input v-model="formData.contextPath" placeholder="请输入服务路径" /> <el-input v-model="formData.contextPath" placeholder="请输入服务路径" />
</el-form-item> </el-form-item>
<el-form-item prop="version" label="版本"> <el-form-item prop="version" label="版本">
<el-select v-model="formData.id" :disabled="!versionList" placeholder="请填写对应镜像名选择版本" <el-select
@change="handleChange"> v-model="formData.id"
<el-option v-for="item in versionList" :key="item.id" :label="item.version" :value="item.id" /> :disabled="!versionList"
placeholder="请填写对应镜像名选择版本"
@change="handleChange"
>
<el-option
v-for="item in versionList"
:key="item.id"
:label="item.version"
:value="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-form> </el-form>
...@@ -32,92 +61,91 @@ ...@@ -32,92 +61,91 @@
</el-dialog> </el-dialog>
</template> </template>
<script setup lang='ts'> <script setup lang="ts">
import { ref } from 'vue' import { ref } from "vue";
import { getImageService, getImageVersion } from '@/services/api/imageService/index'; import {
getImageService,
getImageVersion,
} from "@/services/api/imageService/index";
const props = defineProps({ const props = defineProps({
mirrorDialog: { mirrorDialog: {
type: Boolean, type: Boolean,
require: true require: true,
} },
}) });
const emits = defineEmits(['update:mirrorDialog', 'mirrorData']) const emits = defineEmits(["update:mirrorDialog", "mirrorData"]);
const formData = ref({ const formData = ref({
id: '', id: "",
name: '', name: "",
contextPath: '', contextPath: "",
version: '', version: "",
}) });
const versionList = ref([]) as any const versionList = ref([]) as any;
const serviceList = ref([]) as any const serviceList = ref([]) as any;
const formRef = ref() const formRef = ref();
const title = ref('新增服务镜像') const title = ref("新增服务镜像");
const rules = ref({ const rules = ref({
name: [{ required: true, message: '请输入镜像名', trigger: 'blur' }], name: [{ required: true, message: "请输入镜像名", trigger: "blur" }],
// contextPath: [{ required: true, message: '请输入服务路径', trigger: 'blur' }], // contextPath: [{ required: true, message: '请输入服务路径', trigger: 'blur' }],
}) });
const handleServiceChange = async () => { const handleServiceChange = async () => {
if (formData.value.name) { if (formData.value.name) {
let imageId; let imageId;
serviceList.value.map((item: any) => { serviceList.value.map((item: any) => {
if (item.name == formData.value.name) if (item.name == formData.value.name) imageId = item.id;
imageId = item.id });
}) const res: any = await getImageVersion({ imageId });
const res: any = await getImageVersion({ imageId }) if (res.code === 200) versionList.value = res.data;
if (res.code === 200) versionList.value = res.data
} }
} };
const handleChange = (e: any) => { const handleChange = (e: any) => {
versionList.value.map((item: any) => { versionList.value.map((item: any) => {
if (item.id == e) { if (item.id == e) {
formData.value.version = item.version formData.value.version = item.version;
} }
}) });
} };
const initService = async () => { const initService = async () => {
const res: any = await getImageService({ pageSize: 100 }) const res: any = await getImageService({ pageSize: 100 });
if (res.code === 200) { if (res.code === 200) {
serviceList.value = res.data.records serviceList.value = res.data.records;
} }
} };
const handleClose = () => { const handleClose = () => {
formRef.value?.resetFields() formRef.value?.resetFields();
formData.value = { formData.value = {
id: '', id: "",
name: '', name: "",
contextPath: '', contextPath: "",
version: '', version: "",
} };
emits('update:mirrorDialog', false) emits("update:mirrorDialog", false);
} };
const onConfirm = () => { const onConfirm = () => {
formRef.value?.validate((valid: Boolean, fields: any) => { formRef.value?.validate((valid: Boolean, fields: any) => {
if (valid) { if (valid) {
emits('mirrorData', formData.value) emits("mirrorData", formData.value);
} else { } else {
console.log('error submit!', fields) console.log("error submit!", fields);
} }
}) });
} };
defineExpose({ defineExpose({
formData, formData,
title, title,
initService, initService,
handleClose handleClose,
}) });
</script> </script>
<style lang = "scss" scoped>
</style>
\ No newline at end of file
<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
v-model="props.imageServiceDialog"
:title="title"
width="30%"
:before-close="handleClose"
>
<el-form ref="formRef" :model="formData" label-width="100px" :rules="rules"> <el-form ref="formRef" :model="formData" label-width="100px" :rules="rules">
<el-form-item prop="name" label="镜像名"> <el-form-item prop="name" label="镜像名">
<el-input v-model="formData.name" placeholder="请输入镜像名" /> <el-input v-model="formData.name" placeholder="请输入镜像名" />
...@@ -8,7 +13,11 @@ ...@@ -8,7 +13,11 @@
<el-input v-model="formData.contextPath" placeholder="请输入服务路径" /> <el-input v-model="formData.contextPath" placeholder="请输入服务路径" />
</el-form-item> </el-form-item>
<el-form-item prop="describe" label="描述"> <el-form-item prop="describe" label="描述">
<el-input v-model="formData.describe" placeholder="请输入描述" type="textarea" /> <el-input
v-model="formData.describe"
placeholder="请输入描述"
type="textarea"
/>
</el-form-item> </el-form-item>
</el-form> </el-form>
...@@ -19,60 +28,57 @@ ...@@ -19,60 +28,57 @@
</el-dialog> </el-dialog>
</template> </template>
<script setup lang='ts'> <script setup lang="ts">
import { ref } from 'vue' import { ref } from "vue";
import { ruleProps } from '../interface/index' import { ruleProps } from "../interface/index";
const props = defineProps({ const props = defineProps({
imageServiceDialog: { imageServiceDialog: {
type: Boolean, type: Boolean,
require: true require: true,
} },
}) });
const emits = defineEmits(['update:imageServiceDialog', 'imageServiceData']) const emits = defineEmits(["update:imageServiceDialog", "imageServiceData"]);
const formData = ref<ruleProps>({ const formData = ref<ruleProps>({
id: '', id: "",
name: '', name: "",
contextPath: '', contextPath: "",
describe: '', describe: "",
}) });
const formRef = ref() const formRef = ref();
const title = ref('新增服务镜像') const title = ref("新增服务镜像");
const rules = ref({ const rules = ref({
name: [{ required: true, message: '请输入镜像名', trigger: 'blur' }], name: [{ required: true, message: "请输入镜像名", trigger: "blur" }],
// contextPath: [{ required: true, message: '请输入服务路径', trigger: 'blur' }], // contextPath: [{ required: true, message: '请输入服务路径', trigger: 'blur' }],
}) });
const handleClose = () => { const handleClose = () => {
formRef.value?.resetFields() formRef.value?.resetFields();
formData.value = { formData.value = {
id: '', id: "",
name: '', name: "",
contextPath: '', contextPath: "",
describe: '', describe: "",
} };
emits('update:imageServiceDialog', false) emits("update:imageServiceDialog", false);
} };
const onConfirm = () => { const onConfirm = () => {
formRef.value?.validate((valid: Boolean, fields: any) => { formRef.value?.validate((valid: Boolean, fields: any) => {
if (valid) { if (valid) {
emits('imageServiceData', formData.value) emits("imageServiceData", formData.value);
} else { } else {
console.log('error submit!', fields) console.log("error submit!", fields);
} }
}) });
} };
defineExpose({ defineExpose({
formData, formData,
title title,
}) });
</script> </script>
<style lang = "scss" scoped>
</style>
\ No newline at end of file
<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"
style="margin-bottom: 10px"
@click="addData"
>
新增服务镜像</el-button
>
<el-table :data="tableData" border stripe> <el-table :data="tableData" border stripe>
<el-table-column v-for="(item, i ) in labelList" :key="i" :label="item.label" :prop="item.prop" <el-table-column
align="center" /> v-for="(item, i) in labelList"
:key="i"
:label="item.label"
:prop="item.prop"
align="center"
/>
<el-table-column label="操作" align="center" width="255" fixed="right"> <el-table-column label="操作" align="center" width="255" fixed="right">
<template #default="scope"> <template #default="scope">
<el-button link type="primary" size="small" @click="imageVersion(scope.row.id)">服务镜像版本 <el-button
link
type="primary"
size="small"
@click="imageVersion(scope.row.id)"
>服务镜像版本
</el-button> </el-button>
<el-divider direction="vertical" /> <el-divider direction="vertical" />
<el-button link type="primary" size="small" @click="editData(scope.row)">编辑 <el-button
link
type="primary"
size="small"
@click="editData(scope.row)"
>编辑
</el-button> </el-button>
<el-divider direction="vertical" /> <el-divider direction="vertical" />
<el-button link type="danger" size="small" @click="deleteData(scope.row.id)">删除</el-button> <el-button
link
type="danger"
size="small"
@click="deleteData(scope.row.id)"
>删除</el-button
>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination :page-data="listQuery" :total="listQuery.total" @size-change="sizeChange" <pagination
@current-change="currentChange" /> :page-data="listQuery"
:total="listQuery.total"
@size-change="sizeChange"
@current-change="currentChange"
/>
</div> </div>
<image-service-form ref="imageServiceFormRef" v-model:image-service-dialog="imageServiceDialog" <image-service-form
@image-service-data="getImageServiceData" /> ref="imageServiceFormRef"
<image-service-table ref="imageVersionRef" v-model:image-version-table-dialog="imageVersionTableDialog" /> v-model:image-service-dialog="imageServiceDialog"
@image-service-data="getImageServiceData"
/>
<image-service-table
ref="imageVersionRef"
v-model:image-version-table-dialog="imageVersionTableDialog"
/>
</template> </template>
<script setup lang='ts'> <script setup lang="ts">
import { ref, reactive } from 'vue' import { ref, reactive } from "vue";
import { ruleProps } from './interface/index' import { ruleProps } from "./interface/index";
import { import {
getImageService, getImageService,
addImageService, addImageService,
updateImageService, updateImageService,
deleteImageService deleteImageService,
} from '@/services/api/imageService/index'; } from "@/services/api/imageService/index";
import { ElMessage, ElMessageBox } from 'element-plus'; import { ElMessage, ElMessageBox } from "element-plus";
import imageServiceForm from './components/imageServiceForm.vue'; import imageServiceForm from "./components/imageServiceForm.vue";
import imageServiceTable from './components/imageServiceTable.vue'; import imageServiceTable from "./components/imageServiceTable.vue";
import pagination from '@/components/pagination/index.vue' import pagination from "@/components/pagination/index.vue";
const labelList = [ const labelList = [
{ label: '镜像名', prop: 'name' }, { label: "镜像名", prop: "name" },
{ label: '服务路径', prop: 'contextPath' }, { label: "服务路径", prop: "contextPath" },
{ label: '描述', prop: 'describe' }, { label: "描述", prop: "describe" },
] ];
const imageServiceDialog = ref(false) const imageServiceDialog = ref(false);
const imageVersionTableDialog = ref(false) const imageVersionTableDialog = ref(false);
const loading = ref(true) const loading = ref(true);
const imageServiceFormRef = ref() const imageServiceFormRef = ref();
const imageVersionRef = ref() const imageVersionRef = ref();
const tableData = ref<ruleProps[]>() const tableData = ref<ruleProps[]>();
const listQuery = reactive({ const listQuery = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
total: 0 total: 0,
}) });
// 每页新条数 // 每页新条数
const sizeChange = (val: number) => { const sizeChange = (val: number) => {
listQuery.pageSize = val listQuery.pageSize = val;
init() init();
} };
// 新页数 // 新页数
const currentChange = (val: number) => { const currentChange = (val: number) => {
listQuery.pageNo = val listQuery.pageNo = val;
init() init();
} };
const imageVersion = (id: number) => { const imageVersion = (id: number) => {
imageVersionRef.value.imageVersionId = id imageVersionRef.value.imageVersionId = id;
imageVersionRef.value.initVersion(id) imageVersionRef.value.initVersion(id);
imageVersionTableDialog.value = true imageVersionTableDialog.value = true;
} };
const addData = () => { const addData = () => {
imageServiceFormRef.value.title = '新增服务镜像'; imageServiceFormRef.value.title = "新增服务镜像";
imageServiceDialog.value = true; imageServiceDialog.value = true;
} };
const editData = (row: any) => { const editData = (row: any) => {
imageServiceFormRef.value.formData = row imageServiceFormRef.value.formData = row;
imageServiceFormRef.value.title = '编辑服务镜像' imageServiceFormRef.value.title = "编辑服务镜像";
imageServiceDialog.value = true imageServiceDialog.value = true;
} };
const deleteData = (id: number) => { const deleteData = (id: number) => {
ElMessageBox.confirm('确定删除吗?', '温馨提示', { ElMessageBox.confirm("确定删除吗?", "温馨提示", {
confirmButtonText: '确定', confirmButtonText: "确定",
cancelButtonText: '取消', cancelButtonText: "取消",
type: 'warning', type: "warning",
}).then(async () => { }).then(async () => {
const res: any = await deleteImageService(id) const res: any = await deleteImageService(id);
if (res.code === 200) { if (res.code === 200) {
ElMessage.success('删除成功') ElMessage.success("删除成功");
init() init();
} }
}) });
} };
const getImageServiceData = async (formData: ruleProps) => { const getImageServiceData = async (formData: ruleProps) => {
if (!formData.id) { if (!formData.id) {
const res: any = await addImageService(formData) const res: any = await addImageService(formData);
if (res.code === 200) { if (res.code === 200) {
ElMessage.success('添加成功') ElMessage.success("添加成功");
init() init();
imageServiceDialog.value = false imageServiceDialog.value = false;
} }
} else { } else {
const res: any = await updateImageService(formData) const res: any = await updateImageService(formData);
if (res.code === 200) { if (res.code === 200) {
ElMessage.success('修改成功') ElMessage.success("修改成功");
imageServiceDialog.value = false imageServiceDialog.value = false;
init() init();
} }
} }
} };
const init = async () => { const init = async () => {
loading.value = true loading.value = true;
const res: any = await getImageService(listQuery) const res: any = await getImageService(listQuery);
if (res.code === 200) { if (res.code === 200) {
loading.value = false loading.value = false;
tableData.value = res.data.records tableData.value = res.data.records;
listQuery.total = res.data.total listQuery.total = res.data.total;
} }
} };
init()
init();
</script> </script>
<style lang = "scss" scoped>
</style>
\ No newline at end of file
<template>
</template>
<script setup lang="ts">
</script>
<style lang="scss">
</style>
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
: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
...@@ -38,15 +38,15 @@ ...@@ -38,15 +38,15 @@
</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="login" @keyup.enter.native="toLogin"
spellcheck="false" spellcheck="false"
style="width: 249px !important"
> >
<template #prefix> <template #prefix>
<el-icon class="el-input__icon"> <el-icon class="el-input__icon">
...@@ -54,12 +54,8 @@ ...@@ -54,12 +54,8 @@
</el-icon> </el-icon>
</template> </template>
</el-input> </el-input>
</el-col>
<el-col :span="2"></el-col>
<el-col :span="4">
<img :src="imgSrc" @click="getImage" /> <img :src="imgSrc" @click="getImage" />
</el-col> </div>
</el-row>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button <el-button
...@@ -75,9 +71,11 @@ ...@@ -75,9 +71,11 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { watch } from "vue";
import useImage from "@/services/business/login/useImage"; import useImage from "@/services/business/login/useImage";
import useBaseLogin from "@/services/business/login/useBaseLogin"; import useBaseLogin from "@/services/business/login/useBaseLogin";
import useLogin from "@/services/business/login/useLogin"; import useLogin from "@/services/business/login/useLogin";
//基础数据 //基础数据
const { loginModel, rules, loginFormRef } = useBaseLogin(); const { loginModel, rules, loginFormRef } = useBaseLogin();
...@@ -85,7 +83,13 @@ const { loginModel, rules, loginFormRef } = useBaseLogin(); ...@@ -85,7 +83,13 @@ const { loginModel, rules, loginFormRef } = useBaseLogin();
const { imgSrc, getImage } = useImage(); const { imgSrc, getImage } = useImage();
//登录 //登录
const { login, loginState } = useLogin(loginModel); const { login, loginState, num } = useLogin(loginModel);
const toLogin = () => {
if (!loginState.value) login();
};
watch(num, () => getImage(), { deep: true });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.logincontainer { .logincontainer {
...@@ -94,6 +98,7 @@ const { login, loginState } = useLogin(loginModel); ...@@ -94,6 +98,7 @@ const { login, loginState } = useLogin(loginModel);
justify-content: center; justify-content: center;
align-items: center; align-items: center;
background-image: url("../../assets/login-background.jpg"); background-image: url("../../assets/login-background.jpg");
.loginForm { .loginForm {
height: 320px; height: 320px;
width: 400px; width: 400px;
...@@ -101,6 +106,7 @@ const { login, loginState } = useLogin(loginModel); ...@@ -101,6 +106,7 @@ const { login, loginState } = useLogin(loginModel);
padding: 20px 35px; padding: 20px 35px;
background-color: white; background-color: white;
box-shadow: 0 0 25px #cac6c6; box-shadow: 0 0 25px #cac6c6;
.loginTitle { .loginTitle {
margin: 0 auto; margin: 0 auto;
font-size: 24px; font-size: 24px;
...@@ -109,13 +115,23 @@ const { login, loginState } = useLogin(loginModel); ...@@ -109,13 +115,23 @@ const { login, loginState } = useLogin(loginModel);
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
.mybtn { .mybtn {
width: 100%; width: 100%;
} }
.el-icon { .el-icon {
height: 2.8em; height: 2.8em;
margin-left: -5px; margin-left: -5px;
} }
.code {
width: 100%;
padding: 0 6px;
display: flex;
justify-content: space-between;
margin-bottom: 6px;
}
} }
} }
</style> </style>
<template> <template>
<div class="app-container"> <div class="app-container">
<Custom-table <Custom-table :tableConfigData="tableConfigData" @handle-show="handleShow">
:tableConfigData="tableConfigData"
@handle-show="handleShow"
>
<template v-slot:drawer> <template v-slot:drawer>
<el-form-item <el-form-item
v-for="(item, index) in tableConfigData.tableTitle" v-for="(item, index) in tableConfigData.tableTitle"
...@@ -30,40 +27,41 @@ ...@@ -30,40 +27,41 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { ref, Ref, reactive } from 'vue' import { ref, Ref, reactive } from "vue";
import { Scope } from '@/table/type' import { Scope } from "@/table/type";
import CustomFormItem from '@/table/components/edit.vue' import CustomFormItem from "@/table/components/edit.vue";
import { menuConfigData } from './tableConfigData/menuManage' import { menuConfigData } from "./tableConfigData/menuManage";
export default { export default {
name: 'MenuManage', name: "MenuManage",
components: { components: {
'custom-form-item': CustomFormItem "custom-form-item": CustomFormItem,
}, },
setup() { setup() {
// 列表数据 // 列表数据
const tableConfigData = reactive(menuConfigData) const tableConfigData: any = reactive(menuConfigData);
const tableData: Ref<any[]> = ref([]) const tableData: Ref<any[]> = ref([]);
const handleShow = ref((params: { key: string, tableData: object[], scope?: Scope }) => { const handleShow = ref(
tableData.value = params.tableData (params: { key: string; tableData: object[]; scope?: Scope }) => {
const key = params.key tableData.value = params.tableData;
const key = params.key;
switch (key) { switch (key) {
case '新增': case "新增":
tableConfigData.drawerformData = { tableConfigData.drawerformData = {
id: '', id: "",
type: 0, type: 0,
title: '', title: "",
component: '', component: "",
path: '', path: "",
sortNo: 0, sortNo: 0,
apiKey: '', apiKey: "",
parentId: '', parentId: "",
icon: '', icon: "",
is_show: true is_show: true,
} };
break break;
case '编辑': { case "编辑": {
if (!params.scope) return false if (!params.scope) return false;
const row = params.scope.row const row = params.scope.row;
tableConfigData.drawerformData = { tableConfigData.drawerformData = {
id: row.id, id: row.id,
type: row.type, type: row.type,
...@@ -74,21 +72,18 @@ export default { ...@@ -74,21 +72,18 @@ export default {
apiKey: row.apiKey, apiKey: row.apiKey,
parentId: row.parentId, parentId: row.parentId,
icon: row.icon, icon: row.icon,
is_show: row.is_show 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"
@handle-show="handleShow"
>
<template v-slot:tableButton="scope"> <template v-slot:tableButton="scope">
<el-button type="primary" size="small" @click="drawerData.handleShow(scope)">授权</el-button> <el-button
type="primary"
size="small"
@click="drawerData.handleShow(scope)"
>授权</el-button
>
</template> </template>
<template v-slot:drawer> <template v-slot:drawer>
<el-form-item <el-form-item
...@@ -31,102 +33,119 @@ ...@@ -31,102 +33,119 @@
direction="rtl" direction="rtl"
:before-close="drawerData.handleClose" :before-close="drawerData.handleClose"
> >
<el-tree ref="tree" :data="drawerData.treeData" node-key="key" :default-expand-all="true" :check-strictly="true" show-checkbox /> <el-tree
<el-button type="primary" @click="drawerData.onSubmit(ruleFormRef)">保存</el-button> ref="tree"
:data="drawerData.treeData"
node-key="key"
:default-expand-all="true"
:check-strictly="true"
show-checkbox
/>
<el-button type="primary" @click="drawerData.onSubmit()">保存</el-button>
<el-button @click="drawerData.handleClose">取消</el-button> <el-button @click="drawerData.handleClose">取消</el-button>
</el-drawer> </el-drawer>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { ref, Ref, reactive } from 'vue' import { ref, Ref, reactive } from "vue";
import { Scope } from '@/table/type' import { Scope } from "@/table/type";
import { roleConfigData } from './tableConfigData/roleManage' import { roleConfigData } from "./tableConfigData/roleManage";
import { getQueryRoleMenu, getQueryTreeList, saveRole } from '@/services/api/role/roleAPI' import {
import type { ElTree } from 'element-plus'; getQueryRoleMenu,
import { ElNotification } from 'element-plus' getQueryTreeList,
saveRole,
} from "@/services/api/role/roleAPI";
import type { ElTree } from "element-plus";
import { ElNotification } from "element-plus";
export default { export default {
name: 'MenuManage', name: "MenuManage",
setup() { setup() {
// type: 编辑的输入类型不填表示不加入编辑功能 inputType: input类型 // type: 编辑的输入类型不填表示不加入编辑功能 inputType: input类型
const tableConfigData = reactive(roleConfigData) const tableConfigData: any = reactive(roleConfigData);
const editData: Ref<any[]> = ref([]) const editData: Ref<any[]> = ref([]);
tableConfigData.tableTitle.forEach(item => { tableConfigData.tableTitle.forEach((item: any) => {
if (item.type) { if (item.type) {
editData.value.push(item) editData.value.push(item);
} }
}) });
const tableData: Ref<any[]> = ref([]) const tableData: Ref<any[]> = ref([]);
const handleShow = ref((params: { key: string, tableData: object[], scope?: Scope }) => { const handleShow = ref(
tableData.value = params.tableData (params: { key: string; tableData: object[]; scope?: Scope }) => {
const key = params.key tableData.value = params.tableData;
const key = params.key;
switch (key) { switch (key) {
case '新增': case "新增":
tableConfigData.drawerformData = { tableConfigData.drawerformData = {
id: '', id: "",
roleCode: '', roleCode: "",
roleName: '', roleName: "",
roleDesc: '' roleDesc: "",
} };
break break;
case '编辑': { case "编辑": {
if (!params.scope) return false if (!params.scope) return false;
const row = params.scope.row const row = params.scope.row;
tableConfigData.drawerformData = { tableConfigData.drawerformData = {
id: row.id, id: row.id,
roleCode: row.roleCode, roleCode: row.roleCode,
roleName: row.roleName, roleName: row.roleName,
roleDesc: row.roleDesc roleDesc: row.roleDesc,
};
break;
} }
break
} }
} }
}) );
const tree = ref<InstanceType<typeof ElTree>>() const tree = ref<InstanceType<typeof ElTree>>();
const permissionParams: { permissionIds: Array<any>, lastPermissionIds: Array<any>, roleId: string} = { const permissionParams: {
permissionIds: Array<any>;
lastPermissionIds: Array<any>;
roleId: string;
} = {
permissionIds: [], permissionIds: [],
lastPermissionIds: [], lastPermissionIds: [],
roleId: '' roleId: "",
} };
// 授权抽屉数据 // 授权抽屉数据
const drawerData = reactive({ const drawerData = reactive({
drawerShow: false, drawerShow: false,
treeData: [], treeData: [],
handleClose: () => { handleClose: () => {
drawerData.drawerShow = false drawerData.drawerShow = false;
}, },
handleShow: (scope: Scope) => { handleShow: (scope: Scope) => {
drawerData.drawerShow = true drawerData.drawerShow = true;
permissionParams.roleId = scope.row.id permissionParams.roleId = scope.row.id;
getQueryRoleMenu({ id: scope.row.id }).then((res: any) => { getQueryRoleMenu({ id: scope.row.id }).then((res: any) => {
if (res.code === 200) { if (res.code === 200) {
permissionParams.lastPermissionIds = res.data permissionParams.lastPermissionIds = res.data;
tree.value!.setCheckedKeys(res.data as Node[], true) tree.value!.setCheckedKeys(res.data, true);
} }
}) });
}, },
onSubmit: () => { onSubmit: () => {
permissionParams.permissionIds = tree.value!.getCheckedKeys(false) permissionParams.permissionIds = tree.value!.getCheckedKeys(false);
saveRole(permissionParams).then((res: any) => { saveRole(permissionParams).then((res: any) => {
if (res.code === 200) { if (res.code === 200) {
drawerData.handleClose() drawerData.handleClose();
ElNotification({ ElNotification({
title: '温馨提示', title: "温馨提示",
message: '保存成功!', message: "保存成功!",
type: 'success' type: "success",
}) });
}
})
} }
}) });
},
});
getQueryTreeList().then((res: any) => { getQueryTreeList().then((res: any) => {
if (res.code === 200) { if (res.code === 200) {
drawerData.treeData = res.data.treeList drawerData.treeData = res.data.treeList;
} }
}) });
return { return {
handleShow, handleShow,
...@@ -134,12 +153,8 @@ export default { ...@@ -134,12 +153,8 @@ export default {
tableData, tableData,
editData, editData,
drawerData, drawerData,
tree tree,
} };
} },
} };
</script> </script>
<style lang="scss">
</style>
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: [
{ required: true, message: '请输入角色名称', trigger: 'blur' }
]
}, },
btnObj: { btnObj: {
width: '200', width: "200",
isAdd: true, isAdd: true,
isDelete: true isDelete: true,
}, },
apiKey: 'role', apiKey: "role",
tableApi: '/list', tableApi: "/list",
dataKey: 'records' dataKey: "records",
} };
export { roleConfigData } 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: [
// // Auto register icon components
// // 自动注册图标组件
// IconsResolver({
// enabledCollections: ['ep'],
// }),
// // Auto register Element Plus components
// // 自动导入 Element Plus 组件
// ElementPlusResolver(),
// ],
// dts: path.resolve(pathSrc, 'components.d.ts'),
// }),
// Icons({ resolvers: [
// autoInstall: true, ElementPlusResolver(),
// }), IconsResolver({
prefix: "Icon",
}),
],
dts: resolve(pathSrc, "auto-imports.d.ts"),
}),
Components({
resolvers: [
// 自动注册图标组件
IconsResolver({
enabledCollections: ["ep"],
}),
// 自动导入 Element Plus 组件
ElementPlusResolver(),
],
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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论