1、项目名增加plat
2、增加数据和模型的swagger接口api
3、增加应用列表及应用切换功能,暂时放home页
4、其它相关修改
已修改11个文件
已添加5个文件
313 ■■■■ 文件已修改
src/api/system/app/index.ts 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.ts 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/fetch.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/hostMap.ts 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Home/Index.vue 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Login/Login.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/Login/components/LoginForm.vue 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/data/swagger/index.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/swagger/index.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/infra/wiki/index.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/micro/index.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/model/swagger/index.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/app/AppForm.vue 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/app/index.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/role/index.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/system/app/index.ts
@@ -24,9 +24,14 @@
  return request.get({ url: '/system/app/page', params })
}
// 查询列表
// 查询所拥有应用列表
export const getAppList = () => {
  return request.get({ url: '/system/app/getAppList' })
  return request.get({ url: '/system/auth/get-app-permission' })
}
// 查询所拥有应用菜单列表
export const getAppMenuList = (id) => {
  return request.get({ url: '/system/auth/get-app-menu-permission?id=' + id })
}
// 获得
src/main.ts
@@ -46,9 +46,15 @@
const { setupApp } = WujieVue
import { micros, getUrl } from '@/utils/micors'
import hostMap from "@/utils/hostMap";
import { micros } from '@/utils/micors'
import lifecycles from '@/utils/lifecycles' // 生命周期函数
// import credentialsFetch from "@/utils/fetch";
const isProduction = process.env.NODE_ENV === "production";
// 创建实例
const setupAll = async () => {
@@ -79,6 +85,13 @@
setupAll()
const degrade = window.localStorage.getItem("degrade") === "true" || !window.Proxy || !window.CustomElementRegistry;
const props = {
  jump: (name) => {
    router.push({ name });
  },
};
// 模拟接口查询,实现动动态子应用加载与动态路由添加
const setMiro = () =>
  new Promise((resolve) => {
@@ -89,12 +102,27 @@
        component: () => import(`@/views/micro/index.vue`)
      }
      router.addRoute('home', obj)
      const attrs = isProduction ? { src: hostMap("//localhost/") } : {};
      setupApp({
        name: value.name,
        url: getUrl(value.name, micros),
        name: "fast",
        url: hostMap("//localhost:90/"),
        attrs,
        exec: true,
        ...lifecycles
      })
        alive: true,
        plugins: [{ cssExcludes: ["https://stackpath.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"] }],
        props,
        // 引入了的第三方样式不需要添加credentials
        // fetch: (url, options) =>
        //   url.includes(hostMap("//localhost:90/")) ? credentialsFetch(url, options) : window.fetch(url, options),
        degrade,
        ...lifecycles,
      });
      // setupApp({
      //   name: value.name,
      //   url: getUrl(value.name, micros),
      //   exec: true,
      //   ...lifecycles
      // })
    }
    resolve(true)
  })
