index.html | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
public/favicon.ico | 补丁 | 查看 | 原始文档 | blame | 历史 | |
public/logo.gif | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/api/system/tenantPackage/index.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/assets/imgs/logo.png | 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/hooks/web/useCache.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/layout/components/Logo/src/Logo.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/store/modules/user.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/Home/Index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/micro/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/report/drag/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/system/tenantPackage/TenantPackageForm.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/system/tenantPackage/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
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"> public/favicon.icoBinary files differ
public/logo.gifBinary files differ
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 src/assets/imgs/logo.pngsrc/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 登录表单 } 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 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) }, 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> 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 { 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> 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 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>