From 94d91d89fd5e3a641e77629ac60ea5d7e1a6801f Mon Sep 17 00:00:00 2001 From: houzhongjian <houzhongyi@126.com> Date: 星期三, 27 十一月 2024 09:53:37 +0800 Subject: [PATCH] 1、修改首页 2、修改租户套餐页面 3、修改logo图标 4、点击左上角平台名称和logo,展示所有菜单等 --- /dev/null | 0 src/views/system/tenantPackage/TenantPackageForm.vue | 21 +++ src/views/report/drag/index.vue | 13 + src/hooks/web/useCache.ts | 16 ++ index.html | 4 src/assets/imgs/logo.png | 0 src/api/system/tenantPackage/index.ts | 3 src/store/modules/user.ts | 1 src/layout/components/Logo/src/Logo.vue | 25 +++ src/views/Home/Index.vue | 104 ++++++++++---- src/views/system/tenantPackage/index.vue | 166 ++++++++++++++++++----- src/views/micro/index.vue | 26 +-- 12 files changed, 294 insertions(+), 85 deletions(-) diff --git a/index.html b/index.html index 0d9deba..c3d9097 100644 --- a/index.html +++ b/index.html @@ -2,7 +2,7 @@ <html lang="en"> <head> <meta charset="UTF-8" /> - <link rel="icon" href="/favicon.ico" /> + <link rel="icon" href="/src/assets/imgs/logo.png" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta @@ -136,7 +136,7 @@ <div class="app-loading"> <div class="app-loading-wrap"> <div class="app-loading-title"> - <img src="/logo.gif" class="app-loading-logo" alt="Logo" /> + <img src="/src/assets/imgs/logo.png" class="app-loading-logo" alt="Logo" /> <div class="app-loading-title">%VITE_APP_TITLE%</div> </div> <div class="app-loading-item"> diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index 5a7de08..0000000 --- a/public/favicon.ico +++ /dev/null Binary files differ diff --git a/public/logo.gif b/public/logo.gif deleted file mode 100644 index fdbd32c..0000000 --- a/public/logo.gif +++ /dev/null Binary files differ diff --git a/src/api/system/tenantPackage/index.ts b/src/api/system/tenantPackage/index.ts index e01375a..fdf9a5b 100644 --- a/src/api/system/tenantPackage/index.ts +++ b/src/api/system/tenantPackage/index.ts @@ -4,6 +4,9 @@ id: number name: string status: number + icon: string + labels: string + description: string remark: string creator: string updater: string diff --git a/src/assets/imgs/logo.png b/src/assets/imgs/logo.png index 4017d80..f55aafb 100644 --- a/src/assets/imgs/logo.png +++ b/src/assets/imgs/logo.png Binary files differ diff --git a/src/hooks/web/useCache.ts b/src/hooks/web/useCache.ts index 4f39f30..f6b2bd1 100644 --- a/src/hooks/web/useCache.ts +++ b/src/hooks/web/useCache.ts @@ -37,3 +37,19 @@ wsCache.delete(CACHE_KEY.ROLE_ROUTERS) // 注意,不要清理 LoginForm 登录表单 } + +export const useSessionCache = (type: CacheType = 'sessionStorage') => { + const wsSessionCache: WebStorageCache = new WebStorageCache({ + storage: type + }) + + return { + wsSessionCache + } +} + +export const deleteUserSessionCache = () => { + const { wsSessionCache } = useSessionCache() + wsSessionCache.delete(CACHE_KEY.ROLE_ROUTERS) + // 注意,不要清理 用户和 LoginForm 登录表单 +} diff --git a/src/layout/components/Logo/src/Logo.vue b/src/layout/components/Logo/src/Logo.vue index 2d1cfb6..98b17c3 100644 --- a/src/layout/components/Logo/src/Logo.vue +++ b/src/layout/components/Logo/src/Logo.vue @@ -1,8 +1,14 @@ <script lang="ts" setup> import { computed, onMounted, ref, unref, watch } from 'vue' import { useAppStore } from '@/store/modules/app' +import { useUserStoreWithOut } from '@/store/modules/user' +import { usePermissionStoreWithOut } from '@/store/modules/permission' import { useDesign } from '@/hooks/web/useDesign' -import * as authUtil from "@/utils/auth"; +import {isRelogin} from "@/config/axios/service"; +import router from "@/router"; +import type {RouteRecordRaw} from "vue-router"; +import {CACHE_KEY, useCache} from "@/hooks/web/useCache"; +const { wsCache } = useCache() defineOptions({ name: 'Logo' }) @@ -59,6 +65,22 @@ } } ) + +/** 刷新所有菜单权限 */ +const gotoHome = async () => { + const userStore = useUserStoreWithOut() + const permissionStore = usePermissionStoreWithOut() + isRelogin.show = true + wsCache.set(CACHE_KEY.USER, null) + await userStore.setUserInfoAction() + isRelogin.show = false + // 后端过滤菜单 + await permissionStore.generateRoutes() + permissionStore.getAddRouters.forEach((route) => { + router.addRoute(route as unknown as RouteRecordRaw) // 动态添加可访问路由表 + }) +} + </script> <template> @@ -69,6 +91,7 @@ layout !== 'classic' ? `${prefixCls}__Top` : '', 'flex !h-[var(--logo-height)] items-center cursor-pointer pl-8px relative decoration-none overflow-hidden' ]" + @click="gotoHome" :to="homePath" > <img diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index b386180..1e8ae63 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -61,6 +61,7 @@ this.roles = userInfo.roles this.user = userInfo.user this.isSetUser = true + console.log(userInfo.menus) wsCache.set(CACHE_KEY.USER, userInfo) wsCache.set(CACHE_KEY.ROLE_ROUTERS, userInfo.menus) }, diff --git a/src/views/Home/Index.vue b/src/views/Home/Index.vue index 822f800..8150679 100644 --- a/src/views/Home/Index.vue +++ b/src/views/Home/Index.vue @@ -1,13 +1,20 @@ <template> - <div> - <h1>IAILAB 平台主页</h1> + <div id="title"> + <span>工业互联网平台</span> </div> <el-skeleton :loading="loading" animated> - <div id="app" v-for="(item, index) in appList" :key="`dynamics-${index}`"> - <div class="card" @click="gotoApp(item)"> - <img :src="item.icon" style="width: 100px; height: 100px"/> - <div> - {{ item.appName }} + <div id="app"> + <div class="card" v-for="(item, index) in appList" :key="`dynamics-${index}`"> + <div @click="gotoApp(item)"> + <img class="card-left" :src="item.icon"/> + <div class="card-right"> + <div class="app-title"> + {{ item.appName }} + </div> + <div class="goto-app"> + <div>进入系统</div> + </div> + </div> </div> </div> </div> @@ -63,11 +70,11 @@ if (type === 0) { await getAppMenuList(id, appCode) } else { - const data = await AppApi.getAppMenuList(id) - let userInfo = wsCache.get(CACHE_KEY.USER) - userInfo.menus = data - wsCache.set(CACHE_KEY.USER, userInfo) - wsCache.set(CACHE_KEY.ROLE_ROUTERS, data) + // const data = await AppApi.getAppMenuList(id) + // let userInfo = wsCache.get(CACHE_KEY.USER) + // userInfo.menus = data + // wsCache.set(CACHE_KEY.USER, userInfo) + // wsCache.set(CACHE_KEY.ROLE_ROUTERS, data) window.open(item.appDomain + '/index', '_blank') // window.open('/plat/shasteel', '_blank') // window.location.href = '/plat/shasteel' @@ -78,24 +85,63 @@ </script> <style lang="scss" scoped> -#app { - width: 300px; - height: 200px; - display: inline-block; - background: transparent; +#title { + width: 280px; + height: 51px; + margin: 30px auto; + font-family: Microsoft YaHei UI, Microsoft YaHei UI; + font-weight: bold; + font-size: 40px; + color: #282F3D; } - +#app { + margin: 0 96px; + width: 100%; +} .card { - border: thin dashed gainsboro; - width: 150px; - height: 120px; - padding: 30px; - text-align: center; - justify-content: center; - font-size: 15px; - font-weight: bolder; - color: blue; - background: aliceblue; - border-radius: 10px; + width: 354px; + height: 200px; + margin: 0 24px 24px 0; + background: linear-gradient( 180deg, #E9F0FA 0%, #FFFFFF 100%); + border-radius: 12px 12px 12px 12px; + border: 2px solid; + border-image: linear-gradient(180deg, rgba(255, 255, 255, 1), rgba(255, 255, 255, 1)) 2 2; + display: inline-block; +} +.card > div{ + display: inline-block; +} +.card-left{ + height: 100px; + width: 100px; + float: left; + margin: 50px 30px; +} +.card-right { + float: right; + margin: 61px 10px; +} +.app-title { + width: 162px; + height: 32px; + font-family: Microsoft YaHei, Microsoft YaHei; + font-weight: bold; + font-size: 24px; + color: #282F3D; +} +.goto-app { + width: 96px; + height: 35px; + margin-top: 5px; + background: #3A99FD; + border-radius: 80px 80px 80px 80px; +} +.goto-app > div { + padding: 6px; + margin-left: 5px; + font-family: Microsoft YaHei UI, Microsoft YaHei UI; + font-weight: 400; + font-size: 18px; + color: #FFFFFF; } </style> diff --git a/src/views/micro/index.vue b/src/views/micro/index.vue index 1a4669c..92b9626 100644 --- a/src/views/micro/index.vue +++ b/src/views/micro/index.vue @@ -1,22 +1,20 @@ <template> <div class="sub-app"> - <WujieVue width="100%" height="100%" :name="name" :url="url" :alive="true" sync /> + <WujieVue width="100%" height="100%" v-bind="computedOptions" :degrade="true" :alive="true" sync /> </div> </template> <script lang="ts" setup> -import hostMap from "@/utils/hostMap"; -import wujieVue from "wujie-vue3"; -const route = useRoute() -const url = hostMap("//localhost:90/") + route.params.path -const name = 'fast' -watch(() => "$route.params.path", - () => { - wujieVue.bus.$emit("vue3-router-change", `/${route.params.path}`); - }, - { - immediate: true - } -) + import WujieVue from "wujie-vue3"; + import { useRoute } from 'vue-router' + import { computed } from 'vue' + + const route = useRoute() + const computedOptions = computed(() => { + return { + name: route.query.key, + url: route.query.url, + } + }) </script> <style scoped lang="scss"> .sub-app { diff --git a/src/views/report/drag/index.vue b/src/views/report/drag/index.vue new file mode 100644 index 0000000..295c10a --- /dev/null +++ b/src/views/report/drag/index.vue @@ -0,0 +1,13 @@ +<template> + <ContentWrap> + <IFrame :src="src" /> + </ContentWrap> +</template> +<script lang="ts" setup> +import { getAccessToken } from '@/utils/auth' + +defineOptions({ name: 'Drag' }) + +const BASE_URL = import.meta.env.VITE_BASE_URL +const src = ref(BASE_URL + '/drag/list?token=' + getAccessToken()) +</script> diff --git a/src/views/system/tenantPackage/TenantPackageForm.vue b/src/views/system/tenantPackage/TenantPackageForm.vue index 7492889..c8bec1f 100644 --- a/src/views/system/tenantPackage/TenantPackageForm.vue +++ b/src/views/system/tenantPackage/TenantPackageForm.vue @@ -10,6 +10,12 @@ <el-form-item label="套餐名" prop="name"> <el-input v-model="formData.name" placeholder="请输入套餐名" /> </el-form-item> + <el-form-item label="套餐介绍" prop="description"> + <el-input type="textarea" v-model="formData.description" placeholder="请输入套餐介绍" /> + </el-form-item> + <el-form-item label="套餐图标"> + <UploadImg v-model="formData.icon" :limit="1" /> + </el-form-item> <el-form-item label="菜单权限"> <el-card class="cardHeight"> <template #header> @@ -39,6 +45,18 @@ show-checkbox /> </el-card> + </el-form-item> + <el-form-item label="套餐标签" prop="labels"> + <el-select + v-model="formData.labels" + filterable + multiple + allow-create + placeholder="请输入套餐标签" + style="width: 500px" + > + <el-option v-for="label in formData.labels" :key="label" :label="label" :value="label" /> + </el-select> </el-form-item> <el-form-item label="状态" prop="status"> <el-radio-group v-model="formData.status"> @@ -81,6 +99,9 @@ const formData = ref({ id: null, name: null, + icon: undefined, + labels: [], + description: null, remark: null, menuIds: [], status: CommonStatusEnum.ENABLE diff --git a/src/views/system/tenantPackage/index.vue b/src/views/system/tenantPackage/index.vue index fc68a4d..e135ec5 100644 --- a/src/views/system/tenantPackage/index.vue +++ b/src/views/system/tenantPackage/index.vue @@ -55,43 +55,51 @@ <!-- 列表 --> <ContentWrap> - <el-table v-loading="loading" :data="list"> - <el-table-column label="套餐编号" align="center" prop="id" width="120" /> - <el-table-column label="套餐名" align="center" prop="name" /> - <el-table-column label="状态" align="center" prop="status" width="100"> - <template #default="scope"> - <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /> - </template> - </el-table-column> - <el-table-column label="备注" align="center" prop="remark" /> - <el-table-column - label="创建时间" - align="center" - prop="createTime" - width="180" - :formatter="dateFormatter" - /> - <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> - <template #default="scope"> - <el-button - link - type="primary" - @click="openForm('update', scope.row.id)" - v-hasPermi="['system:tenant-package:update']" + <el-row :gutter="20"> + <div v-loading="loading" class="package-card" v-for="(item, index) in packages" :key="`dynamics-${index}`"> + <el-col :span="6"> + <img class="card-icon" :src="item.icon" /> + <div class="card-middle"> + <div class="tenant-title">{{item.name}}</div> + <div class="tenant-operation"> + <el-dropdown @command="(command) => handleCommand(command, item)"> + <el-button type="primary" link><Icon icon="ep:more-filled" /> </el-button> + <template #dropdown> + <el-dropdown-menu> + <el-dropdown-item + command="handleUpdate" + v-if="checkPermi(['system:tenant-package:update'])" + > + <Icon icon="ep:edit" />修改 + </el-dropdown-item> + </el-dropdown-menu> + <el-dropdown-menu> + <el-dropdown-item + command="handleDelete" + v-if="checkPermi(['system:tenant-package:delete'])" + > + <Icon icon="ep:delete" />删除 + </el-dropdown-item> + </el-dropdown-menu> + </template> + </el-dropdown> + </div> + </div> + <div class="description">{{item.description}}</div> + <div class="label-areas"> + <el-tag + :disable-transitions="true" + :key="index" + v-for="(label, index) in item.labels" + :index="index" + class="label" > - 修改 - </el-button> - <el-button - link - type="danger" - @click="handleDelete(scope.row.id)" - v-hasPermi="['system:tenant-package:delete']" - > - 删除 - </el-button> - </template> - </el-table-column> - </el-table> + {{ label }} + </el-tag> + </div> + </el-col> + </div> + </el-row> <!-- 分页 --> <Pagination :total="total" @@ -106,9 +114,10 @@ </template> <script lang="ts" setup> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' -import { dateFormatter } from '@/utils/formatTime' import * as TenantPackageApi from '@/api/system/tenantPackage' import TenantPackageForm from './TenantPackageForm.vue' +import {TenantPackageVO} from "@/api/system/tenantPackage"; +import {checkPermi} from "@/utils/permission"; defineOptions({ name: 'SystemTenantPackage' }) @@ -117,7 +126,8 @@ const loading = ref(true) // 列表的加载中 const total = ref(0) // 列表的总页数 -const list = ref([]) // 列表的数据 +const packages = ref([]) // 列表的数据 + const queryParams = reactive({ pageNo: 1, pageSize: 10, @@ -133,7 +143,7 @@ loading.value = true try { const data = await TenantPackageApi.getTenantPackagePage(queryParams) - list.value = data.list + packages.value = data.list total.value = data.total } finally { loading.value = false @@ -158,6 +168,20 @@ formRef.value.open(type, id) } +/** 操作分发 */ +const handleCommand = (command: string, row: TenantPackageVO) => { + switch (command) { + case 'handleUpdate': + openForm('update', row.id) + break + case 'handleDelete': + handleDelete(row.id) + break + default: + break + } +} + /** 删除按钮操作 */ const handleDelete = async (id: number) => { try { @@ -175,4 +199,68 @@ onMounted(() => { getList() }) + </script> +<style lang="scss" scoped> +.package-card { + display: inline-block; + width: 396px; + height: 379px; + background: #FFFFFF; + border-radius: 4px 4px 4px 4px; + border: 1px solid #EBEDF0; + margin: 0px 8px 8px 0; +} +.card-icon { + width: 372px; + height: 200px; + margin: 10px 0 10px 2px; +} +.card-middle { + width: 396px; + height: 25px; + margin: 0 12px; + display: flex; +} +.tenant-title { + width: 340px; + height: 25px; + font-family: Microsoft YaHei UI, Microsoft YaHei UI; + font-weight: bold; + font-size: 20px; + color: #282F3D; +} +.tenant-operation { + margin-right: 12px; +} +.description { + margin: 8px 12px; + width: 372px; + height: 36px; + font-family: Microsoft YaHei, Microsoft YaHei; + font-weight: 400; + font-size: 14px; + color: #6B7785; + line-height: 18px; + word-wrap: break-word; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; +} +.label-areas { + display: flex; + flex-wrap: wrap; + height: 54px; + width: 396px; + margin: 0 8px; +} +.label { + width: 80px; + height: 20px; + margin: 4px; + border-radius: 80px 80px 80px 80px; + border: 1px solid #417CFF; +} +</style> -- Gitblit v1.9.3