src/router/index.ts
@@ -5,7 +5,7 @@
// 创建路由实例
const router = createRouter({
  history: createWebHistory(), // createWebHashHistory URL带#,createWebHistory URL不带#
  history: createWebHistory('/plat'), // createWebHashHistory URL带#,createWebHistory URL不带#
  strict: true,
  routes: remainingRouter as RouteRecordRaw[],
  scrollBehavior: () => ({ left: 0, top: 0 })
src/utils/fetch.ts
对比新文件
@@ -0,0 +1,4 @@
// 携带登录态credentials必须为include
export default function fetch(url, options) {
  return window.fetch(url, { ...options, credentials: "omit" });
}
src/utils/hostMap.ts
对比新文件
@@ -0,0 +1,10 @@
const map = {
  "//localhost:7200/": "//wujie-micro.github.io/demo-vue2/",
  "//localhost:90/": "//localhost:90/",
  "//localhost:8000/": "//wujie-micro.github.io/demo-main-vue/",
};
export default function hostMap(host) {
  if (process.env.NODE_ENV === "production") return map[host];
  return host;
}
src/views/Home/Index.vue
@@ -1,12 +1,96 @@
<template>
  <div>
    <h1>这里是应用首页</h1>
    <h1>IAILAB 平台主页</h1>
  </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>
      </div>
    </div>
  </el-skeleton>
</template>
<script lang="ts" setup>
import * as AppApi from '@/api/system/app'
import {Apps} from "@/views/Home/types";
import {CACHE_KEY, useCache} from "@/hooks/web/useCache";
import * as authUtil from "@/utils/auth";
defineOptions({ name: 'Home' })
const { wsCache } = useCache()
const loading = ref(true)
let appList = reactive<Apps[]>([])
const getAppList = async () => {
  const data = await AppApi.getAppList()
  appList = Object.assign(appList, data)
}
const getAppMenuList = async (id) => {
  const data = await AppApi.getAppMenuList(id)
  console.log(data)
  let userInfo = wsCache.get(CACHE_KEY.USER)
  let routers = wsCache.get(CACHE_KEY.ROLE_ROUTERS)
  console.log(userInfo)
  console.log(routers)
  userInfo.menus = data
  wsCache.set(CACHE_KEY.USER, userInfo)
  wsCache.set(CACHE_KEY.ROLE_ROUTERS, data)
  window.location.href = '/plat/index'
}
const getAllApi = async () => {
  await Promise.all([
    getAppList()
  ])
  loading.value = false
}
getAllApi()
// 进入应用
const gotoApp = async (item) => {
  let id = item.id
  let type = item.type
  console.log(type)
  if(type === 0) {
    getAppMenuList(id)
  } else {
    // await OAuth2Login(formData.value)
    window.open(item.appDomain + '/login?appid=' + item.id + "&username=" + authUtil.getLoginForm().username, '_blank')
  }
}
</script>
<style lang="scss" scoped>
#app{
  width: 300px;
  height: 200px;
  display: inline-block;
  background: transparent;
}
.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;
}
</style>
src/views/Login/Login.vue
@@ -55,7 +55,7 @@
            <!-- 注册 -->
            <!--<RegisterForm class="m-auto h-auto p-20px lt-xl:(rounded-3xl light:bg-white)" />-->
            <!-- 三方登录 -->
            <!--<SSOLoginVue class="m-auto h-auto p-20px lt-xl:(rounded-3xl light:bg-white)" />-->
            <SSOLoginVue class="m-auto h-auto p-20px lt-xl:(rounded-3xl light:bg-white)" />
          </div>
        </Transition>
      </div>
