提交 9cc6d9b6 authored 作者: 王鹏飞's avatar 王鹏飞

feat: 优化路由缓存并统一本地部署配置

上级 a7e77ccc
VITE_LOGIN_URL=http://172.16.3.203:1001/auth/login/index
VITE_QA_CENTER_URL=http://172.16.3.203:1004
VITE_BI_URL=http://172.16.3.203:1012
VITE_FILE_PREVIEW_URL=http://172.16.3.203:8012
VITE_STATIC_URL=https://saas-lab-api
\ No newline at end of file
# IP 地址由 src/utils/env.ts 从浏览器地址栏自动获取,无需手动配置。
# 固定端口:1001=登录、1004=答疑、1012=BI、8012=文件预览。
VITE_STATIC_URL=https://saas-lab-api
......@@ -28,11 +28,15 @@
"controlledComputed": true,
"controlledRef": true,
"createApp": true,
"createDisposableDirective": true,
"createEventHook": true,
"createGlobalState": true,
"createInjectionState": true,
"createReactiveFn": true,
"createRef": true,
"createReusableTemplate": true,
"createSharedComposable": true,
"createTemplatePromise": true,
"createUnrefFn": true,
"customRef": true,
"debouncedRef": true,
......@@ -48,15 +52,13 @@
"h": true,
"ignorableWatch": true,
"inject": true,
"injectLocal": true,
"isDefined": true,
"isProxy": true,
"isReactive": true,
"isReadonly": true,
"isRef": true,
"isShallow": true,
"logicAnd": true,
"logicNot": true,
"logicOr": true,
"makeDestructurable": true,
"markRaw": true,
"nextTick": true,
......@@ -68,6 +70,7 @@
"onBeforeUpdate": true,
"onClickOutside": true,
"onDeactivated": true,
"onElementRemoval": true,
"onErrorCaptured": true,
"onKeyStroke": true,
"onLongPress": true,
......@@ -82,6 +85,7 @@
"onWatcherCleanup": true,
"pausableWatch": true,
"provide": true,
"provideLocal": true,
"reactify": true,
"reactifyObject": true,
"reactive": true,
......@@ -93,11 +97,10 @@
"refAutoReset": true,
"refDebounced": true,
"refDefault": true,
"refManualReset": true,
"refThrottled": true,
"refWithControl": true,
"resolveComponent": true,
"resolveRef": true,
"resolveUnref": true,
"shallowReactive": true,
"shallowReadonly": true,
"shallowRef": true,
......@@ -121,6 +124,19 @@
"unrefElement": true,
"until": true,
"useActiveElement": true,
"useAnimate": true,
"useArrayDifference": true,
"useArrayEvery": true,
"useArrayFilter": true,
"useArrayFind": true,
"useArrayFindIndex": true,
"useArrayFindLast": true,
"useArrayIncludes": true,
"useArrayJoin": true,
"useArrayMap": true,
"useArrayReduce": true,
"useArraySome": true,
"useArrayUnique": true,
"useAsyncQueue": true,
"useAsyncState": true,
"useAttrs": true,
......@@ -131,12 +147,15 @@
"useBroadcastChannel": true,
"useBrowserLocation": true,
"useCached": true,
"useClamp": true,
"useClipboard": true,
"useClipboardItems": true,
"useCloned": true,
"useColorMode": true,
"useConfirmDialog": true,
"useCountdown": true,
"useCounter": true,
"useCssModule": true,
"useCssSupports": true,
"useCssVar": true,
"useCssVars": true,
"useCurrentElement": true,
......@@ -204,17 +223,25 @@
"useOnline": true,
"usePageLeave": true,
"useParallax": true,
"useParentElement": true,
"usePerformanceObserver": true,
"usePermission": true,
"usePointer": true,
"usePointerLock": true,
"usePointerSwipe": true,
"usePreferredColorScheme": true,
"usePreferredContrast": true,
"usePreferredDark": true,
"usePreferredLanguages": true,
"usePreferredReducedMotion": true,
"usePreferredReducedTransparency": true,
"usePrevious": true,
"useRafFn": true,
"useRefHistory": true,
"useResizeObserver": true,
"useRoute": true,
"useRouter": true,
"useSSRWidth": true,
"useScreenOrientation": true,
"useScreenSafeArea": true,
"useScriptTag": true,
......@@ -223,26 +250,32 @@
"useSessionStorage": true,
"useShare": true,
"useSlots": true,
"useSorted": true,
"useSpeechRecognition": true,
"useSpeechSynthesis": true,
"useStepper": true,
"useStorage": true,
"useStorageAsync": true,
"useStyleTag": true,
"useSupported": true,
"useSwipe": true,
"useTemplateRef": true,
"useTemplateRefsList": true,
"useTextDirection": true,
"useTextSelection": true,
"useTextareaAutosize": true,
"useThrottle": true,
"useThrottleFn": true,
"useThrottledRefHistory": true,
"useTimeAgo": true,
"useTimeAgoIntl": true,
"useTimeout": true,
"useTimeoutFn": true,
"useTimeoutPoll": true,
"useTimestamp": true,
"useTitle": true,
"useToNumber": true,
"useToString": true,
"useToggle": true,
"useTransition": true,
"useUrlSearchParams": true,
......@@ -263,8 +296,10 @@
"watchArray": true,
"watchAtMost": true,
"watchDebounced": true,
"watchDeep": true,
"watchEffect": true,
"watchIgnorable": true,
"watchImmediate": true,
"watchOnce": true,
"watchPausable": true,
"watchPostEffect": true,
......
......@@ -17,11 +17,15 @@ declare global {
const controlledComputed: typeof import('@vueuse/core').controlledComputed
const controlledRef: typeof import('@vueuse/core').controlledRef
const createApp: typeof import('vue').createApp
const createDisposableDirective: typeof import('@vueuse/core').createDisposableDirective
const createEventHook: typeof import('@vueuse/core').createEventHook
const createGlobalState: typeof import('@vueuse/core').createGlobalState
const createInjectionState: typeof import('@vueuse/core').createInjectionState
const createReactiveFn: typeof import('@vueuse/core').createReactiveFn
const createRef: typeof import('@vueuse/core').createRef
const createReusableTemplate: typeof import('@vueuse/core').createReusableTemplate
const createSharedComposable: typeof import('@vueuse/core').createSharedComposable
const createTemplatePromise: typeof import('@vueuse/core').createTemplatePromise
const createUnrefFn: typeof import('@vueuse/core').createUnrefFn
const customRef: typeof import('vue').customRef
const debouncedRef: typeof import('@vueuse/core').debouncedRef
......@@ -37,6 +41,7 @@ declare global {
const h: typeof import('vue').h
const ignorableWatch: typeof import('@vueuse/core').ignorableWatch
const inject: typeof import('vue').inject
const injectLocal: typeof import('@vueuse/core').injectLocal
const isDefined: typeof import('@vueuse/core').isDefined
const isProxy: typeof import('vue').isProxy
const isReactive: typeof import('vue').isReactive
......@@ -57,6 +62,7 @@ declare global {
const onBeforeUpdate: typeof import('vue').onBeforeUpdate
const onClickOutside: typeof import('@vueuse/core').onClickOutside
const onDeactivated: typeof import('vue').onDeactivated
const onElementRemoval: typeof import('@vueuse/core').onElementRemoval
const onErrorCaptured: typeof import('vue').onErrorCaptured
const onKeyStroke: typeof import('@vueuse/core').onKeyStroke
const onLongPress: typeof import('@vueuse/core').onLongPress
......@@ -71,6 +77,7 @@ declare global {
const onWatcherCleanup: typeof import('vue').onWatcherCleanup
const pausableWatch: typeof import('@vueuse/core').pausableWatch
const provide: typeof import('vue').provide
const provideLocal: typeof import('@vueuse/core').provideLocal
const reactify: typeof import('@vueuse/core').reactify
const reactifyObject: typeof import('@vueuse/core').reactifyObject
const reactive: typeof import('vue').reactive
......@@ -82,6 +89,7 @@ declare global {
const refAutoReset: typeof import('@vueuse/core').refAutoReset
const refDebounced: typeof import('@vueuse/core').refDebounced
const refDefault: typeof import('@vueuse/core').refDefault
const refManualReset: typeof import('@vueuse/core').refManualReset
const refThrottled: typeof import('@vueuse/core').refThrottled
const refWithControl: typeof import('@vueuse/core').refWithControl
const resolveComponent: typeof import('vue').resolveComponent
......@@ -110,6 +118,19 @@ declare global {
const unrefElement: typeof import('@vueuse/core').unrefElement
const until: typeof import('@vueuse/core').until
const useActiveElement: typeof import('@vueuse/core').useActiveElement
const useAnimate: typeof import('@vueuse/core').useAnimate
const useArrayDifference: typeof import('@vueuse/core').useArrayDifference
const useArrayEvery: typeof import('@vueuse/core').useArrayEvery
const useArrayFilter: typeof import('@vueuse/core').useArrayFilter
const useArrayFind: typeof import('@vueuse/core').useArrayFind
const useArrayFindIndex: typeof import('@vueuse/core').useArrayFindIndex
const useArrayFindLast: typeof import('@vueuse/core').useArrayFindLast
const useArrayIncludes: typeof import('@vueuse/core').useArrayIncludes
const useArrayJoin: typeof import('@vueuse/core').useArrayJoin
const useArrayMap: typeof import('@vueuse/core').useArrayMap
const useArrayReduce: typeof import('@vueuse/core').useArrayReduce
const useArraySome: typeof import('@vueuse/core').useArraySome
const useArrayUnique: typeof import('@vueuse/core').useArrayUnique
const useAsyncQueue: typeof import('@vueuse/core').useAsyncQueue
const useAsyncState: typeof import('@vueuse/core').useAsyncState
const useAttrs: typeof import('vue').useAttrs
......@@ -122,10 +143,14 @@ declare global {
const useCached: typeof import('@vueuse/core').useCached
const useClamp: typeof import('@vueuse/core').useClamp
const useClipboard: typeof import('@vueuse/core').useClipboard
const useClipboardItems: typeof import('@vueuse/core').useClipboardItems
const useCloned: typeof import('@vueuse/core').useCloned
const useColorMode: typeof import('@vueuse/core').useColorMode
const useConfirmDialog: typeof import('@vueuse/core').useConfirmDialog
const useCountdown: typeof import('@vueuse/core').useCountdown
const useCounter: typeof import('@vueuse/core').useCounter
const useCssModule: typeof import('vue').useCssModule
const useCssSupports: typeof import('@vueuse/core').useCssSupports
const useCssVar: typeof import('@vueuse/core').useCssVar
const useCssVars: typeof import('vue').useCssVars
const useCurrentElement: typeof import('@vueuse/core').useCurrentElement
......@@ -193,17 +218,25 @@ declare global {
const useOnline: typeof import('@vueuse/core').useOnline
const usePageLeave: typeof import('@vueuse/core').usePageLeave
const useParallax: typeof import('@vueuse/core').useParallax
const useParentElement: typeof import('@vueuse/core').useParentElement
const usePerformanceObserver: typeof import('@vueuse/core').usePerformanceObserver
const usePermission: typeof import('@vueuse/core').usePermission
const usePointer: typeof import('@vueuse/core').usePointer
const usePointerLock: typeof import('@vueuse/core').usePointerLock
const usePointerSwipe: typeof import('@vueuse/core').usePointerSwipe
const usePreferredColorScheme: typeof import('@vueuse/core').usePreferredColorScheme
const usePreferredContrast: typeof import('@vueuse/core').usePreferredContrast
const usePreferredDark: typeof import('@vueuse/core').usePreferredDark
const usePreferredLanguages: typeof import('@vueuse/core').usePreferredLanguages
const usePreferredReducedMotion: typeof import('@vueuse/core').usePreferredReducedMotion
const usePreferredReducedTransparency: typeof import('@vueuse/core').usePreferredReducedTransparency
const usePrevious: typeof import('@vueuse/core').usePrevious
const useRafFn: typeof import('@vueuse/core').useRafFn
const useRefHistory: typeof import('@vueuse/core').useRefHistory
const useResizeObserver: typeof import('@vueuse/core').useResizeObserver
const useRoute: typeof import('vue-router').useRoute
const useRouter: typeof import('vue-router').useRouter
const useSSRWidth: typeof import('@vueuse/core').useSSRWidth
const useScreenOrientation: typeof import('@vueuse/core').useScreenOrientation
const useScreenSafeArea: typeof import('@vueuse/core').useScreenSafeArea
const useScriptTag: typeof import('@vueuse/core').useScriptTag
......@@ -212,26 +245,32 @@ declare global {
const useSessionStorage: typeof import('@vueuse/core').useSessionStorage
const useShare: typeof import('@vueuse/core').useShare
const useSlots: typeof import('vue').useSlots
const useSorted: typeof import('@vueuse/core').useSorted
const useSpeechRecognition: typeof import('@vueuse/core').useSpeechRecognition
const useSpeechSynthesis: typeof import('@vueuse/core').useSpeechSynthesis
const useStepper: typeof import('@vueuse/core').useStepper
const useStorage: typeof import('@vueuse/core').useStorage
const useStorageAsync: typeof import('@vueuse/core').useStorageAsync
const useStyleTag: typeof import('@vueuse/core').useStyleTag
const useSupported: typeof import('@vueuse/core').useSupported
const useSwipe: typeof import('@vueuse/core').useSwipe
const useTemplateRef: typeof import('vue').useTemplateRef
const useTemplateRefsList: typeof import('@vueuse/core').useTemplateRefsList
const useTextDirection: typeof import('@vueuse/core').useTextDirection
const useTextSelection: typeof import('@vueuse/core').useTextSelection
const useTextareaAutosize: typeof import('@vueuse/core').useTextareaAutosize
const useThrottle: typeof import('@vueuse/core').useThrottle
const useThrottleFn: typeof import('@vueuse/core').useThrottleFn
const useThrottledRefHistory: typeof import('@vueuse/core').useThrottledRefHistory
const useTimeAgo: typeof import('@vueuse/core').useTimeAgo
const useTimeAgoIntl: typeof import('@vueuse/core').useTimeAgoIntl
const useTimeout: typeof import('@vueuse/core').useTimeout
const useTimeoutFn: typeof import('@vueuse/core').useTimeoutFn
const useTimeoutPoll: typeof import('@vueuse/core').useTimeoutPoll
const useTimestamp: typeof import('@vueuse/core').useTimestamp
const useTitle: typeof import('@vueuse/core').useTitle
const useToNumber: typeof import('@vueuse/core').useToNumber
const useToString: typeof import('@vueuse/core').useToString
const useToggle: typeof import('@vueuse/core').useToggle
const useTransition: typeof import('@vueuse/core').useTransition
const useUrlSearchParams: typeof import('@vueuse/core').useUrlSearchParams
......@@ -252,8 +291,10 @@ declare global {
const watchArray: typeof import('@vueuse/core').watchArray
const watchAtMost: typeof import('@vueuse/core').watchAtMost
const watchDebounced: typeof import('@vueuse/core').watchDebounced
const watchDeep: typeof import('@vueuse/core').watchDeep
const watchEffect: typeof import('vue').watchEffect
const watchIgnorable: typeof import('@vueuse/core').watchIgnorable
const watchImmediate: typeof import('@vueuse/core').watchImmediate
const watchOnce: typeof import('@vueuse/core').watchOnce
const watchPausable: typeof import('@vueuse/core').watchPausable
const watchPostEffect: typeof import('vue').watchPostEffect
......
差异被折叠。
......@@ -16,7 +16,8 @@
"dependencies": {
"@element-plus/icons-vue": "^2.0.4",
"@tinymce/tinymce-vue": "^5.0.0",
"axios": "^0.27.2",
"@vueuse/core": "^14.3.0",
"axios": "^1.18.1",
"blueimp-md5": "^2.19.0",
"dayjs": "^1.11.3",
"echarts": "^5.6.0",
......@@ -27,9 +28,9 @@
"qs": "^6.10.5",
"sortablejs": "^1.15.0",
"video.js": "^7.19.2",
"vue": "^3.2.37",
"vue": "^3.5.39",
"vue-echarts": "^7.0.3",
"vue-router": "^4.0.16",
"vue-router": "^4.6.4",
"xlsx": "^0.18.5"
},
"devDependencies": {
......@@ -39,9 +40,9 @@
"@types/qs": "^6.9.7",
"@types/sortablejs": "^1.13.0",
"@types/xlsx": "^0.0.35",
"@vitejs/plugin-vue": "^6.0.5",
"@vitejs/plugin-vue": "^6.0.7",
"@vue/eslint-config-typescript": "^10.0.0",
"@vue/tsconfig": "^0.9.0",
"@vue/tsconfig": "^0.9.1",
"ali-oss": "^6.17.1",
"chalk": "^5.0.1",
"eslint": "^8.16.0",
......@@ -49,8 +50,8 @@
"sass": "^1.70.0",
"typescript": "^5.9.3",
"unplugin-auto-import": "^21.0.0",
"vite": "^8.0.2",
"vite": "^8.1.4",
"vite-plugin-mkcert": "^1.17.12",
"vue-tsc": "^3.2.6"
"vue-tsc": "^3.3.7"
}
}
import type { IMenuItem } from '@/types'
import { urls } from '@/utils/env'
import {
FolderOpened,
ToiletPaper,
......@@ -63,12 +64,12 @@ export const menus: IMenuItem[] = [
{
icon: Collection,
name: '题库管理',
path: import.meta.env.VITE_QA_CENTER_URL + '/question/list?project_tag=resourse_ci',
path: urls.qaCenter + '/question/list?project_tag=resourse_ci',
},
{
icon: ToiletPaper,
name: '试卷管理',
path: import.meta.env.VITE_QA_CENTER_URL + '/paper/list?project_tag=resourse_ci',
path: urls.qaCenter + '/paper/list?project_tag=resourse_ci',
},
],
},
......
......@@ -6,6 +6,7 @@ export default { name: 'AppHeader' }
import { menus } from '@/assets/menus'
import { useUserStore } from '@/stores/user'
import type { IMenuItem } from '@/types'
import { urls } from '@/utils/env'
withDefaults(defineProps<{ hasTitle?: boolean }>(), {
hasTitle: true,
})
......@@ -18,7 +19,7 @@ const userInfo = userStore.user
const logout = async () => {
await userStore.logout()
location.href = `${import.meta.env.VITE_LOGIN_URL}?rd=${encodeURIComponent(location.href)}`
location.href = `${urls.login}?rd=${encodeURIComponent(location.href)}`
}
function genNavClassName(data: IMenuItem) {
......
......@@ -10,6 +10,13 @@ withDefaults(defineProps<{ hasBreadcrumb?: boolean }>(), {
})
const dialogVisible = ref(false)
const route = useRoute()
// 同一二级 URL 分支共享缓存;切换分支时销毁上一分支的全部页面缓存。
const cacheScope = computed(() => {
const segments = route.path.split('/').filter(Boolean)
return `/${segments.slice(0, 2).join('/')}`
})
</script>
<template>
......@@ -19,11 +26,10 @@ const dialogVisible = ref(false)
<app-breadcrumb v-if="hasBreadcrumb"></app-breadcrumb>
</div>
<div class="app-main-container">
<router-view v-slot="{ Component, route }">
<keep-alive :max="10">
<component :is="Component" v-if="route.meta.keepAlive" :key="route.path" />
<router-view v-slot="{ Component, route: currentRoute }">
<keep-alive :key="cacheScope" :max="10">
<component :is="Component" :key="currentRoute.path" />
</keep-alive>
<component :is="Component" v-if="!route.meta.keepAlive" :key="route.path" />
</router-view>
</div>
</div>
......
<script lang="ts" setup>
import { urls } from '@/utils/env'
const emit = defineEmits<Emits>()
defineProps({
......@@ -13,7 +15,7 @@ interface Emits {
const handleCancel = () => {
emit('update:isShowAnalysisDialog', false)
}
const biURL = import.meta.env.VITE_BI_URL
const biURL = urls.bi
</script>
<template>
<el-dialog :model-value="isShowAnalysisDialog" draggable :before-close="handleCancel" width="30%">
......
......@@ -6,7 +6,7 @@ export const routes: Array<RouteRecordRaw> = [
path: '/admin/teacher',
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue'), meta: { keepAlive: true } },
{ path: '', component: () => import('./views/List.vue') },
{ path: '/admin/teacher/detail', component: () => import('./views/Detail.vue'), meta: { title: '讲师详情' } },
{ path: '/admin/teacher/add', name: 'update', component: () => import('./views/Add.vue'), meta: { title: '新增/编辑讲师' } }
]
......
......@@ -6,7 +6,7 @@ export const routes: Array<RouteRecordRaw> = [
path: '/course/my',
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue'), meta: { keepAlive: true } },
{ path: '', component: () => import('./views/List.vue') },
{ path: '/course/my/view', component: () => import('./views/View.vue'), meta: { title: '课程详情' } },
// id: 章节id courseId课程id
{ path: '/course/my/view/:id/:courseId', component: () => import('./views/ViewDetails.vue'), meta: { title: '章节详情' } },
......
<script setup lang="ts">
const loginUrl = `${import.meta.env.VITE_LOGIN_URL}?rd=${encodeURIComponent(location.origin)}`
import { urls } from '@/utils/env'
const loginUrl = `${urls.login}?rd=${encodeURIComponent(location.origin)}`
</script>
<template>
......
......@@ -75,7 +75,7 @@ async function handleSetBelong() {
</script>
<template>
<div class="tool-btn-box" v-if="$route.query.id" style="margin-bottom: 20px">
<div class="tool-btn-box" v-if="route.query.id" style="margin-bottom: 20px">
<router-link v-if="props.data.auth_edit" :to="`/resource/case/update?id=${id}`">
<div class="btn-item">编辑案例信息</div>
</router-link>
......
......@@ -6,7 +6,7 @@ export const routes: Array<RouteRecordRaw> = [
path: '/resource/case',
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue'), meta: { keepAlive: true } },
{ path: '', component: () => import('./views/List.vue') },
{ path: '/resource/case/update', component: () => import('./views/Update.vue'), meta: { title: '新建/编辑案例' } },
{ path: '/resource/case/view', component: () => import('./views/View.vue'), meta: { title: '案例详情' } },
],
......
......@@ -124,7 +124,7 @@ const handlesetBelong = () => {
</script>
<template>
<div class="tool-btn-box" v-if="$route.query.id" style="margin-bottom: 20px">
<div class="tool-btn-box" v-if="route.query.id" style="margin-bottom: 20px">
<template v-if="props.data.auth_edit">
<router-link v-permission="'v1-resource-courseware-update'" :to="`/resource/courseware/update?id=${id}`">
<div class="btn-item">编辑课件信息</div>
......
......@@ -6,7 +6,7 @@ export const routes: Array<RouteRecordRaw> = [
path: '/resource/courseware',
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue'), meta: { keepAlive: true } },
{ path: '', component: () => import('./views/List.vue') },
{ path: '/resource/courseware/update', component: () => import('./views/Update.vue'), meta: { title: '新建/编辑课件' } },
{ path: '/resource/courseware/view', component: () => import('./views/View.vue'), meta: { title: '课件详情' } }
// { path: 'update/:id', component: () => import('./views/Update.vue'), props: true }
......
......@@ -124,7 +124,7 @@ const handlesetBelong = () => {
</script>
<template>
<div class="tool-btn-box" v-if="$route.query.id" style="margin-bottom: 20px">
<div class="tool-btn-box" v-if="route.query.id" style="margin-bottom: 20px">
<template v-if="props.data.auth_edit">
<router-link v-permission="'v1-resource-lesson-plan-update'" :to="`/resource/lessonplan/update?id=${id}`">
<div class="btn-item">编辑教案信息</div>
......
......@@ -6,7 +6,7 @@ export const routes: Array<RouteRecordRaw> = [
path: '/resource/lessonplan',
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue'), meta: { keepAlive: true } },
{ path: '', component: () => import('./views/List.vue') },
{ path: '/resource/lessonplan/update', component: () => import('./views/Update.vue'), meta: { title: '新建/编辑教案' } },
{ path: '/resource/lessonplan/view', component: () => import('./views/View.vue'), meta: { title: '教案详情' } }
// { path: 'update/:id', component: () => import('./views/Update.vue'), props: true }
......
......@@ -4,6 +4,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
import { useProjectList } from '@/composables/useGetProjectList'
const router = useRouter()
const route = useRoute()
const props = defineProps(['data'])
......@@ -122,7 +123,7 @@ const handlesetBelong = () => {
</script>
<template>
<div class="tool-btn-box" v-if="$route.query.id" style="margin-bottom: 20px">
<div class="tool-btn-box" v-if="route.query.id" style="margin-bottom: 20px">
<template v-if="props.data.auth_edit">
<router-link v-permission="'v1-resource-other-information-update'" :to="`/resource/other/update?id=${id}`">
<div class="btn-item">编辑其他资料信息</div>
......
......@@ -6,7 +6,7 @@ export const routes: Array<RouteRecordRaw> = [
path: '/resource/other',
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue'), meta: { keepAlive: true } },
{ path: '', component: () => import('./views/List.vue') },
{ path: '/resource/other/update', component: () => import('./views/Update.vue'), meta: { title: '新建/编辑其他资料' } },
{ path: '/resource/other/view', component: () => import('./views/View.vue'), meta: { title: '其他资料详情' } }
// { path: 'update/:id', component: () => import('./views/Update.vue'), props: true }
......
......@@ -123,7 +123,7 @@ const handlesetBelong = () => {
</script>
<template>
<div class="tool-btn-box" v-if="$route.query.id" style="margin-bottom: 20px">
<div class="tool-btn-box" v-if="route.query.id" style="margin-bottom: 20px">
<template v-if="props.data.auth_edit">
<router-link :to="`/resource/video/update?id=${id}`">
<div class="btn-item">编辑视频信息</div>
......
......@@ -6,7 +6,7 @@ export const routes: Array<RouteRecordRaw> = [
path: '/resource/video',
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue'), meta: { keepAlive: true } },
{ path: '', component: () => import('./views/List.vue') },
{ path: 'update', component: () => import('./views/Update.vue'), meta: { title: '新建/编辑视频' } },
{ path: 'view', component: () => import('./views/View.vue'), meta: { title: '视频详情' } },
{ path: 'edit-courseware', component: () => import('./views/EditCourseware.vue'), meta: { title: '编辑视频课件' } },
......
......@@ -6,7 +6,7 @@ export const routes: Array<RouteRecordRaw> = [
path: '/system/dictionary',
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue'), meta: { keepAlive: true } },
{ path: '', component: () => import('./views/List.vue') },
{ path: '/system/dictionary/rowList', component: () => import('./views/rowList.vue'), meta: { title: '字典项管理' } }
]
}
......
......@@ -6,8 +6,8 @@ export const routes: Array<RouteRecordRaw> = [
path: '/teach/exam',
component: AppLayout,
children: [
{ path: '/teach/exam', component: () => import('./views/List.vue'), meta: { keepAlive: true } },
{ path: '/teach/stuList', component: () => import('./views/StudentList.vue'), meta: { keepAlive: true, title: '学生列表', menuPath: '/teach/exam' } },
{ path: '/teach/exam', component: () => import('./views/List.vue') },
{ path: '/teach/stuList', component: () => import('./views/StudentList.vue'), meta: { title: '学生列表', menuPath: '/teach/exam' } },
{ path: '/teach/view', component: () => import('./views/View.vue'), meta: { title: '试卷详情', menuPath: '/teach/exam' } }
]
}
......
......@@ -6,7 +6,7 @@ export const routes: Array<RouteRecordRaw> = [
path: '/teach/posts',
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue'), meta: { keepAlive: true } },
{ path: '', component: () => import('./views/List.vue') },
{ path: '/teach/posts/detail', component: () => import('./views/View.vue'), meta: { title: '帖子详情' } }
]
}
......
......@@ -2,6 +2,7 @@ import axios from 'axios'
import qs from 'qs'
import { ElMessage } from 'element-plus'
import router from '@/router'
import { urls } from '@/utils/env'
const httpRequest = axios.create({
timeout: 60000,
......@@ -36,7 +37,7 @@ httpRequest.interceptors.response.use(
const { data } = response
// 未登录
if (data.code === 4001) {
location.href = `${import.meta.env.VITE_LOGIN_URL}?rd=${encodeURIComponent(location.href)}`
location.href = `${urls.login}?rd=${encodeURIComponent(location.href)}`
return Promise.reject(data)
}
if (data.code === 1) {
......@@ -58,7 +59,7 @@ httpRequest.interceptors.response.use(
const { status, message } = error.response.data
// 未登录
if (status === 403) {
location.href = `${import.meta.env.VITE_LOGIN_URL}?rd=${encodeURIComponent(location.href)}`
location.href = `${urls.login}?rd=${encodeURIComponent(location.href)}`
} else if (status === 402) {
// 未授权
router.push('/401')
......
/**
* 学校本地部署时,各服务与前端使用同一主机、固定端口。
* school 模式从浏览器地址栏读取主机,其他模式继续使用环境变量。
*/
const schoolHost = import.meta.env.MODE === 'school' ? window.location.hostname : ''
export const urls = {
login: schoolHost ? `http://${schoolHost}:1001/auth/login/index` : import.meta.env.VITE_LOGIN_URL,
qaCenter: schoolHost ? `http://${schoolHost}:1004` : import.meta.env.VITE_QA_CENTER_URL,
bi: schoolHost ? `http://${schoolHost}:1012` : import.meta.env.VITE_BI_URL,
filePreview: schoolHost ? `http://${schoolHost}:8012` : import.meta.env.VITE_FILE_PREVIEW_URL,
}
import { Base64 } from 'js-base64'
import { urls } from './env'
export function getOnlinePreviewUrl(url: string) {
return import.meta.env.MODE === 'school'
? `${import.meta.env.VITE_FILE_PREVIEW_URL}/onlinePreview?url=${encodeURIComponent(Base64.encode(url))}`
? `${urls.filePreview}/onlinePreview?url=${encodeURIComponent(Base64.encode(url))}`
: `https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}`
}
......
......@@ -16,16 +16,16 @@ export default defineConfig(({ mode }) => ({
open: true,
host: 'dev.ezijing.com',
proxy: {
'/api/resource': {
target: 'http://localhost:20082',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/resource/, ''),
},
'/api/lab': {
target: 'http://localhost:20081',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/lab/, ''),
},
// '/api/resource': {
// target: 'http://localhost:20082',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api\/resource/, ''),
// },
// '/api/lab': {
// target: 'http://localhost:20081',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api\/lab/, ''),
// },
'/api': 'https://resource-center.ezijing.com',
},
},
......
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论