1、修改首页
2、修改租户套餐页面
3、修改logo图标
4、点击左上角平台名称和logo,展示所有菜单等
已修改10个文件
已删除2个文件
已添加1个文件
379 ■■■■ 文件已修改
index.html 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/favicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
public/logo.gif 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/tenantPackage/index.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/imgs/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/web/useCache.ts 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Logo/src/Logo.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/user.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Home/Index.vue 104 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/micro/index.vue 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/report/drag/index.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/tenantPackage/TenantPackageForm.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/tenantPackage/index.vue 166 ●●●● 补丁 | 查看 | 原始文档 | 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.ico
Binary files differ
public/logo.gif
Binary 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.png

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 登录表单
}
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>