src/views/Login/components/LoginForm.vue
@@ -100,13 +100,12 @@
defineOptions({ name: 'LoginForm' })
const { t } = useI18n()
const message = useMessage()
const iconHouse = useIcon({ icon: 'ep:house' })
const iconAvatar = useIcon({ icon: 'ep:avatar' })
const iconLock = useIcon({ icon: 'ep:lock' })
const formLogin = ref()
const { validForm } = useFormValid(formLogin)
const { setLoginState, getLoginState } = useLoginState()
const { getLoginState } = useLoginState()
const { currentRoute, push } = useRouter()
const permissionStore = usePermissionStore()
const redirect = ref<string>('')
@@ -201,20 +200,14 @@
    }
    authUtil.setToken(res)
    if (!redirect.value) {
      redirect.value = '/'
      redirect.value = '/index'
    }
    let tenantId = authUtil.getTenantId()
    // if(tenantId != 1) {
    //   //只要不是系统租户,登录成功跳转到home2页面
    //   window.location.href = '/home2'
    // } else {
      // 判断是否为SSO登录
      if (redirect.value.indexOf('sso') !== -1) {
        window.location.href = window.location.href.replace('/login?redirect=', '')
      } else {
        push({ path: redirect.value || permissionStore.addRouters[0].path })
      }
    // }
    // 判断是否为SSO登录
    if (redirect.value.indexOf('sso') !== -1) {
      window.location.href = window.location.href.replace('/login?redirect=', '')
    } else {
      push({ path: redirect.value || permissionStore.addRouters[0].path })
    }
  } finally {
    loginLoading.value = false
    loading.value.close()
src/views/data/swagger/index.vue
对比新文件
@@ -0,0 +1,25 @@
<template>
  <ContentWrap>
    <IFrame :src="src" />
  </ContentWrap>
</template>
<script lang="ts" setup>
import * as ConfigApi from '@/api/infra/config'
defineOptions({ name: 'DataSwagger' })
const loading = ref(true) // 是否加载中
const src = ref(import.meta.env.VITE_BASE_URL + '/doc.html')
/** 初始化 */
onMounted(async () => {
  try {
    const data = await ConfigApi.getConfigKey('data.swagger')
    if (data && data.length > 0) {
      src.value = data
    }
  } finally {
    loading.value = false
  }
})
</script>
src/views/infra/swagger/index.vue
@@ -9,8 +9,7 @@
defineOptions({ name: 'InfraSwagger' })
const loading = ref(true) // 是否加载中
const src = ref(import.meta.env.VITE_BASE_URL + '/doc.html') // Knife4j UI
// const src = ref(import.meta.env.VITE_BASE_URL + '/swagger-ui') // Swagger UI
const src = ref(import.meta.env.VITE_BASE_URL + '/doc.html')
/** 初始化 */
onMounted(async () => {
src/views/infra/wiki/index.vue
对比新文件
@@ -0,0 +1,25 @@
<template>
  <ContentWrap>
    <IFrame v-if="!loading" :src="url" />
  </ContentWrap>
</template>
<script lang="ts" setup>
import * as ConfigApi from '@/api/infra/config'
defineOptions({ name: 'InfraWiki' })
const loading = ref(true) // 是否加载中
const url = ref(import.meta.env.VITE_BASE_URL + '/wiki/index.html')
/** 初始化 */
onMounted(async () => {
  try {
    const data = await ConfigApi.getConfigKey('url.wiki')
    if (data && data.length > 0) {
      url.value = data
    }
  } finally {
    loading.value = false
  }
})
</script>
src/views/micro/index.vue
@@ -4,10 +4,19 @@
  </div>
</template>
<script lang="ts" setup>
import { getUrl } from '@/utils/micors'
const router: any = useRouter()
const url = computed(() => getUrl(router.currentRoute.value.name))
const name = computed(() => router.currentRoute.value.name)
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
  }
)
</script>
<style scoped lang="scss">
.sub-app {
src/views/model/swagger/index.vue
对比新文件
@@ -0,0 +1,26 @@
<template>
  <ContentWrap>
    <IFrame :src="src" />
  </ContentWrap>
</template>
<script lang="ts" setup>
import * as ConfigApi from '@/api/infra/config'
defineOptions({ name: 'ModelSwagger' })
const loading = ref(true) // 是否加载中
const src = ref(import.meta.env.VITE_BASE_URL + '/doc.html')
// const src = ref(import.meta.env.VITE_BASE_URL + '/swagger-ui') // Swagger UI
/** 初始化 */
onMounted(async () => {
  try {
    const data = await ConfigApi.getConfigKey('model.swagger')
    if (data && data.length > 0) {
      src.value = data
    }
  } finally {
    loading.value = false
  }
})
</script>
src/views/system/app/AppForm.vue
@@ -7,27 +7,15 @@
      :rules="formRules"
      label-width="80px"
    >
      <el-col :span="12">
        <el-form-item label="应用类型">
          <el-select v-model="formData.type" placeholder="请选择">
            <el-option
              v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_APP_TYPE)"
              :key="dict.value"
              :label="dict.label"
              :value="dict.value"
            />
          </el-select>
        </el-form-item>
      </el-col>
      <el-row>
        <el-col :span="12">
          <el-form-item label="选择租户" prop="tenantId">
            <el-select v-model="formData.tenantId" clearable placeholder="请选择租户">
          <el-form-item label="应用类型">
            <el-select v-model="formData.type" placeholder="请选择">
              <el-option
                v-for="item in tenantList"
                :key="item.id"
                :label="item.name"
                :value="item.id"
                v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_APP_TYPE)"
                :key="dict.value"
                :label="dict.label"
                :value="dict.value"
              />
            </el-select>
          </el-form-item>
src/views/system/app/index.vue
@@ -81,15 +81,6 @@
          <dict-tag :type="DICT_TYPE.SYSTEM_APP_TYPE" :value="scope.row.type" />
        </template>
      </el-table-column>
      <el-table-column label="所属租户" align="center" prop="tenantId">
        <template #default="scope">
          <template v-for="item in tenantList">
            <el-tag type="success" :key="item.id" v-if="item.id === scope.row.tenantId">
              {{ item.name }}
            </el-tag>
          </template>
        </template>
      </el-table-column>
      <el-table-column label="应用分组" align="center" prop="groupId">
        <template #default="scope">
          <template v-for="item in groupList">
src/views/system/role/index.vue
@@ -125,16 +125,6 @@
            菜单权限
          </el-button>
          <el-button
            v-hasPermi="['system:permission:assign-role-data-scope']"
            link
            preIcon="ep:coin"
            title="数据权限"
            type="primary"
            @click="openDataPermissionForm(scope.row)"
          >
            数据权限
          </el-button>
          <el-button
            v-hasPermi="['system:role:delete']"
            link
            type="danger"