提交 f00e730f authored 作者: lihuihui's avatar lihuihui

On master: 暂存

{
"globals": {
"$": true,
"$$": true,
"$computed": true,
"$customRef": true,
"$ref": true,
"$shallowRef": true,
"$toRef": true,
"EffectScope": true,
"asyncComputed": true,
"autoResetRef": true,
"computed": true,
"computedAsync": true,
"computedEager": true,
"computedInject": true,
"computedWithControl": true,
"controlledComputed": true,
"controlledRef": true,
"createApp": true,
"createEventHook": true,
"createGlobalState": true,
"createInjectionState": true,
"createReactiveFn": true,
"createSharedComposable": true,
"createUnrefFn": true,
"customRef": true,
"debouncedRef": true,
"debouncedWatch": true,
"defineAsyncComponent": true,
"defineComponent": true,
"eagerComputed": true,
"effectScope": true,
"extendRef": true,
"getCurrentInstance": true,
"getCurrentScope": true,
"h": true,
"ignorableWatch": true,
"inject": true,
"isDefined": true,
"isReadonly": true,
"isRef": true,
"logicAnd": true,
"logicNot": true,
"logicOr": true,
"makeDestructurable": true,
"markRaw": true,
"nextTick": true,
"onActivated": true,
"onBeforeMount": true,
"onBeforeUnmount": true,
"onBeforeUpdate": true,
"onClickOutside": true,
"onDeactivated": true,
"onErrorCaptured": true,
"onKeyStroke": true,
"onLongPress": true,
"onMounted": true,
"onRenderTracked": true,
"onRenderTriggered": true,
"onScopeDispose": true,
"onServerPrefetch": true,
"onStartTyping": true,
"onUnmounted": true,
"onUpdated": true,
"pausableWatch": true,
"provide": true,
"reactify": true,
"reactifyObject": true,
"reactive": true,
"reactiveComputed": true,
"reactiveOmit": true,
"reactivePick": true,
"readonly": true,
"ref": true,
"refAutoReset": true,
"refDebounced": true,
"refDefault": true,
"refThrottled": true,
"refWithControl": true,
"resolveComponent": true,
"shallowReactive": true,
"shallowReadonly": true,
"shallowRef": true,
"syncRef": true,
"syncRefs": true,
"templateRef": true,
"throttledRef": true,
"throttledWatch": true,
"toRaw": true,
"toReactive": true,
"toRef": true,
"toRefs": true,
"triggerRef": true,
"tryOnBeforeMount": true,
"tryOnBeforeUnmount": true,
"tryOnMounted": true,
"tryOnScopeDispose": true,
"tryOnUnmounted": true,
"unref": true,
"unrefElement": true,
"until": true,
"useActiveElement": true,
"useAsyncQueue": true,
"useAsyncState": true,
"useAttrs": true,
"useBase64": true,
"useBattery": true,
"useBreakpoints": true,
"useBroadcastChannel": true,
"useBrowserLocation": true,
"useCached": true,
"useClamp": true,
"useClipboard": true,
"useColorMode": true,
"useConfirmDialog": true,
"useCounter": true,
"useCssModule": true,
"useCssVar": true,
"useCssVars": true,
"useCurrentElement": true,
"useCycleList": true,
"useDark": true,
"useDateFormat": true,
"useDebounce": true,
"useDebounceFn": true,
"useDebouncedRefHistory": true,
"useDeviceMotion": true,
"useDeviceOrientation": true,
"useDevicePixelRatio": true,
"useDevicesList": true,
"useDisplayMedia": true,
"useDocumentVisibility": true,
"useDraggable": true,
"useElementBounding": true,
"useElementByPoint": true,
"useElementHover": true,
"useElementSize": true,
"useElementVisibility": true,
"useEventBus": true,
"useEventListener": true,
"useEventSource": true,
"useEyeDropper": true,
"useFavicon": true,
"useFetch": true,
"useFileSystemAccess": true,
"useFocus": true,
"useFocusWithin": true,
"useFps": true,
"useFullscreen": true,
"useGamepad": true,
"useGeolocation": true,
"useIdle": true,
"useInfiniteScroll": true,
"useIntersectionObserver": true,
"useInterval": true,
"useIntervalFn": true,
"useKeyModifier": true,
"useLastChanged": true,
"useLocalStorage": true,
"useMagicKeys": true,
"useManualRefHistory": true,
"useMediaControls": true,
"useMediaQuery": true,
"useMemoize": true,
"useMemory": true,
"useMounted": true,
"useMouse": true,
"useMouseInElement": true,
"useMousePressed": true,
"useMutationObserver": true,
"useNavigatorLanguage": true,
"useNetwork": true,
"useNow": true,
"useOffsetPagination": true,
"useOnline": true,
"usePageLeave": true,
"useParallax": true,
"usePermission": true,
"usePointer": true,
"usePointerSwipe": true,
"usePreferredColorScheme": true,
"usePreferredDark": true,
"usePreferredLanguages": true,
"useRafFn": true,
"useRefHistory": true,
"useResizeObserver": true,
"useRoute": true,
"useRouter": true,
"useScreenOrientation": true,
"useScreenSafeArea": true,
"useScriptTag": true,
"useScroll": true,
"useScrollLock": true,
"useSessionStorage": true,
"useShare": true,
"useSlots": true,
"useSpeechRecognition": true,
"useSpeechSynthesis": true,
"useStorage": true,
"useStorageAsync": true,
"useStyleTag": true,
"useSwipe": true,
"useTemplateRefsList": true,
"useTextSelection": true,
"useThrottle": true,
"useThrottleFn": true,
"useThrottledRefHistory": true,
"useTimeAgo": true,
"useTimeout": true,
"useTimeoutFn": true,
"useTimeoutPoll": true,
"useTimestamp": true,
"useTitle": true,
"useToggle": true,
"useTransition": true,
"useUrlSearchParams": true,
"useUserMedia": true,
"useVModel": true,
"useVModels": true,
"useVibrate": true,
"useVirtualList": true,
"useWakeLock": true,
"useWebNotification": true,
"useWebSocket": true,
"useWebWorker": true,
"useWebWorkerFn": true,
"useWindowFocus": true,
"useWindowScroll": true,
"useWindowSize": true,
"watch": true,
"watchAtMost": true,
"watchDebounced": true,
"watchEffect": true,
"watchIgnorable": true,
"watchOnce": true,
"watchPausable": true,
"watchThrottled": true,
"watchWithFilter": true,
"whenever": true
}
}
\ No newline at end of file
// Generated by 'unplugin-auto-import'
export {}
declare global {
const $$: typeof import('vue/macros')['$$']
const $: typeof import('vue/macros')['$']
const $computed: typeof import('vue/macros')['$computed']
const $customRef: typeof import('vue/macros')['$customRef']
const $ref: typeof import('vue/macros')['$ref']
const $shallowRef: typeof import('vue/macros')['$shallowRef']
const $toRef: typeof import('vue/macros')['$toRef']
const EffectScope: typeof import('vue')['EffectScope']
const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
const computed: typeof import('vue')['computed']
const computedAsync: typeof import('@vueuse/core')['computedAsync']
const computedEager: typeof import('@vueuse/core')['computedEager']
const computedInject: typeof import('@vueuse/core')['computedInject']
const computedWithControl: typeof import('@vueuse/core')['computedWithControl']
const controlledComputed: typeof import('@vueuse/core')['controlledComputed']
const controlledRef: typeof import('@vueuse/core')['controlledRef']
const createApp: typeof import('vue')['createApp']
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 createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
const customRef: typeof import('vue')['customRef']
const debouncedRef: typeof import('@vueuse/core')['debouncedRef']
const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch']
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
const defineComponent: typeof import('vue')['defineComponent']
const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
const effectScope: typeof import('vue')['effectScope']
const extendRef: typeof import('@vueuse/core')['extendRef']
const getCurrentInstance: typeof import('vue')['getCurrentInstance']
const getCurrentScope: typeof import('vue')['getCurrentScope']
const h: typeof import('vue')['h']
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
const inject: typeof import('vue')['inject']
const isDefined: typeof import('@vueuse/core')['isDefined']
const isReadonly: typeof import('vue')['isReadonly']
const isRef: typeof import('vue')['isRef']
const logicAnd: typeof import('@vueuse/core')['logicAnd']
const logicNot: typeof import('@vueuse/core')['logicNot']
const logicOr: typeof import('@vueuse/core')['logicOr']
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
const markRaw: typeof import('vue')['markRaw']
const nextTick: typeof import('vue')['nextTick']
const onActivated: typeof import('vue')['onActivated']
const onBeforeMount: typeof import('vue')['onBeforeMount']
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
const onClickOutside: typeof import('@vueuse/core')['onClickOutside']
const onDeactivated: typeof import('vue')['onDeactivated']
const onErrorCaptured: typeof import('vue')['onErrorCaptured']
const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke']
const onLongPress: typeof import('@vueuse/core')['onLongPress']
const onMounted: typeof import('vue')['onMounted']
const onRenderTracked: typeof import('vue')['onRenderTracked']
const onRenderTriggered: typeof import('vue')['onRenderTriggered']
const onScopeDispose: typeof import('vue')['onScopeDispose']
const onServerPrefetch: typeof import('vue')['onServerPrefetch']
const onStartTyping: typeof import('@vueuse/core')['onStartTyping']
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
const provide: typeof import('vue')['provide']
const reactify: typeof import('@vueuse/core')['reactify']
const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
const reactive: typeof import('vue')['reactive']
const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed']
const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit']
const reactivePick: typeof import('@vueuse/core')['reactivePick']
const readonly: typeof import('vue')['readonly']
const ref: typeof import('vue')['ref']
const refAutoReset: typeof import('@vueuse/core')['refAutoReset']
const refDebounced: typeof import('@vueuse/core')['refDebounced']
const refDefault: typeof import('@vueuse/core')['refDefault']
const refThrottled: typeof import('@vueuse/core')['refThrottled']
const refWithControl: typeof import('@vueuse/core')['refWithControl']
const resolveComponent: typeof import('vue')['resolveComponent']
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const syncRef: typeof import('@vueuse/core')['syncRef']
const syncRefs: typeof import('@vueuse/core')['syncRefs']
const templateRef: typeof import('@vueuse/core')['templateRef']
const throttledRef: typeof import('@vueuse/core')['throttledRef']
const throttledWatch: typeof import('@vueuse/core')['throttledWatch']
const toRaw: typeof import('vue')['toRaw']
const toReactive: typeof import('@vueuse/core')['toReactive']
const toRef: typeof import('vue')['toRef']
const toRefs: typeof import('vue')['toRefs']
const triggerRef: typeof import('vue')['triggerRef']
const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted']
const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose']
const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted']
const unref: typeof import('vue')['unref']
const unrefElement: typeof import('@vueuse/core')['unrefElement']
const until: typeof import('@vueuse/core')['until']
const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
const useAttrs: typeof import('vue')['useAttrs']
const useBase64: typeof import('@vueuse/core')['useBase64']
const useBattery: typeof import('@vueuse/core')['useBattery']
const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints']
const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel']
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
const useCached: typeof import('@vueuse/core')['useCached']
const useClamp: typeof import('@vueuse/core')['useClamp']
const useClipboard: typeof import('@vueuse/core')['useClipboard']
const useColorMode: typeof import('@vueuse/core')['useColorMode']
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
const useCounter: typeof import('@vueuse/core')['useCounter']
const useCssModule: typeof import('vue')['useCssModule']
const useCssVar: typeof import('@vueuse/core')['useCssVar']
const useCssVars: typeof import('vue')['useCssVars']
const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement']
const useCycleList: typeof import('@vueuse/core')['useCycleList']
const useDark: typeof import('@vueuse/core')['useDark']
const useDateFormat: typeof import('@vueuse/core')['useDateFormat']
const useDebounce: typeof import('@vueuse/core')['useDebounce']
const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn']
const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory']
const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion']
const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation']
const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio']
const useDevicesList: typeof import('@vueuse/core')['useDevicesList']
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
const useDraggable: typeof import('@vueuse/core')['useDraggable']
const useElementBounding: typeof import('@vueuse/core')['useElementBounding']
const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint']
const useElementHover: typeof import('@vueuse/core')['useElementHover']
const useElementSize: typeof import('@vueuse/core')['useElementSize']
const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility']
const useEventBus: typeof import('@vueuse/core')['useEventBus']
const useEventListener: typeof import('@vueuse/core')['useEventListener']
const useEventSource: typeof import('@vueuse/core')['useEventSource']
const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper']
const useFavicon: typeof import('@vueuse/core')['useFavicon']
const useFetch: typeof import('@vueuse/core')['useFetch']
const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess']
const useFocus: typeof import('@vueuse/core')['useFocus']
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
const useFps: typeof import('@vueuse/core')['useFps']
const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
const useGamepad: typeof import('@vueuse/core')['useGamepad']
const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
const useIdle: typeof import('@vueuse/core')['useIdle']
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver']
const useInterval: typeof import('@vueuse/core')['useInterval']
const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn']
const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier']
const useLastChanged: typeof import('@vueuse/core')['useLastChanged']
const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage']
const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys']
const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory']
const useMediaControls: typeof import('@vueuse/core')['useMediaControls']
const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery']
const useMemoize: typeof import('@vueuse/core')['useMemoize']
const useMemory: typeof import('@vueuse/core')['useMemory']
const useMounted: typeof import('@vueuse/core')['useMounted']
const useMouse: typeof import('@vueuse/core')['useMouse']
const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement']
const useMousePressed: typeof import('@vueuse/core')['useMousePressed']
const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver']
const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage']
const useNetwork: typeof import('@vueuse/core')['useNetwork']
const useNow: typeof import('@vueuse/core')['useNow']
const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination']
const useOnline: typeof import('@vueuse/core')['useOnline']
const usePageLeave: typeof import('@vueuse/core')['usePageLeave']
const useParallax: typeof import('@vueuse/core')['useParallax']
const usePermission: typeof import('@vueuse/core')['usePermission']
const usePointer: typeof import('@vueuse/core')['usePointer']
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
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 useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation']
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
const useScriptTag: typeof import('@vueuse/core')['useScriptTag']
const useScroll: typeof import('@vueuse/core')['useScroll']
const useScrollLock: typeof import('@vueuse/core')['useScrollLock']
const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage']
const useShare: typeof import('@vueuse/core')['useShare']
const useSlots: typeof import('vue')['useSlots']
const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition']
const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis']
const useStorage: typeof import('@vueuse/core')['useStorage']
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
const useSwipe: typeof import('@vueuse/core')['useSwipe']
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
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 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 useToggle: typeof import('@vueuse/core')['useToggle']
const useTransition: typeof import('@vueuse/core')['useTransition']
const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams']
const useUserMedia: typeof import('@vueuse/core')['useUserMedia']
const useVModel: typeof import('@vueuse/core')['useVModel']
const useVModels: typeof import('@vueuse/core')['useVModels']
const useVibrate: typeof import('@vueuse/core')['useVibrate']
const useVirtualList: typeof import('@vueuse/core')['useVirtualList']
const useWakeLock: typeof import('@vueuse/core')['useWakeLock']
const useWebNotification: typeof import('@vueuse/core')['useWebNotification']
const useWebSocket: typeof import('@vueuse/core')['useWebSocket']
const useWebWorker: typeof import('@vueuse/core')['useWebWorker']
const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn']
const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus']
const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll']
const useWindowSize: typeof import('@vueuse/core')['useWindowSize']
const watch: typeof import('vue')['watch']
const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
const watchDebounced: typeof import('@vueuse/core')['watchDebounced']
const watchEffect: typeof import('vue')['watchEffect']
const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable']
const watchOnce: typeof import('@vueuse/core')['watchOnce']
const watchPausable: typeof import('@vueuse/core')['watchPausable']
const watchThrottled: typeof import('@vueuse/core')['watchThrottled']
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
const whenever: typeof import('@vueuse/core')['whenever']
}
......@@ -6,6 +6,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>统一资源管理平台</title>
<script src="https://webapp-pub.ezijing.com/plugins/tinymce@6/tinymce.min.js"></script>
<script src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/lib/aliyun-upload-sdk/lib/es6-promise.min.js"></script>
<script src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/lib/aliyun-upload-sdk/lib/aliyun-oss-sdk-6.17.1.min.js"></script>
<script src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/lib/aliyun-upload-sdk/aliyun-upload-sdk-1.5.3.min.js"></script>
</head>
<body>
<div id="app"></div>
......
......@@ -34,3 +34,18 @@ export function uploadFile(data: Record<string, any>) {
export function deleteComment(data: { id: string }) {
return httpRequest.post('/api/psp/backend/comment/delete', data)
}
// 上传视频
export function getCreateAuth(data: { title: string, file_name: string }) {
return httpRequest.post('/api/resource/v1/resource/video/create-auth', data)
}
// 刷新上传视频的地址凭证
export function updateAuth(data: { source_id: string }) {
return httpRequest.post('/api/resource/v1/resource/video/create-auth', data)
}
// 获取公共字典列表
export function getMapList() {
return httpRequest.get('/api/resource/v1/util/get-data-dictionary-list')
}
<script setup lang="ts">
import { Files } from '@element-plus/icons-vue'
</script>
<template>
<div class="card-item">
<div class="card-item-top">
<!-- <div class="title">基金产品(中)(初级)</div> -->
<!-- <img src="http://iph.href.lu/265x170" /> -->
<div class="title">基金产品(中)(初级)</div>
<div class="item-info">
<div class="info">文件大小:1MB</div>
<div class="info">文件大小:1MB</div>
<div class="info">学习人次:165人次</div>
</div>
<el-icon class="item-info-icon">
<Files />
</el-icon>
<div class="tool-pop-btn">
<div class="edit-btn">编辑</div>
<div class="view-btn">查看</div>
</div>
</div>
<div class="card-item-bottom">
<div class="item-t">
<div class="text">张三丰/紫荆教育</div>
<div class="tag green">失效</div>
</div>
<div class="item-b">
<div class="time">2022-03-21 12:34:21</div>
<div class="tag">新建</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.card-item {
width: 265px;
border-radius: 6px;
overflow: hidden;
margin-right: 20px;
margin-bottom: 20px;
// box-shadow: #666666;
box-shadow: 0 0 10px 0 rgb(0 0 0 / 10%);
background: #fff;
.card-item-top {
background: rgba(204,204,204, .5);
height: 170px;
position: relative;
display: flex;
align-items: center;
&:hover {
.tool-pop-btn {
opacity: 1;
}
}
.item-info{
padding-left: 20px;
.info{
width: 150px;
font-size: 14px;
line-height: 100%;
color: #666666;
margin-bottom: 10px;
}
}
.item-info-icon{
font-size: 50px;
color: #aa1941;
}
img {
width: 100%;
height: 100%;
display: block;
}
.title {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
line-height: 37px;
background: rgba(0, 0, 0, .6);
font-size: 18px;
color: #ffffff;
padding-left: 16px;
box-sizing: border-box;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
}
.tool-pop-btn {
transition: all .5s;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
opacity: 0;
.edit-btn{
width: 113px;
line-height: 32px;
border: 1px solid #D3D3D3;
border-radius: 18px;
text-align: center;
font-size: 14px;
color: #FFFFFF;
margin: 52px auto 12px;
cursor: pointer;
}
.view-btn{
width: 113px;
line-height: 32px;
background: #AA1941;
border-radius: 18px;
text-align: center;
font-size: 14px;
color: #FFFFFF;
margin: 0 auto;
cursor: pointer;
}
}
}
}
.card-item-bottom{
background: #fff;
padding: 20px 16px 30px;
.item-t{
display: flex;
align-items: center;
justify-content: space-between;
.text{
width: 150px;
font-size: 16px;
line-height: 100%;
color: #666666;
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis;
}
.tag{
width: 48px;
line-height: 22px;
background: #AA1941;
border-radius: 11px;
font-size: 14px;
color: #fff;
text-align: center;
&.green{
background: #1AB226;
}
}
}
.item-b{
margin-top: 18px;
display: flex;
align-items: center;
justify-content: space-between;
.time{
font-size: 14px;
line-height: 100%;
color: #999999;
}
.tag{
font-size: 16px;
line-height: 100%;
color: #999999;
}
}
}
</style>
\ No newline at end of file
<script setup lang="ts">
import { getCreateAuth, updateAuth } from '@/api/base'
/**
* upload 上传状态 {code: 0(成功) 1(开始上传) 2(上传失败), msg: '上传信息'}
* progress 上传进度
**/
const emit = defineEmits(['upload', 'progress'])
const form:any = reactive({
timeout: '',
partSize: '',
parallel: '',
retryCount: '',
retryDuration: '',
region: 'cn-shanghai',
userId: '1303984639806000',
file: null,
authProgress: 0,
uploader: null,
statusText: ''
})
const fileChange = (e:any) => {
form.file = e.target.files[0]
var userData = '{"Vod":{}}'
if (form.uploader) {
form.uploader.stopUpload()
form.authProgress = 0
form.statusText = ""
}
form.uploader = createUploader()
form.uploader.addFile(form.file, null, null, null, userData)
form.uploader.startUpload()
}
const createUploader:any = () => {
const w = window as any
const uploader = new w.AliyunUpload.Vod({
timeout: form.timeout || 60000,
partSize: form.partSize || 1048576,
parallel: form.parallel || 5,
retryCount: form.retryCount || 3,
retryDuration: form.retryDuration || 2,
region: form.region,
userId: form.userId,
// 开始上传
onUploadstarted: function (uploadInfo:any) {
const fileData = JSON.parse(window.localStorage.fileData || '{}')
// 判断有没有上传过
const isFile = !!fileData.sourceId
if (!isFile) {
// 没上传过请求凭证上传
getCreateAuth({ title: uploadInfo.file.name, file_name: uploadInfo.file.name }).then((data: any) => {
window.localStorage.fileData = JSON.stringify({
uploadAuth: data.data.upload_auth,
uploadAddress: data.data.upload_address,
videoId: data.data.source_id,
fileName: uploadInfo.file.name,
fileSize: uploadInfo.file.size
})
uploader.setUploadAuthAndAddress(uploadInfo, data.data.upload_auth, data.data.upload_address, data.data.source_id)
})
} else {
// 上传过判断一下上次上传的文件和本次上传的文件一不一样,一样的话继续上传
if (fileData.fileName === uploadInfo.file.name && fileData.fileSize === uploadInfo.file.size) {
uploader.setUploadAuthAndAddress(uploadInfo, fileData.uploadAuth, fileData.uploadAddress, fileData.videoId)
} else {
getCreateAuth({ title: uploadInfo.file.name, file_name: uploadInfo.file.name }).then((data: any) => {
uploader.setUploadAuthAndAddress(uploadInfo, data.data.upload_auth, data.data.upload_address, data.data.source_id)
})
}
}
const res = {
code: 1,
name: uploadInfo.file.name,
msg: '开始上传'
}
emit('upload', res)
},
// 文件上传成功
onUploadSucceed: function (uploadInfo:any) {
// console.log("onUploadSucceed: " + uploadInfo.file.name + ", endpoint:" + uploadInfo.endpoint + ", bucket:" + uploadInfo.bucket + ", object:" + uploadInfo.object)
const fileData = window.localStorage.fileData ? JSON.parse(window.localStorage.fileData) : {}
const res = {
code: 0,
name: uploadInfo.file.name,
videoId: fileData.videoId,
msg: '上传成功'
}
emit('upload', res)
},
// 文件上传失败
onUploadFailed: function (uploadInfo:any, code:any, message:any) {
console.log("onUploadFailed: file:" + uploadInfo.file.name + ",code:" + code + ", message:" + message)
const res = {
code: 2,
name: uploadInfo.file.name,
msg: '文件上传失败'
}
emit('upload', res)
},
// 文件上传进度,单位:字节, 可以在这个函数中拿到上传进度并显示在页面上
onUploadProgress: function (uploadInfo:any, totalSize:any, progress:any) {
let progressPercent = Math.ceil(progress * 100)
form.authProgress = progressPercent
emit('progress', form.authProgress)
},
// 上传凭证超时
onUploadTokenExpired: function (uploadInfo:any) {
const fileData = JSON.parse(window.localStorage.fileData || '{}')
updateAuth({ source_id: fileData.videoId }).then(({ data }) => {
let uploadAuth = data.UploadAuth
window.localStorage.fileData = JSON.stringify({
uploadAuth: data.data.upload_auth,
uploadAddress: data.data.upload_address,
videoId: data.data.source_id,
fileName: uploadInfo.file.name,
fileSize: uploadInfo.file.size
})
uploader.resumeUploadWithAuth(uploadAuth)
})
},
// 全部文件上传结束
onUploadEnd: function (uploadInfo: any) {
console.log(uploadInfo, '上传完成')
// console.log("onUploadEnd: uploaded all the files")
}
})
return uploader
}
</script>
<template>
<input type="file" id="fileUpload" @change="fileChange($event)">
</template>
<style lang="scss" scoped>
#fileUpload{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.00001;
}
</style>
\ No newline at end of file
import httpRequest from '@/utils/axios'
// 获取视频列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/psp/backend/video/index', { params })
}
// 创建视频
export function createVideo(data: { course_name: string; cover_page: string; type: string; weight?: string }) {
return httpRequest.post('/api/psp/backend/video/create', data)
}
// 更新视频
export function updateVideo(data: { id: string; course_name: string; cover_page: string; type: string; weight?: string }) {
return httpRequest.post('/api/psp/backend/video/update', data)
}
// 获取视频详情
export function getVideo(params: { id: string }) {
return httpRequest.get('/api/psp/backend/video/view', { params })
}
<script setup lang="ts">
import * as echarts from "echarts"
const echartsRef = ref()
onMounted(() => {
const myEcharts = echarts.init(echartsRef.value)
const option = {
grid: {
bottom: 30,
left: 30,
right: 30
},
xAxis: {
data: ['2022-02-21', '2022-02-21', '2022-02-21', '2022-02-21', '2022-02-21', '2022-02-21'],
axisTick: {
show: false
}
},
color: ['#BF9D6B'],
yAxis: {},
series: [
{
type: 'bar',
barWidth: '18',
data: [5, 20, 36, 10, 10, 20]
}
],
}
//设置配置
myEcharts.setOption(option)
})
const listOptions = {
columns: [
{ label: '访问时间', prop: 'name', align: 'center' },
{ label: '姓名', prop: 'bumen', align: 'center' },
{ label: '所在项目', prop: 'update', align: 'center' },
{ label: '访问时长', prop: 'time', align: 'center' }
],
data: [
{ time: '111', id: 1, name: '宏观经济学.pptx', type: '1', index: '1', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
{ time: '111', id: 2, name: '宏观经济学.pptx', type: '2', index: '2', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
{ time: '111', id: 3, name: '宏观经济学.pptx', type: '3', index: '3', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
{ time: '111', id: 4, name: '宏观经济学.pptx', type: '4', index: '4', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
]
}
</script>
<template>
<div class="data-box">
<div class="echart">
<div class="name">访问量/关联量一周走势图</div>
<div
class="echarts"
ref="echartsRef"
:style="{
width: '600px',
height: '300px'
}"
></div>
</div>
<div class="label-box">
<div class="name">最近访问</div>
<AppList v-bind="listOptions" ref="appList" stripe></AppList>
</div>
</div>
<!-- <div
class="echarts"
ref="echartsRef"
:style="{
width: '600px',
height: '300px'
}"
></div> -->
</template>
<style lang="scss" scoped>
.data-box{
display: flex;
.echart{
flex: 1;
height: 369px;
box-sizing: border-box;
border: 1px solid #E0E0E0;
border-radius: 10px;
margin-right: 10px;
padding: 20px;
.name{
font-size: 16px;
line-height: 100%;
color: #333333;
}
}
.label-box{
box-sizing: border-box;
flex: 1;
height: 369px;
border: 1px solid #E0E0E0;
border-radius: 10px;
margin-left: 10px;
padding: 20px;
.name{
font-size: 16px;
line-height: 100%;
color: #333333;
}
}
}
</style>
<script setup lang="ts">
</script>
<template>
<div class="center-video-box">
<div class="file-box">
<embed width="812" height="433" src="https://vocational-store.oss-cn-beijing.aliyuncs.com/files/20210604/7b1bfdec10354da769461199acf55176.pdf">
</div>
<!-- <video width="812" height="433" controls>
<source src="https://video.shipin520.com/videos/17/36/71/b_KSyZ5ujXfz7R1567173671.mp4" type="video/mp4">
</video> -->
<div class="right-statistics">
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon1.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">使用项目/学校</div>
</div>
</div>
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon2.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">使用课程</div>
</div>
</div>
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon3.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">累计学习人次</div>
</div>
</div>
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon4.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">累计学习时长</div>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.center-video-box{
padding: 20px 0;
display: flex;
.right-statistics{
flex: 1;
padding-top: 15px;
.stat-item{
width: 210px;
height: 85px;
background: #B41E47;
border-radius: 6px;
display: flex;
align-items: center;
margin: 0 auto 20px;
&:nth-child(even){
background: #BF9D6B;
}
img{
width: 52px;
height: 52px;
display: block;
margin-left: 18px;
}
.content{
margin-left: 18px;
.unit{
font-size: 26px;
line-height: 100%;
color: #FFFFFF;
span{
font-size: 12px;
line-height: 100%;
}
}
.tag{
font-size: 14px;
line-height: 100%;
color: #FFFFFF;
margin-top: 10px;
}
}
}
}
}
</style>
<script setup lang="ts">
import { Files } from '@element-plus/icons-vue'
</script>
<template>
<div class="video-info">
<div class="video-img">
<el-icon class="item-info-icon">
<Files />
</el-icon>
<!-- <img src="https://iph.href.lu/211x146"> -->
</div>
<div class="info-items">
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon1.png" class="icons">
<div class="text-box">
<div class="name">状态</div>
<div class="value active">有效</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon12.png" class="icons">
<div class="text-box">
<div class="name">创建者</div>
<div class="value">张三丰</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon3.png" class="icons">
<div class="text-box">
<div class="name">创建时间</div>
<div class="value">2021-08-09 12:32:21</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon4.png" class="icons">
<div class="text-box">
<div class="name">更新时间</div>
<div class="value">2021-08-09 12:32:21</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon5.png" class="icons">
<div class="text-box">
<div class="name">课件名称</div>
<div class="value">基金产品(中)(初级)</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon6.png" class="icons">
<div class="text-box">
<div class="name">课件分类</div>
<div class="value">金融产品数字化营销-黄老师</div>
</div>
</div>
<div class="i-items" style="align-items: flex-start;">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon8.png" class="icons">
<div class="text-box">
<div class="name">知识点</div>
<div class="textarea-box">
某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.video-info{
background: #F7F7F7;
margin-top: 20px;
padding: 20px;
display: flex;
.video-img{
// width: 211px;
padding: 0 30px;
.item-info-icon{
font-size: 100px;
color: #aa1941;
}
.name{
font-size: 16px;
line-height: 100%;
color: #666666;
margin-top: 12px;
text-align: center;
}
}
.info-items{
display: flex;
flex-wrap: wrap;
padding-left: 12px;
.i-items{
display: flex;
align-items: center;
height: fit-content;
margin-right: 80px;
margin-bottom: 30px;
.textarea-box{
padding: 18px 18px 51px;
background: #FFFFFF;
border-radius: 4px;
font-size: 16px;
line-height: 24px;
color: #505050;
margin-top: 14px;
}
.text-box{
margin-left: 16px;
.name{
font-size: 14px;
line-height: 100%;
color: #999999;
}
.value{
font-size: 16px;
font-weight: bold;
line-height: 100%;
color: #333333;
margin-top: 8px;
&.active{
color: #1AB226;
}
}
}
}
}
}
</style>
import type { RouteRecordRaw } from 'vue-router'
import AppLayout from '@/components/layout/Index.vue'
export const routes: Array<RouteRecordRaw> = [
{
path: '/resource/courseware',
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue') },
{ path: 'update', component: () => import('./views/Update.vue') },
{ path: 'view', component: () => import('./views/View.vue') }
// { path: 'update/:id', component: () => import('./views/Update.vue'), props: true }
]
}
]
<script setup lang="ts">
// import { getVideoList } from '../api'
import CardListItem from '@/components/base/CardListItem.vue'
import { Expand, Search } from '@element-plus/icons-vue'
const appList = ref()
const isCard = ref(true)
const listOptions = {
remote: {
// httpRequest: getVideoList,
params: { type: '' },
beforeRequest(params: any) {
// params.type = 选项卡类型
return params
}
},
filters: [
{ type: 'select', prop: 'type', label: '状态' },
{ type: 'select', prop: 'project_id', label: '项目' },
{ type: 'select', prop: 'category_id', label: '类别' },
{ prop: 'search', slots: 'filter-search' }
// { type: 'input', prop: 'category_id', prefixIcon: 'Search' }
],
columns: [
{ label: '视频标题', prop: 'title' },
{ label: '视频分类', prop: 'type' },
{ label: '知识点', prop: 'zsd' },
{ label: '封面', slots: 'table-cover', width: 100 },
{ label: '资源状态', prop: 'state' },
{ label: '审核状态', prop: 'state2' },
{ label: '更新人', prop: 'update' },
{ label: '更新人部门', prop: 'updatebm' },
{ label: '更新日期', prop: 'update_time' },
{ label: '操作', slots: 'table-operate', align: 'right' }
],
data: [
{ id: 1, title: '视频标题', type: '视频分类' },
{ id: 2, title: '视频标题', type: '视频分类' }
]
}
</script>
<template>
<AppCard>
<!-- <el-switch v-model="isCard"></el-switch> -->
<div class="video-head">
<el-tabs>
<el-tab-pane label="我的资源"></el-tab-pane>
<el-tab-pane label="部门资源"></el-tab-pane>
<el-tab-pane label="公开资源"></el-tab-pane>
</el-tabs>
<el-icon class="video-head-icon" @click="isCard = !isCard"><Expand /></el-icon>
</div>
<div class="video-tool-btn">
<router-link to="/resource/courseware/update">
<el-button type="primary" round>新建课件资源</el-button>
</router-link>
</div>
<AppList v-bind="listOptions" ref="appList">
<template #header-aside></template>
<template #filter-search="{ params }">
<el-input v-model="params.search" placeholder="搜索" :prefix-icon="Search" />
</template>
<template #table-operate="{ row }">
<el-space>
<router-link :to="`/video/update/${row.id}`">
<el-button plain>编辑</el-button>
</router-link>
<router-link :to="`/video/view/${row.id}`">
<el-button type="primary" plain>查看</el-button>
</router-link>
</el-space>
</template>
<!-- 卡片 -->
<template #body="{ data }" v-if="isCard">
<div class="card-list">
<CardListItem v-for="(item, index) in data" :data="item" :key="index"></CardListItem>
</div>
<!-- <div class="resource-video-item" v-for="item in data" :key="item.id">{{ item.title }}</div> -->
</template>
</AppList>
</AppCard>
</template>
<style lang="scss">
.card-list{
background: #FAFAFA;
padding: 20px;
display: flex;
}
.video-head {
position: relative;
.video-head-icon {
position: absolute;
top: 0;
right: 0;
font-size: 30px;
color: #666;
cursor: pointer;
}
}
.video-tool-btn {
padding: 10px 0 30px 0;
}
</style>
<script setup lang="ts">
import UploadAuth from '@/components/base/UploadAuth.vue'
// form表单
const form = reactive({ videoFile: '', videoName: '', videoType: '', zsd: '', aliyun_video_id: '', weight: '' })
const rules = {}
const data = [
{
value: '1',
label: 'Level one 1',
children: [
{
value: '1-1',
label: 'Level two 1-1',
children: [
{
value: '1-1-1',
label: 'Level three 1-1-1',
},
],
},
],
},
{
value: '2',
label: 'Level one 2',
children: [
{
value: '2-1',
label: 'Level two 2-1',
children: [
{
value: '2-1-1',
label: 'Level three 2-1-1',
},
],
},
{
value: '2-2',
label: 'Level two 2-2',
children: [
{
value: '2-2-1',
label: 'Level three 2-2-1',
},
],
},
],
},
{
value: '3',
label: 'Level one 3',
children: [
{
value: '3-1',
label: 'Level two 3-1',
children: [
{
value: '3-1-1',
label: 'Level three 3-1-1',
},
],
},
{
value: '3-2',
label: 'Level two 3-2',
children: [
{
value: '3-2-1',
label: 'Level three 3-2-1',
},
],
},
],
},
]
// 协议
const protocol = ref(false)
// 上传视频过程返回值
const videoUpload = reactive({ code: -1, msg: '', progress: 0, fileName: '' })
// 上传视频回调
const uploadProgress = (res: any) => {
videoUpload.progress = res
}
const upload = (res: any) => {
const { code, msg, name } = res
videoUpload.code = code
videoUpload.msg = msg
videoUpload.fileName = name
videoUpload.progress = 0
}
</script>
<template>
<AppCard title="新建课件资源">
<div class="tool-btn-box" v-if="$route.query.id">
<div class="btn-item">部门共享</div>
<div class="btn-item">平台共享</div>
<div class="btn-item">资源下线</div>
<div class="btn-item">更改负责人</div>
</div>
<el-form ref="formRef" :model="form" :rules="rules" style="width: 70%">
<el-form-item label="课件文件:" prop="course_name">
<div>
<div class="upload-video">
<div class="upload-btn">
本地文件
<UploadAuth @progress="uploadProgress" @upload="upload"></UploadAuth>
</div>
<div class="demo-progress" v-if="videoUpload.code === 1">
<el-progress :percentage="videoUpload.progress" status="success" />
</div>
<div class="error video-info" v-if="videoUpload.code === 2">
<div class="name">上传失败</div>
</div>
<div class="video-info" v-if="videoUpload.code === 0">
<div class="name">{{ videoUpload.fileName }}</div>
<div class="view">查阅</div>
</div>
</div>
<div class="tips">课件支持格式包含:doc docx xls xlsx pdf ppt pptx,大小不超过50M</div>
</div>
</el-form-item>
<el-form-item label="课件名称:" prop="course_name">
<el-input v-model="form.videoName" />
</el-form-item>
<el-form-item label="课件分类:" prop="course_name">
<el-tree-select style="width:100%" v-model="form.videoType" :data="data" />
</el-form-item>
<el-form-item label="&nbsp;&nbsp;&nbsp;知识点:" prop="course_name">
<el-input
v-model="form.zsd"
:rows="2"
type="textarea"
/>
</el-form-item>
</el-form>
<div class="protocol-box">
<el-checkbox v-model="protocol" size="large">
我已阅读并同意<span>《紫荆教育用户入驻及网络教学资源协议》</span>
</el-checkbox>
</div>
<div class="btn-box">
<div class="confirm">保存</div>
<div class="cancel">取消</div>
</div>
</AppCard>
</template>
<style lang="scss" scoped>
.tips{
font-size: 12px;
line-height: 100%;
color: #999999;
margin-top: 8px;
}
.tool-btn-box{
display: flex;
justify-content: right;
.btn-item{
width: 127px;
line-height: 36px;
background: #AA1941;
border-radius: 20px;
margin-right: 10px;
font-size: 14px;
color: #FFFFFF;
text-align: center;
}
}
.demo-progress{
width: 350px;
}
.video-cover{
display: flex;
.img-box{
width: 208px;
height: 130px;
border-radius: 4px;
background: #F7F7F7;
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
img{
width: 100%;
height: 100%;
display: block;
}
}
.video-cover_right{
margin-left: 20px;
.list{
.item{
display: flex;
align-items: center;
margin-top: 12px;
img{
width: 9px;
display: block;
margin-right: 5px;
}
.text{
font-size: 12px;
color: #999999;
line-height: 100%;
}
}
}
}
}
.swiper-box{
min-width: 660px;
margin-top: 20px;
padding: 0 40px;
position: relative;
.arrow{
position: absolute;
top: 50%;
transform: translateY(-50%);
font-size: 30px;
color: #D5D5D5;
cursor: pointer;
&.left{
left: 0;
}
&.right{
right: 10px;
}
}
.cover-list{
display: flex;
flex-wrap: wrap;
.cover-list_item{
display: block;
width: 155px;
height: 96px;
margin: 0 10px 10px 0;
border-radius: 4px;
cursor: pointer;
}
}
}
:deep(.el-carousel__indicators--horizontal){
display: none;
}
.protocol-box{
font-size: 14px;
line-height: 24px;
padding-left: 90px;
padding-top: 20px;
color: #666666;
span{
color: #AA1941;
}
}
.btn-box{
display: flex;
margin-top: 20px;
margin-left: 90px;
.confirm{
width: 94px;
background: #AA1941;
border-radius: 20px;
text-align: center;
line-height: 36px;
color: #fff;
margin-right: 26px;
cursor: pointer;
}
.cancel{
width: 94px;
line-height: 36px;
border: 1px solid #AA1941;
border-radius: 20px;
text-align: center;
color: #AA1941;
cursor: pointer;
}
}
.upload-video{
display: flex;
align-items: center;
.upload-btn{
position: relative;
width: 94px;
line-height: 36px;
background: rgba(250, 223, 230, 0.39);
border: 1px solid #AA1941;
border-radius: 20px;
font-size: 14px;
color: #AA1941;
margin-right: 30px;
text-align: center;
}
.video-info{
display: flex;
.name{
color: #333333;
font-size: 16px;
line-height: 100%;
}
.view{
font-size: 16px;
line-height: 100%;
color: #399EE8;
margin-left: 20px;
cursor: pointer;
}
}
}
</style>
<script setup lang="ts">
import TopInfo from '../components/view/TopInfo.vue'
import CenterInfo from '../components/view/CenterInfo.vue'
import BottomInfo from '../components/view/BottomInfo.vue'
const listOptions = {
columns: [
{ label: '课程图片', prop: 'img', align: 'center' },
{ label: '课程名称', prop: 'cursor_name', align: 'center' },
{ label: '分类名称', prop: 'type_name', align: 'center' },
{ label: '所在章', slots: 'zhang', align: 'center' },
{ label: '所在小结', prop: 'jie', align: 'center' },
{ label: '创建日期', prop: 'update', align: 'center' },
{ label: '操作', slots: 'table-operate', align: 'center' }
],
data: [
{ img: 1, cursor_name: '宏观经济学.pptx', type_name: '1', zhang: '1', jie: '吉林师范大学', update: '王重阳' },
{ img: 2, cursor_name: '宏观经济学.pptx', type_name: '2', zhang: '2', jie: '吉林师范大学', update: '王重阳' },
{ img: 3, cursor_name: '宏观经济学.pptx', type_name: '3', zhang: '3', jie: '吉林师范大学', update: '王重阳' },
{ img: 4, cursor_name: '宏观经济学.pptx', type_name: '4', zhang: '4', jie: '吉林师范大学', update: '王重阳' },
{ img: 5, cursor_name: '宏观经济学.pptx', type_name: '5', zhang: '5', jie: '吉林师范大学', update: '王重阳' }
]
}
</script>
<template>
<AppCard title="课件资源信息">
<div class="btn-box">
<div class="btn-item">部门共享</div>
<div class="btn-item">平台共享</div>
<div class="btn-item">资源下线</div>
<div class="btn-item">更改负责人</div>
</div>
<TopInfo></TopInfo>
<CenterInfo></CenterInfo>
<BottomInfo></BottomInfo>
</AppCard>
<AppCard title="课件资源关联使用课程">
<AppList v-bind="listOptions" ref="appList" stripe>
<template #table-operate="{ row }">
<el-space>
<router-link :to="`/video/update/${row.id}`">
<el-button
style="color: #399EE8;"
type="primary"
link
>查看</el-button
>
</router-link>
</el-space>
</template>
</AppList>
</AppCard>
</template>
<style lang="scss" scoped>
.btn-box{
display: flex;
justify-content: right;
.btn-item{
width: 127px;
line-height: 36px;
background: #AA1941;
border-radius: 20px;
margin-right: 10px;
font-size: 14px;
color: #FFFFFF;
text-align: center;
}
}
</style>
import httpRequest from '@/utils/axios'
// 获取视频列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/psp/backend/video/index', { params })
// 获取资源统计信息
export function getUtilData() {
return httpRequest.get('/api/resource/v1/util/index')
}
<script setup lang="ts"></script>
<script setup lang="ts">
const prop = defineProps(['data'])
const listOptions = {
columns: [
{ label: '排名', slots: 'table-ranking', align: 'center' },
{ label: '关联使用', slots: 'table-relation', align: 'center' },
{ label: '资源名称', prop: 'name', align: 'center' },
{ label: '资源类型', slots: 'table-type', align: 'center' },
{ label: '所在部门', prop: 'project_id_name', align: 'center' },
{ label: '更新人', prop: 'created_operator_name', align: 'center' },
{ label: '操作', slots: 'table-operate', align: 'center' }
],
data: prop.data
}
</script>
<template>
<div></div>
<AppList v-bind="listOptions" ref="appList" border stripe>
<template #table-ranking="{ row }">
<div :class="`table-ranking active${row.index}`">{{ row.index <= 3 ? '' : row.index }}</div>
</template>
<template #table-relation="{ row }">
<div :class="`table-relation active${row.index}`">{{ row.relation }}<span></span></div>
</template>
<template #table-type="{ row }">
<div :class="`table-type active${row.index}`">{{ row.resource_type }}</div>
</template>
<template #table-operate="{ row }">
<el-space>
<router-link :to="`/video/update/${row.id}`">
<el-button
style="color: #399EE8;"
type="primary"
link
>查阅</el-button
>
</router-link>
</el-space>
</template>
</AppList>
</template>
<style lang="scss"></style>
\ No newline at end of file
<style lang="scss">
.table-ranking{
font-size: 14px;
color: #666666;
margin: 0 auto;
&.active1{
width: 20px;
height: 26px;
background: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-ranking1.png);
}
&.active2{
width: 20px;
height: 26px;
background: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-ranking2.png);
}
&.active3{
width: 20px;
height: 26px;
background: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-ranking3.png);
}
}
.table-type{
width: 84px;
line-height: 28px;
border-radius: 14px;
text-align: center;
font-size: 14px;
margin: 0 auto;
&.active1{
background: #FAEDF1;
color: #AA1941;
}
&.active2{
background: #F5EBDA;
color: #BA8B45;
}
&.active3{
background:#E9EAF8;
color: #5B61B5;
}
&.active4{
background: #DFEFF2;
color:#47A7B9;
}
&.active5{
background: #FAEEE2;
color: #CE893F;
}
}
.table-relation{
font-size: 14px;
span{
color: #666666;
}
&.active1{
color: #AA1941;
}
&.active2{
color: #BA8B45;
}
&.active3{
color: #5B61B5;
}
&.active4{
color:#47A7B9;
}
&.active5{
color: #CE893F;
}
}
</style>
\ No newline at end of file
<script setup lang="ts"></script>
<script setup lang="ts">
const prop = defineProps(['data'])
const listOptions = {
columns: [
{ label: '排名', slots: 'table-ranking', align: 'center' },
{ label: '资源名称', prop: 'name', align: 'center' },
{ label: '资源类型', slots: 'table-type', align: 'center' },
{ label: '所在部门', prop: 'project_id_name', align: 'center' },
{ label: '更新人', prop: 'created_operator_name', align: 'center' },
{ label: '更新时间', prop: 'updated_time', align: 'center' },
{ label: '操作', slots: 'table-operate', align: 'center' }
],
data: prop.data
}
</script>
<template>
<div></div>
<AppList v-bind="listOptions" ref="appList" border stripe>
<template #table-ranking="{ row }">
<div :class="`table-ranking active${row.index}`">{{ row.index <= 3 ? '' : row.index }}</div>
</template>
<template #table-type="{ row }">
<div :class="`table-type active${row.index}`">{{ row.resource_type }}</div>
</template>
<template #table-operate="{ row }">
<el-space>
<router-link :to="`/video/update/${row.id}`">
<el-button
style="color: #399EE8;"
type="primary"
link
>查阅</el-button
>
</router-link>
</el-space>
</template>
</AppList>
</template>
<style lang="scss"></style>
\ No newline at end of file
<style lang="scss">
.table-ranking{
font-size: 14px;
color: #666666;
margin: 0 auto;
&.active1{
width: 20px;
height: 26px;
background: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-ranking1.png);
}
&.active2{
width: 20px;
height: 26px;
background: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-ranking2.png);
}
&.active3{
width: 20px;
height: 26px;
background: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-ranking3.png);
}
}
.table-type{
width: 84px;
line-height: 28px;
border-radius: 14px;
text-align: center;
font-size: 14px;
margin: 0 auto;
&.active1{
background: #FAEDF1;
color: #AA1941;
}
&.active2{
background: #F5EBDA;
color: #BA8B45;
}
&.active3{
background:#E9EAF8;
color: #5B61B5;
}
&.active4{
background: #DFEFF2;
color:#47A7B9;
}
&.active5{
background: #FAEEE2;
color: #CE893F;
}
}
</style>
\ No newline at end of file
<script setup lang="ts"></script>
<script setup lang="ts">
const prop = defineProps(['data'])
const listOptions = {
columns: [
{ label: '排名', slots: 'table-ranking', align: 'center' },
{ label: '资源名称', prop: 'name', align: 'center' },
{ label: '资源类型', slots: 'table-type', align: 'center' },
{ label: '所在部门', prop: 'project_id_name', align: 'center' },
{ label: '更新人', prop: 'created_operator_name', align: 'center' },
{ label: '更新时间', prop: 'updated_time', align: 'center' },
{ label: '操作', slots: 'table-operate', align: 'center' }
],
data: prop.data
}
</script>
<template>
<div></div>
<AppList v-bind="listOptions" ref="appList" border stripe>
<template #table-ranking="{ row }">
<div :class="`table-ranking active${row.index}`">{{ row.index <= 3 ? '' : row.index }}</div>
</template>
<template #table-type="{ row }">
<div :class="`table-type active${row.index}`">{{ row.resource_type }}</div>
</template>
<template #table-operate="{ row }">
<el-space>
<router-link :to="`/video/update/${row.id}`">
<el-button
style="color: #399EE8;"
type="primary"
link
>查阅</el-button
>
</router-link>
</el-space>
</template>
</AppList>
</template>
<style lang="scss"></style>
\ No newline at end of file
<style lang="scss">
.table-ranking{
font-size: 14px;
color: #666666;
margin: 0 auto;
&.active1{
width: 20px;
height: 26px;
background: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-ranking1.png);
}
&.active2{
width: 20px;
height: 26px;
background: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-ranking2.png);
}
&.active3{
width: 20px;
height: 26px;
background: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-ranking3.png);
}
}
.table-type{
width: 84px;
line-height: 28px;
border-radius: 14px;
text-align: center;
font-size: 14px;
margin: 0 auto;
&.active1{
background: #FAEDF1;
color: #AA1941;
}
&.active2{
background: #F5EBDA;
color: #BA8B45;
}
&.active3{
background:#E9EAF8;
color: #5B61B5;
}
&.active4{
background: #DFEFF2;
color:#47A7B9;
}
&.active5{
background: #FAEEE2;
color: #CE893F;
}
}
</style>
\ No newline at end of file
<script setup lang="ts"></script>
<script setup lang="ts">
const prop = defineProps(['data'])
</script>
<template>
<div class="statistics-list">
<div class="item"></div>
<div class="item" v-for="(item, index) in prop.data" :key="index">
<div class="icon"></div>
<div class="num">{{ item.number }}<span>{{ item.unit }}</span></div>
<div class="text">{{ item.text }}</div>
</div>
</div>
</template>
<style lang="scss">
.statistics-list{
display: flex;
flex-wrap: wrap;
margin-top: -20px;
.item{
width: 110px;
padding-top: 15px;
min-width: 110px;
height: 140px;
border: 1px solid #E5E5E5;
border-radius: 6px;
box-sizing: border-box;
margin-right: 20px;
margin-top: 20px;
.icon{
width: 40px;
height: 40px;
background-size: 100% 100%;
margin: 0 auto;
&:nth-child(1){
background-image: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-icon1.png);
}
&:nth-child(2){
background-image: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-icon2.png);
}
&:nth-child(3){
background-image: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-icon3.png);
}
&:nth-child(4){
background-image: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-icon4.png);
}
&:nth-child(5){
background-image: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-icon5.png);
}
&:nth-child(6){
background-image: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-icon6.png);
}
&:nth-child(7){
background-image: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-icon7.png);
}
&:nth-child(8){
background-image: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-icon8.png);
}
&:nth-child(9){
background-image: url(https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/home-icon9.png);
}
}
.num{
font-size: 26px;
line-height: 100%;
color: #BF9D6B;
text-align: center;
padding: 10px;
span{
font-size: 12px;
}
}
.text{
font-size: 14px;
line-height: 100%;
color: #8E8E8E;
text-align: center;
}
}
}
</style>
\ No newline at end of file
......@@ -3,18 +3,64 @@ import Statistics from '../components/Statistics.vue'
import Newest from '../components/Newest.vue'
import Hottest from '../components/Hottest.vue'
import RecentLearning from '../components/RecentLearning.vue'
import { getUtilData } from '../api'
let flag = $ref(false)
const data = reactive<{statistics: object[], latest: object[], hot: object[], learn: object[] }>({
statistics: [],
latest: [],
hot: [],
learn: []
})
// 所有数据
getUtilData().then(res => {
flag = true
let { latest = [], hot = [], learn = [] }: { latest: object[], hot: object[], learn: object[] } = res.data
if (learn === null) learn = []
// 统计资源数据整合
const statisticsData = [
{ key: 'video_count', unit: '个', number: 0, text: '视频资源' },
{ key: 'courseware_count', unit: '个', number: 0, text: '课件资源' },
{ key: 'other_information_count', unit: '个', number: 0, text: '其他资料' },
{ key: 'question_count', unit: '个', number: 0, text: '题库资源' },
{ key: 'paper_count', unit: '套', number: 0, text: '试卷资源' },
{ key: 'memory_size', unit: 'GB', number: 0, text: '资源总体量' },
{ key: 'length', unit: '小时', number: 0, text: '资源总时长' },
{ key: 'learn_times', unit: '万人次', number: 0, text: '总学习人次' },
{ key: 'learn_time_length', unit: '小时', number: 0, text: '总学习时长' }
]
data.statistics = statisticsData.map(item => {
item.number = res.data[item.key] || 0
return item
})
// 最近数据
data.latest = latest.map((item: any, index: number) => {
item.index = index + 1
return item
})
// 最热资源
data.hot = hot.map((item: any, index: number) => {
item.index = index + 1
return item
})
data.learn = learn.map((item: any, index: number) => {
item.index = index + 1
return item
})
})
</script>
<template>
<div v-if="flag">
<AppCard title="资源统计">
<Statistics></Statistics>
<Statistics :data="data.statistics"></Statistics>
</AppCard>
<AppCard title="最新资源">
<Newest></Newest>
<Newest :data="data.latest"></Newest>
</AppCard>
<AppCard title="最热资源">
<AppCard :data="data.hot" title="最热资源">
<Hottest></Hottest>
</AppCard>
<AppCard title="最近学习">
<RecentLearning></RecentLearning>
<RecentLearning :data="data.learn"></RecentLearning>
</AppCard>
</div>
</template>
import httpRequest from '@/utils/axios'
// 获取视频列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/psp/backend/video/index', { params })
}
// 创建视频
export function createVideo(data: { course_name: string; cover_page: string; type: string; weight?: string }) {
return httpRequest.post('/api/psp/backend/video/create', data)
}
// 更新视频
export function updateVideo(data: { id: string; course_name: string; cover_page: string; type: string; weight?: string }) {
return httpRequest.post('/api/psp/backend/video/update', data)
}
// 获取视频详情
export function getVideo(params: { id: string }) {
return httpRequest.get('/api/psp/backend/video/view', { params })
}
<script setup lang="ts">
import * as echarts from "echarts"
const echartsRef = ref()
onMounted(() => {
const myEcharts = echarts.init(echartsRef.value)
const option = {
grid: {
bottom: 30,
left: 30,
right: 30
},
xAxis: {
data: ['2022-02-21', '2022-02-21', '2022-02-21', '2022-02-21', '2022-02-21', '2022-02-21'],
axisTick: {
show: false
}
},
color: ['#BF9D6B'],
yAxis: {},
series: [
{
type: 'bar',
barWidth: '18',
data: [5, 20, 36, 10, 10, 20]
}
],
}
//设置配置
myEcharts.setOption(option)
})
const listOptions = {
columns: [
{ label: '访问时间', prop: 'name', align: 'center' },
{ label: '姓名', prop: 'bumen', align: 'center' },
{ label: '所在项目', prop: 'update', align: 'center' },
{ label: '访问时长', prop: 'time', align: 'center' }
],
data: [
{ time: '111', id: 1, name: '宏观经济学.pptx', type: '1', index: '1', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
{ time: '111', id: 2, name: '宏观经济学.pptx', type: '2', index: '2', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
{ time: '111', id: 3, name: '宏观经济学.pptx', type: '3', index: '3', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
{ time: '111', id: 4, name: '宏观经济学.pptx', type: '4', index: '4', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
]
}
</script>
<template>
<div class="data-box">
<div class="echart">
<div class="name">访问量/关联量一周走势图</div>
<div
class="echarts"
ref="echartsRef"
:style="{
width: '600px',
height: '300px'
}"
></div>
</div>
<div class="label-box">
<div class="name">最近访问</div>
<AppList v-bind="listOptions" ref="appList" stripe></AppList>
</div>
</div>
<!-- <div
class="echarts"
ref="echartsRef"
:style="{
width: '600px',
height: '300px'
}"
></div> -->
</template>
<style lang="scss" scoped>
.data-box{
display: flex;
.echart{
flex: 1;
height: 369px;
box-sizing: border-box;
border: 1px solid #E0E0E0;
border-radius: 10px;
margin-right: 10px;
padding: 20px;
.name{
font-size: 16px;
line-height: 100%;
color: #333333;
}
}
.label-box{
box-sizing: border-box;
flex: 1;
height: 369px;
border: 1px solid #E0E0E0;
border-radius: 10px;
margin-left: 10px;
padding: 20px;
.name{
font-size: 16px;
line-height: 100%;
color: #333333;
}
}
}
</style>
<script setup lang="ts">
</script>
<template>
<div class="center-video-box">
<div class="file-box">
<embed width="812" height="433" src="https://vocational-store.oss-cn-beijing.aliyuncs.com/files/20210604/7b1bfdec10354da769461199acf55176.pdf">
</div>
<!-- <video width="812" height="433" controls>
<source src="https://video.shipin520.com/videos/17/36/71/b_KSyZ5ujXfz7R1567173671.mp4" type="video/mp4">
</video> -->
<div class="right-statistics">
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon1.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">使用项目/学校</div>
</div>
</div>
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon2.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">使用课程</div>
</div>
</div>
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon3.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">累计学习人次</div>
</div>
</div>
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon4.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">累计学习时长</div>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.center-video-box{
padding: 20px 0;
display: flex;
.right-statistics{
flex: 1;
padding-top: 15px;
.stat-item{
width: 210px;
height: 85px;
background: #B41E47;
border-radius: 6px;
display: flex;
align-items: center;
margin: 0 auto 20px;
&:nth-child(even){
background: #BF9D6B;
}
img{
width: 52px;
height: 52px;
display: block;
margin-left: 18px;
}
.content{
margin-left: 18px;
.unit{
font-size: 26px;
line-height: 100%;
color: #FFFFFF;
span{
font-size: 12px;
line-height: 100%;
}
}
.tag{
font-size: 14px;
line-height: 100%;
color: #FFFFFF;
margin-top: 10px;
}
}
}
}
}
</style>
<script setup lang="ts">
import { Files } from '@element-plus/icons-vue'
</script>
<template>
<div class="video-info">
<div class="video-img">
<el-icon class="item-info-icon">
<Files />
</el-icon>
<!-- <img src="https://iph.href.lu/211x146"> -->
</div>
<div class="info-items">
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon1.png" class="icons">
<div class="text-box">
<div class="name">状态</div>
<div class="value active">有效</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon12.png" class="icons">
<div class="text-box">
<div class="name">创建者</div>
<div class="value">张三丰</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon3.png" class="icons">
<div class="text-box">
<div class="name">创建时间</div>
<div class="value">2021-08-09 12:32:21</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon4.png" class="icons">
<div class="text-box">
<div class="name">更新时间</div>
<div class="value">2021-08-09 12:32:21</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon5.png" class="icons">
<div class="text-box">
<div class="name">课件名称</div>
<div class="value">基金产品(中)(初级)</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon6.png" class="icons">
<div class="text-box">
<div class="name">课件分类</div>
<div class="value">金融产品数字化营销-黄老师</div>
</div>
</div>
<div class="i-items" style="align-items: flex-start;">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon8.png" class="icons">
<div class="text-box">
<div class="name">知识点</div>
<div class="textarea-box">
某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.video-info{
background: #F7F7F7;
margin-top: 20px;
padding: 20px;
display: flex;
.video-img{
// width: 211px;
padding: 0 30px;
.item-info-icon{
font-size: 100px;
color: #aa1941;
}
.name{
font-size: 16px;
line-height: 100%;
color: #666666;
margin-top: 12px;
text-align: center;
}
}
.info-items{
display: flex;
flex-wrap: wrap;
padding-left: 12px;
.i-items{
display: flex;
align-items: center;
height: fit-content;
margin-right: 80px;
margin-bottom: 30px;
.textarea-box{
padding: 18px 18px 51px;
background: #FFFFFF;
border-radius: 4px;
font-size: 16px;
line-height: 24px;
color: #505050;
margin-top: 14px;
}
.text-box{
margin-left: 16px;
.name{
font-size: 14px;
line-height: 100%;
color: #999999;
}
.value{
font-size: 16px;
font-weight: bold;
line-height: 100%;
color: #333333;
margin-top: 8px;
&.active{
color: #1AB226;
}
}
}
}
}
}
</style>
import type { RouteRecordRaw } from 'vue-router'
import AppLayout from '@/components/layout/Index.vue'
export const routes: Array<RouteRecordRaw> = [
{
path: '/resource/lessonplan',
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue') },
{ path: 'update', component: () => import('./views/Update.vue') },
{ path: 'view', component: () => import('./views/View.vue') }
// { path: 'update/:id', component: () => import('./views/Update.vue'), props: true }
]
}
]
<script setup lang="ts">
// import { getVideoList } from '../api'
import CardListItem from '@/components/base/CardListItem.vue'
import { Expand, Search } from '@element-plus/icons-vue'
const appList = ref()
const isCard = ref(true)
const listOptions = {
remote: {
// httpRequest: getVideoList,
params: { type: '' },
beforeRequest(params: any) {
// params.type = 选项卡类型
return params
}
},
filters: [
{ type: 'select', prop: 'type', label: '状态' },
{ type: 'select', prop: 'project_id', label: '项目' },
{ type: 'select', prop: 'category_id', label: '类别' },
{ prop: 'search', slots: 'filter-search' }
// { type: 'input', prop: 'category_id', prefixIcon: 'Search' }
],
columns: [
{ label: '视频标题', prop: 'title' },
{ label: '视频分类', prop: 'type' },
{ label: '知识点', prop: 'zsd' },
{ label: '封面', slots: 'table-cover', width: 100 },
{ label: '资源状态', prop: 'state' },
{ label: '审核状态', prop: 'state2' },
{ label: '更新人', prop: 'update' },
{ label: '更新人部门', prop: 'updatebm' },
{ label: '更新日期', prop: 'update_time' },
{ label: '操作', slots: 'table-operate', align: 'right' }
],
data: [
{ id: 1, title: '视频标题', type: '视频分类' },
{ id: 2, title: '视频标题', type: '视频分类' }
]
}
</script>
<template>
<AppCard>
<!-- <el-switch v-model="isCard"></el-switch> -->
<div class="video-head">
<el-tabs>
<el-tab-pane label="我的资源"></el-tab-pane>
<el-tab-pane label="部门资源"></el-tab-pane>
<el-tab-pane label="公开资源"></el-tab-pane>
</el-tabs>
<el-icon class="video-head-icon" @click="isCard = !isCard"><Expand /></el-icon>
</div>
<div class="video-tool-btn">
<router-link to="/resource/lessonplan/update">
<el-button type="primary" round>新建教案资源</el-button>
</router-link>
</div>
<AppList v-bind="listOptions" ref="appList">
<template #header-aside></template>
<template #filter-search="{ params }">
<el-input v-model="params.search" placeholder="搜索" :prefix-icon="Search" />
</template>
<template #table-operate="{ row }">
<el-space>
<router-link :to="`/video/update/${row.id}`">
<el-button plain>编辑</el-button>
</router-link>
<router-link :to="`/video/view/${row.id}`">
<el-button type="primary" plain>查看</el-button>
</router-link>
</el-space>
</template>
<!-- 卡片 -->
<template #body="{ data }" v-if="isCard">
<div class="card-list">
<CardListItem v-for="(item, index) in data" :data="item" :key="index"></CardListItem>
</div>
<!-- <div class="resource-video-item" v-for="item in data" :key="item.id">{{ item.title }}</div> -->
</template>
</AppList>
</AppCard>
</template>
<style lang="scss">
.card-list{
background: #FAFAFA;
padding: 20px;
display: flex;
}
.video-head {
position: relative;
.video-head-icon {
position: absolute;
top: 0;
right: 0;
font-size: 30px;
color: #666;
cursor: pointer;
}
}
.video-tool-btn {
padding: 10px 0 30px 0;
}
</style>
<script setup lang="ts">
import UploadAuth from '@/components/base/UploadAuth.vue'
// form表单
const form = reactive({ videoFile: '', videoName: '', videoType: '', zsd: '', aliyun_video_id: '', weight: '' })
const rules = {}
const data = [
{
value: '1',
label: 'Level one 1',
children: [
{
value: '1-1',
label: 'Level two 1-1',
children: [
{
value: '1-1-1',
label: 'Level three 1-1-1',
},
],
},
],
},
{
value: '2',
label: 'Level one 2',
children: [
{
value: '2-1',
label: 'Level two 2-1',
children: [
{
value: '2-1-1',
label: 'Level three 2-1-1',
},
],
},
{
value: '2-2',
label: 'Level two 2-2',
children: [
{
value: '2-2-1',
label: 'Level three 2-2-1',
},
],
},
],
},
{
value: '3',
label: 'Level one 3',
children: [
{
value: '3-1',
label: 'Level two 3-1',
children: [
{
value: '3-1-1',
label: 'Level three 3-1-1',
},
],
},
{
value: '3-2',
label: 'Level two 3-2',
children: [
{
value: '3-2-1',
label: 'Level three 3-2-1',
},
],
},
],
},
]
// 协议
const protocol = ref(false)
// 上传视频过程返回值
const videoUpload = reactive({ code: -1, msg: '', progress: 0, fileName: '' })
// 上传视频回调
const uploadProgress = (res: any) => {
videoUpload.progress = res
}
const upload = (res: any) => {
const { code, msg, name } = res
videoUpload.code = code
videoUpload.msg = msg
videoUpload.fileName = name
videoUpload.progress = 0
}
</script>
<template>
<AppCard title="新建教案资源">
<div class="tool-btn-box" v-if="$route.query.id">
<div class="btn-item">部门共享</div>
<div class="btn-item">平台共享</div>
<div class="btn-item">资源下线</div>
<div class="btn-item">更改负责人</div>
</div>
<el-form ref="formRef" :model="form" :rules="rules" style="width: 70%">
<el-form-item label="教案文件:" prop="course_name">
<div>
<div class="upload-video">
<div class="upload-btn">
本地文件
<UploadAuth @progress="uploadProgress" @upload="upload"></UploadAuth>
</div>
<div class="demo-progress" v-if="videoUpload.code === 1">
<el-progress :percentage="videoUpload.progress" status="success" />
</div>
<div class="error video-info" v-if="videoUpload.code === 2">
<div class="name">上传失败</div>
</div>
<div class="video-info" v-if="videoUpload.code === 0">
<div class="name">{{ videoUpload.fileName }}</div>
<div class="view">查阅</div>
</div>
</div>
<div class="tips">课件支持格式包含:doc docx pdf ppt pptx,大小不超过50M</div>
</div>
</el-form-item>
<el-form-item label="教案名称:" prop="course_name">
<el-input v-model="form.videoName" />
</el-form-item>
<el-form-item label="教案分类:" prop="course_name">
<el-tree-select style="width:100%" v-model="form.videoType" :data="data" />
</el-form-item>
<el-form-item label="&nbsp;&nbsp;&nbsp;知识点:" prop="course_name">
<el-input
v-model="form.zsd"
:rows="2"
type="textarea"
/>
</el-form-item>
</el-form>
<div class="protocol-box">
<el-checkbox v-model="protocol" size="large">
我已阅读并同意<span>《紫荆教育用户入驻及网络教学资源协议》</span>
</el-checkbox>
</div>
<div class="btn-box">
<div class="confirm">保存</div>
<div class="cancel">取消</div>
</div>
</AppCard>
</template>
<style lang="scss" scoped>
.tips{
font-size: 12px;
line-height: 100%;
color: #999999;
margin-top: 8px;
}
.tool-btn-box{
display: flex;
justify-content: right;
.btn-item{
width: 127px;
line-height: 36px;
background: #AA1941;
border-radius: 20px;
margin-right: 10px;
font-size: 14px;
color: #FFFFFF;
text-align: center;
}
}
.demo-progress{
width: 350px;
}
.video-cover{
display: flex;
.img-box{
width: 208px;
height: 130px;
border-radius: 4px;
background: #F7F7F7;
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
img{
width: 100%;
height: 100%;
display: block;
}
}
.video-cover_right{
margin-left: 20px;
.list{
.item{
display: flex;
align-items: center;
margin-top: 12px;
img{
width: 9px;
display: block;
margin-right: 5px;
}
.text{
font-size: 12px;
color: #999999;
line-height: 100%;
}
}
}
}
}
.swiper-box{
min-width: 660px;
margin-top: 20px;
padding: 0 40px;
position: relative;
.arrow{
position: absolute;
top: 50%;
transform: translateY(-50%);
font-size: 30px;
color: #D5D5D5;
cursor: pointer;
&.left{
left: 0;
}
&.right{
right: 10px;
}
}
.cover-list{
display: flex;
flex-wrap: wrap;
.cover-list_item{
display: block;
width: 155px;
height: 96px;
margin: 0 10px 10px 0;
border-radius: 4px;
cursor: pointer;
}
}
}
:deep(.el-carousel__indicators--horizontal){
display: none;
}
.protocol-box{
font-size: 14px;
line-height: 24px;
padding-left: 90px;
padding-top: 20px;
color: #666666;
span{
color: #AA1941;
}
}
.btn-box{
display: flex;
margin-top: 20px;
margin-left: 90px;
.confirm{
width: 94px;
background: #AA1941;
border-radius: 20px;
text-align: center;
line-height: 36px;
color: #fff;
margin-right: 26px;
cursor: pointer;
}
.cancel{
width: 94px;
line-height: 36px;
border: 1px solid #AA1941;
border-radius: 20px;
text-align: center;
color: #AA1941;
cursor: pointer;
}
}
.upload-video{
display: flex;
align-items: center;
.upload-btn{
position: relative;
width: 94px;
line-height: 36px;
background: rgba(250, 223, 230, 0.39);
border: 1px solid #AA1941;
border-radius: 20px;
font-size: 14px;
color: #AA1941;
margin-right: 30px;
text-align: center;
}
.video-info{
display: flex;
.name{
color: #333333;
font-size: 16px;
line-height: 100%;
}
.view{
font-size: 16px;
line-height: 100%;
color: #399EE8;
margin-left: 20px;
cursor: pointer;
}
}
}
</style>
<script setup lang="ts">
import TopInfo from '../components/view/TopInfo.vue'
import CenterInfo from '../components/view/CenterInfo.vue'
import BottomInfo from '../components/view/BottomInfo.vue'
const listOptions = {
columns: [
{ label: '课程图片', prop: 'img', align: 'center' },
{ label: '课程名称', prop: 'cursor_name', align: 'center' },
{ label: '分类名称', prop: 'type_name', align: 'center' },
{ label: '所在章', slots: 'zhang', align: 'center' },
{ label: '所在小结', prop: 'jie', align: 'center' },
{ label: '创建日期', prop: 'update', align: 'center' },
{ label: '操作', slots: 'table-operate', align: 'center' }
],
data: [
{ img: 1, cursor_name: '宏观经济学.pptx', type_name: '1', zhang: '1', jie: '吉林师范大学', update: '王重阳' },
{ img: 2, cursor_name: '宏观经济学.pptx', type_name: '2', zhang: '2', jie: '吉林师范大学', update: '王重阳' },
{ img: 3, cursor_name: '宏观经济学.pptx', type_name: '3', zhang: '3', jie: '吉林师范大学', update: '王重阳' },
{ img: 4, cursor_name: '宏观经济学.pptx', type_name: '4', zhang: '4', jie: '吉林师范大学', update: '王重阳' },
{ img: 5, cursor_name: '宏观经济学.pptx', type_name: '5', zhang: '5', jie: '吉林师范大学', update: '王重阳' }
]
}
</script>
<template>
<AppCard title="课件资源信息">
<div class="btn-box">
<div class="btn-item">部门共享</div>
<div class="btn-item">平台共享</div>
<div class="btn-item">资源下线</div>
<div class="btn-item">更改负责人</div>
</div>
<TopInfo></TopInfo>
<CenterInfo></CenterInfo>
<BottomInfo></BottomInfo>
</AppCard>
<AppCard title="课件资源关联使用课程">
<AppList v-bind="listOptions" ref="appList" stripe>
<template #table-operate="{ row }">
<el-space>
<router-link :to="`/video/update/${row.id}`">
<el-button
style="color: #399EE8;"
type="primary"
link
>查看</el-button
>
</router-link>
</el-space>
</template>
</AppList>
</AppCard>
</template>
<style lang="scss" scoped>
.btn-box{
display: flex;
justify-content: right;
.btn-item{
width: 127px;
line-height: 36px;
background: #AA1941;
border-radius: 20px;
margin-right: 10px;
font-size: 14px;
color: #FFFFFF;
text-align: center;
}
}
</style>
import httpRequest from '@/utils/axios'
// 获取视频列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/psp/backend/video/index', { params })
}
// 创建视频
export function createVideo(data: { course_name: string; cover_page: string; type: string; weight?: string }) {
return httpRequest.post('/api/psp/backend/video/create', data)
}
// 更新视频
export function updateVideo(data: { id: string; course_name: string; cover_page: string; type: string; weight?: string }) {
return httpRequest.post('/api/psp/backend/video/update', data)
}
// 获取视频详情
export function getVideo(params: { id: string }) {
return httpRequest.get('/api/psp/backend/video/view', { params })
}
<script setup lang="ts">
import * as echarts from "echarts"
const echartsRef = ref()
onMounted(() => {
const myEcharts = echarts.init(echartsRef.value)
const option = {
grid: {
bottom: 30,
left: 30,
right: 30
},
xAxis: {
data: ['2022-02-21', '2022-02-21', '2022-02-21', '2022-02-21', '2022-02-21', '2022-02-21'],
axisTick: {
show: false
}
},
color: ['#BF9D6B'],
yAxis: {},
series: [
{
type: 'bar',
barWidth: '18',
data: [5, 20, 36, 10, 10, 20]
}
],
}
//设置配置
myEcharts.setOption(option)
})
const listOptions = {
columns: [
{ label: '访问时间', prop: 'name', align: 'center' },
{ label: '姓名', prop: 'bumen', align: 'center' },
{ label: '所在项目', prop: 'update', align: 'center' },
{ label: '访问时长', prop: 'time', align: 'center' }
],
data: [
{ time: '111', id: 1, name: '宏观经济学.pptx', type: '1', index: '1', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
{ time: '111', id: 2, name: '宏观经济学.pptx', type: '2', index: '2', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
{ time: '111', id: 3, name: '宏观经济学.pptx', type: '3', index: '3', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
{ time: '111', id: 4, name: '宏观经济学.pptx', type: '4', index: '4', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
]
}
</script>
<template>
<div class="data-box">
<div class="echart">
<div class="name">访问量/关联量一周走势图</div>
<div
class="echarts"
ref="echartsRef"
:style="{
width: '600px',
height: '300px'
}"
></div>
</div>
<div class="label-box">
<div class="name">最近访问</div>
<AppList v-bind="listOptions" ref="appList" stripe></AppList>
</div>
</div>
<!-- <div
class="echarts"
ref="echartsRef"
:style="{
width: '600px',
height: '300px'
}"
></div> -->
</template>
<style lang="scss" scoped>
.data-box{
display: flex;
.echart{
flex: 1;
height: 369px;
box-sizing: border-box;
border: 1px solid #E0E0E0;
border-radius: 10px;
margin-right: 10px;
padding: 20px;
.name{
font-size: 16px;
line-height: 100%;
color: #333333;
}
}
.label-box{
box-sizing: border-box;
flex: 1;
height: 369px;
border: 1px solid #E0E0E0;
border-radius: 10px;
margin-left: 10px;
padding: 20px;
.name{
font-size: 16px;
line-height: 100%;
color: #333333;
}
}
}
</style>
<script setup lang="ts">
</script>
<template>
<div class="center-video-box">
<div class="file-box">
<embed width="812" height="433" src="https://vocational-store.oss-cn-beijing.aliyuncs.com/files/20210604/7b1bfdec10354da769461199acf55176.pdf">
</div>
<!-- <video width="812" height="433" controls>
<source src="https://video.shipin520.com/videos/17/36/71/b_KSyZ5ujXfz7R1567173671.mp4" type="video/mp4">
</video> -->
<div class="right-statistics">
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon1.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">使用项目/学校</div>
</div>
</div>
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon2.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">使用课程</div>
</div>
</div>
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon3.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">累计学习人次</div>
</div>
</div>
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon4.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">累计学习时长</div>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.center-video-box{
padding: 20px 0;
display: flex;
.right-statistics{
flex: 1;
padding-top: 15px;
.stat-item{
width: 210px;
height: 85px;
background: #B41E47;
border-radius: 6px;
display: flex;
align-items: center;
margin: 0 auto 20px;
&:nth-child(even){
background: #BF9D6B;
}
img{
width: 52px;
height: 52px;
display: block;
margin-left: 18px;
}
.content{
margin-left: 18px;
.unit{
font-size: 26px;
line-height: 100%;
color: #FFFFFF;
span{
font-size: 12px;
line-height: 100%;
}
}
.tag{
font-size: 14px;
line-height: 100%;
color: #FFFFFF;
margin-top: 10px;
}
}
}
}
}
</style>
<script setup lang="ts">
import { Files } from '@element-plus/icons-vue'
</script>
<template>
<div class="video-info">
<div class="video-img">
<el-icon class="item-info-icon">
<Files />
</el-icon>
<!-- <img src="https://iph.href.lu/211x146"> -->
</div>
<div class="info-items">
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon1.png" class="icons">
<div class="text-box">
<div class="name">状态</div>
<div class="value active">有效</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon12.png" class="icons">
<div class="text-box">
<div class="name">创建者</div>
<div class="value">张三丰</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon3.png" class="icons">
<div class="text-box">
<div class="name">创建时间</div>
<div class="value">2021-08-09 12:32:21</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon4.png" class="icons">
<div class="text-box">
<div class="name">更新时间</div>
<div class="value">2021-08-09 12:32:21</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon5.png" class="icons">
<div class="text-box">
<div class="name">课件名称</div>
<div class="value">基金产品(中)(初级)</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon6.png" class="icons">
<div class="text-box">
<div class="name">课件分类</div>
<div class="value">金融产品数字化营销-黄老师</div>
</div>
</div>
<div class="i-items" style="align-items: flex-start;">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon8.png" class="icons">
<div class="text-box">
<div class="name">知识点</div>
<div class="textarea-box">
某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.video-info{
background: #F7F7F7;
margin-top: 20px;
padding: 20px;
display: flex;
.video-img{
// width: 211px;
padding: 0 30px;
.item-info-icon{
font-size: 100px;
color: #aa1941;
}
.name{
font-size: 16px;
line-height: 100%;
color: #666666;
margin-top: 12px;
text-align: center;
}
}
.info-items{
display: flex;
flex-wrap: wrap;
padding-left: 12px;
.i-items{
display: flex;
align-items: center;
height: fit-content;
margin-right: 80px;
margin-bottom: 30px;
.textarea-box{
padding: 18px 18px 51px;
background: #FFFFFF;
border-radius: 4px;
font-size: 16px;
line-height: 24px;
color: #505050;
margin-top: 14px;
}
.text-box{
margin-left: 16px;
.name{
font-size: 14px;
line-height: 100%;
color: #999999;
}
.value{
font-size: 16px;
font-weight: bold;
line-height: 100%;
color: #333333;
margin-top: 8px;
&.active{
color: #1AB226;
}
}
}
}
}
}
</style>
import type { RouteRecordRaw } from 'vue-router'
import AppLayout from '@/components/layout/Index.vue'
export const routes: Array<RouteRecordRaw> = [
{
path: '/resource/other',
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue') },
{ path: 'update', component: () => import('./views/Update.vue') },
{ path: 'view', component: () => import('./views/View.vue') }
// { path: 'update/:id', component: () => import('./views/Update.vue'), props: true }
]
}
]
<script setup lang="ts">
// import { getVideoList } from '../api'
import CardListItem from '@/components/base/CardListItem.vue'
import { Expand, Search } from '@element-plus/icons-vue'
const appList = ref()
const isCard = ref(true)
const listOptions = {
remote: {
// httpRequest: getVideoList,
params: { type: '' },
beforeRequest(params: any) {
// params.type = 选项卡类型
return params
}
},
filters: [
{ type: 'select', prop: 'type', label: '状态' },
{ type: 'select', prop: 'project_id', label: '项目' },
{ type: 'select', prop: 'category_id', label: '类别' },
{ prop: 'search', slots: 'filter-search' }
// { type: 'input', prop: 'category_id', prefixIcon: 'Search' }
],
columns: [
{ label: '视频标题', prop: 'title' },
{ label: '视频分类', prop: 'type' },
{ label: '知识点', prop: 'zsd' },
{ label: '封面', slots: 'table-cover', width: 100 },
{ label: '资源状态', prop: 'state' },
{ label: '审核状态', prop: 'state2' },
{ label: '更新人', prop: 'update' },
{ label: '更新人部门', prop: 'updatebm' },
{ label: '更新日期', prop: 'update_time' },
{ label: '操作', slots: 'table-operate', align: 'right' }
],
data: [
{ id: 1, title: '视频标题', type: '视频分类' },
{ id: 2, title: '视频标题', type: '视频分类' }
]
}
</script>
<template>
<AppCard>
<!-- <el-switch v-model="isCard"></el-switch> -->
<div class="video-head">
<el-tabs>
<el-tab-pane label="我的资源"></el-tab-pane>
<el-tab-pane label="部门资源"></el-tab-pane>
<el-tab-pane label="公开资源"></el-tab-pane>
</el-tabs>
<el-icon class="video-head-icon" @click="isCard = !isCard"><Expand /></el-icon>
</div>
<div class="video-tool-btn">
<router-link to="/resource/other/update">
<el-button type="primary" round>新建其他资料</el-button>
</router-link>
</div>
<AppList v-bind="listOptions" ref="appList">
<template #header-aside></template>
<template #filter-search="{ params }">
<el-input v-model="params.search" placeholder="搜索" :prefix-icon="Search" />
</template>
<template #table-operate="{ row }">
<el-space>
<router-link :to="`/video/update/${row.id}`">
<el-button plain>编辑</el-button>
</router-link>
<router-link :to="`/video/view/${row.id}`">
<el-button type="primary" plain>查看</el-button>
</router-link>
</el-space>
</template>
<!-- 卡片 -->
<template #body="{ data }" v-if="isCard">
<div class="card-list">
<CardListItem v-for="(item, index) in data" :data="item" :key="index"></CardListItem>
</div>
<!-- <div class="resource-video-item" v-for="item in data" :key="item.id">{{ item.title }}</div> -->
</template>
</AppList>
</AppCard>
</template>
<style lang="scss">
.card-list{
background: #FAFAFA;
padding: 20px;
display: flex;
}
.video-head {
position: relative;
.video-head-icon {
position: absolute;
top: 0;
right: 0;
font-size: 30px;
color: #666;
cursor: pointer;
}
}
.video-tool-btn {
padding: 10px 0 30px 0;
}
</style>
<script setup lang="ts">
import UploadAuth from '@/components/base/UploadAuth.vue'
// form表单
const form = reactive({ videoFile: '', videoName: '', videoType: '', zsd: '', aliyun_video_id: '', weight: '' })
const rules = {}
const data = [
{
value: '1',
label: 'Level one 1',
children: [
{
value: '1-1',
label: 'Level two 1-1',
children: [
{
value: '1-1-1',
label: 'Level three 1-1-1',
},
],
},
],
},
{
value: '2',
label: 'Level one 2',
children: [
{
value: '2-1',
label: 'Level two 2-1',
children: [
{
value: '2-1-1',
label: 'Level three 2-1-1',
},
],
},
{
value: '2-2',
label: 'Level two 2-2',
children: [
{
value: '2-2-1',
label: 'Level three 2-2-1',
},
],
},
],
},
{
value: '3',
label: 'Level one 3',
children: [
{
value: '3-1',
label: 'Level two 3-1',
children: [
{
value: '3-1-1',
label: 'Level three 3-1-1',
},
],
},
{
value: '3-2',
label: 'Level two 3-2',
children: [
{
value: '3-2-1',
label: 'Level three 3-2-1',
},
],
},
],
},
]
// 协议
const protocol = ref(false)
// 上传视频过程返回值
const videoUpload = reactive({ code: -1, msg: '', progress: 0, fileName: '' })
// 上传视频回调
const uploadProgress = (res: any) => {
videoUpload.progress = res
}
const upload = (res: any) => {
const { code, msg, name } = res
videoUpload.code = code
videoUpload.msg = msg
videoUpload.fileName = name
videoUpload.progress = 0
}
</script>
<template>
<AppCard title="新建其他资源">
<div class="tool-btn-box" v-if="$route.query.id">
<div class="btn-item">部门共享</div>
<div class="btn-item">平台共享</div>
<div class="btn-item">资源下线</div>
<div class="btn-item">更改负责人</div>
</div>
<el-form ref="formRef" :model="form" :rules="rules" style="width: 70%">
<el-form-item label="资料文件:" prop="course_name">
<div>
<div class="upload-video">
<div class="upload-btn">
本地文件
<UploadAuth @progress="uploadProgress" @upload="upload"></UploadAuth>
</div>
<div class="demo-progress" v-if="videoUpload.code === 1">
<el-progress :percentage="videoUpload.progress" status="success" />
</div>
<div class="error video-info" v-if="videoUpload.code === 2">
<div class="name">上传失败</div>
</div>
<div class="video-info" v-if="videoUpload.code === 0">
<div class="name">{{ videoUpload.fileName }}</div>
<div class="view">查阅</div>
</div>
</div>
<div class="tips">文件支持格式包含:doc docx xls xlsx pdf ppt pptx mp3 mp4 png jpeg jpg,大小不超过200M</div>
</div>
</el-form-item>
<el-form-item label="资料名称:" prop="course_name">
<el-input v-model="form.videoName" />
</el-form-item>
<el-form-item label="资料分类:" prop="course_name">
<el-tree-select style="width:100%" v-model="form.videoType" :data="data" />
</el-form-item>
<el-form-item label="&nbsp;&nbsp;&nbsp;知识点:" prop="course_name">
<el-input
v-model="form.zsd"
:rows="2"
type="textarea"
/>
</el-form-item>
</el-form>
<div class="protocol-box">
<el-checkbox v-model="protocol" size="large">
我已阅读并同意<span>《紫荆教育用户入驻及网络教学资源协议》</span>
</el-checkbox>
</div>
<div class="btn-box">
<div class="confirm">保存</div>
<div class="cancel">取消</div>
</div>
</AppCard>
</template>
<style lang="scss" scoped>
.tips{
font-size: 12px;
line-height: 100%;
color: #999999;
margin-top: 8px;
}
.tool-btn-box{
display: flex;
justify-content: right;
.btn-item{
width: 127px;
line-height: 36px;
background: #AA1941;
border-radius: 20px;
margin-right: 10px;
font-size: 14px;
color: #FFFFFF;
text-align: center;
}
}
.demo-progress{
width: 350px;
}
.video-cover{
display: flex;
.img-box{
width: 208px;
height: 130px;
border-radius: 4px;
background: #F7F7F7;
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
img{
width: 100%;
height: 100%;
display: block;
}
}
.video-cover_right{
margin-left: 20px;
.list{
.item{
display: flex;
align-items: center;
margin-top: 12px;
img{
width: 9px;
display: block;
margin-right: 5px;
}
.text{
font-size: 12px;
color: #999999;
line-height: 100%;
}
}
}
}
}
.swiper-box{
min-width: 660px;
margin-top: 20px;
padding: 0 40px;
position: relative;
.arrow{
position: absolute;
top: 50%;
transform: translateY(-50%);
font-size: 30px;
color: #D5D5D5;
cursor: pointer;
&.left{
left: 0;
}
&.right{
right: 10px;
}
}
.cover-list{
display: flex;
flex-wrap: wrap;
.cover-list_item{
display: block;
width: 155px;
height: 96px;
margin: 0 10px 10px 0;
border-radius: 4px;
cursor: pointer;
}
}
}
:deep(.el-carousel__indicators--horizontal){
display: none;
}
.protocol-box{
font-size: 14px;
line-height: 24px;
padding-left: 90px;
padding-top: 20px;
color: #666666;
span{
color: #AA1941;
}
}
.btn-box{
display: flex;
margin-top: 20px;
margin-left: 90px;
.confirm{
width: 94px;
background: #AA1941;
border-radius: 20px;
text-align: center;
line-height: 36px;
color: #fff;
margin-right: 26px;
cursor: pointer;
}
.cancel{
width: 94px;
line-height: 36px;
border: 1px solid #AA1941;
border-radius: 20px;
text-align: center;
color: #AA1941;
cursor: pointer;
}
}
.upload-video{
display: flex;
align-items: center;
.upload-btn{
position: relative;
width: 94px;
line-height: 36px;
background: rgba(250, 223, 230, 0.39);
border: 1px solid #AA1941;
border-radius: 20px;
font-size: 14px;
color: #AA1941;
margin-right: 30px;
text-align: center;
}
.video-info{
display: flex;
.name{
color: #333333;
font-size: 16px;
line-height: 100%;
}
.view{
font-size: 16px;
line-height: 100%;
color: #399EE8;
margin-left: 20px;
cursor: pointer;
}
}
}
</style>
<script setup lang="ts">
import TopInfo from '../components/view/TopInfo.vue'
import CenterInfo from '../components/view/CenterInfo.vue'
import BottomInfo from '../components/view/BottomInfo.vue'
const listOptions = {
columns: [
{ label: '课程图片', prop: 'img', align: 'center' },
{ label: '课程名称', prop: 'cursor_name', align: 'center' },
{ label: '分类名称', prop: 'type_name', align: 'center' },
{ label: '所在章', slots: 'zhang', align: 'center' },
{ label: '所在小结', prop: 'jie', align: 'center' },
{ label: '创建日期', prop: 'update', align: 'center' },
{ label: '操作', slots: 'table-operate', align: 'center' }
],
data: [
{ img: 1, cursor_name: '宏观经济学.pptx', type_name: '1', zhang: '1', jie: '吉林师范大学', update: '王重阳' },
{ img: 2, cursor_name: '宏观经济学.pptx', type_name: '2', zhang: '2', jie: '吉林师范大学', update: '王重阳' },
{ img: 3, cursor_name: '宏观经济学.pptx', type_name: '3', zhang: '3', jie: '吉林师范大学', update: '王重阳' },
{ img: 4, cursor_name: '宏观经济学.pptx', type_name: '4', zhang: '4', jie: '吉林师范大学', update: '王重阳' },
{ img: 5, cursor_name: '宏观经济学.pptx', type_name: '5', zhang: '5', jie: '吉林师范大学', update: '王重阳' }
]
}
</script>
<template>
<AppCard title="课件资源信息">
<div class="btn-box">
<div class="btn-item">部门共享</div>
<div class="btn-item">平台共享</div>
<div class="btn-item">资源下线</div>
<div class="btn-item">更改负责人</div>
</div>
<TopInfo></TopInfo>
<CenterInfo></CenterInfo>
<BottomInfo></BottomInfo>
</AppCard>
<AppCard title="课件资源关联使用课程">
<AppList v-bind="listOptions" ref="appList" stripe>
<template #table-operate="{ row }">
<el-space>
<router-link :to="`/video/update/${row.id}`">
<el-button
style="color: #399EE8;"
type="primary"
link
>查看</el-button
>
</router-link>
</el-space>
</template>
</AppList>
</AppCard>
</template>
<style lang="scss" scoped>
.btn-box{
display: flex;
justify-content: right;
.btn-item{
width: 127px;
line-height: 36px;
background: #AA1941;
border-radius: 20px;
margin-right: 10px;
font-size: 14px;
color: #FFFFFF;
text-align: center;
}
}
</style>
......@@ -2,12 +2,22 @@ import httpRequest from '@/utils/axios'
// 获取视频列表
export function getVideoList(params?: { type?: string; page?: number; page_size?: number }) {
return httpRequest.get('/api/psp/backend/video/index', { params })
return httpRequest.get('/api/resource/v1/resource/video/list', { params })
}
// 创建视频
export function createVideo(data: { course_name: string; cover_page: string; type: string; weight?: string }) {
return httpRequest.post('/api/psp/backend/video/create', data)
export function createVideo(data: { name: string; source: string; classification: string; knowledge_points: string; cover: string; source_id: string }) {
return httpRequest.post('/api/resource/v1/resource/video/create', data)
}
// 获取分类列表
export function getCategoryList(params: { type: string; category_name?: string }) {
return httpRequest.get('/api/resource/v1/backend/category/list', { params })
}
// 获取封面列表
export function getCoverList() {
return httpRequest.get('/api/resource/v1/util/get-cover-list')
}
// 更新视频
......
<script setup lang="ts">
// const props = defineProps<{ data: object }>()
const props:any = defineProps<{ data: object }>()
</script>
<template>
<!-- <div>{{ props.data }}</div> -->
<div class="card-item">
<div class="card-item-top">
<div class="title">基金产品(中)(初级)</div>
<img src="http://iph.href.lu/265x170" />
<div class="title">{{ props.data.name }}</div>
<!-- <img :src="props.data.cover" /> -->
<div class="cover-img" :style="`background-image:url(${props.data.cover})`"></div>
<div class="tool-pop-btn">
<router-link to="/resource/video/update">
<div class="edit-btn">编辑</div>
</router-link>
<router-link to="/resource/video/view">
<div class="view-btn">查看</div>
</router-link>
</div>
</div>
<div class="card-item-bottom">
<div class="item-t">
<div class="text">张三丰/紫荆教育</div>
<div class="tag green">失效</div>
<div class="text">{{ props.data.created_operator_name }}/{{ props.data.organ_id_name }}</div>
<div :class="props.data.status == 1 ? 'tag green' : 'tag'">{{ props.data.status_name }}</div>
</div>
<div class="item-b">
<div class="time">2022-03-21 12:34:21</div>
<div class="tag">新建</div>
<div class="time">{{ props.data.updated_time }}</div>
<!-- <div class="tag">新建</div> -->
</div>
</div>
</div>
......@@ -39,10 +44,10 @@
opacity: 1;
}
}
img {
.cover-img {
width: 100%;
height: 100%;
display: block;
background-size: cover;
}
.title {
position: absolute;
......
<script lang="ts" setup>
import { ElMessage } from 'element-plus'
// import { Plus } from '@element-plus/icons-vue'
import type { UploadProps, UploadUserFile } from 'element-plus'
import md5 from 'blueimp-md5'
import { getSignature } from '@/api/base'
const props = withDefaults(defineProps<{ modelValue: string | []; prefix?: string }>(), {
prefix: 'upload/admin/'
})
const emit = defineEmits(['update:modelValue'])
const uploadData = ref()
const fileList = ref<UploadUserFile[]>([])
watch(
() => props.modelValue,
value => {
fileList.value = Array.isArray(value) ? [...value] : []
}
)
const showFileList = computed(() => {
return Array.isArray(props.modelValue)
})
// 上传之前
const handleBeforeUpload = async (file: any) => {
const fileName = file.name
const key = props.prefix + md5(fileName + new Date().getTime()) + fileName.substr(fileName.lastIndexOf('.'))
const response: Record<string, any> = await getSignature()
uploadData.value = {
key,
OSSAccessKeyId: response.accessid,
policy: response.policy,
signature: response.signature,
success_action_status: '200',
url: `${response.host}/${key}`
}
file.url = `${response.host}/${key}`
}
// 上传成功
const handleSuccess = (response: any, file: any, files: any) => {
if (!files.every((item: any) => item.status === 'success')) return
if (showFileList.value) {
emit(
'update:modelValue',
files.map((item: any) => {
return { name: item.name, url: item.url || item.raw.url }
})
)
} else {
emit('update:modelValue', file.raw.url)
}
}
// 上传限制
const handleExceed: UploadProps['onExceed'] = () => {
ElMessage.warning('文件超出个数限制')
}
// 删除
const handleRemove: UploadProps['onRemove'] = (file, files) => {
emit(
'update:modelValue',
files.map((item: any) => {
return { name: item.name, url: item.url || item.raw.url }
})
)
}
// 预览
const handlePreview: UploadProps['onPreview'] = uploadFile => {
console.log(uploadFile)
}
</script>
<template>
<el-upload
action="https://webapp-pub.oss-cn-beijing.aliyuncs.com"
:data="uploadData"
:show-file-list="showFileList"
:before-upload="handleBeforeUpload"
:on-exceed="handleExceed"
:on-remove="handleRemove"
:on-preview="handlePreview"
:on-success="handleSuccess"
:file-list="fileList"
class="uploader"
>
<el-button type="primary">选择本地图片</el-button>
</el-upload>
</template>
<style lang="scss">
.uploader {
flex: 1;
}
.avatar-uploader {
width: 178px;
height: 178px;
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
.el-image {
width: 100%;
height: 100%;
}
}
.avatar-uploader:hover {
border-color: var(--el-color-primary);
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 100%;
height: 100%;
text-align: center;
}
</style>
<script setup lang="ts">
import * as echarts from "echarts"
const echartsRef = ref()
onMounted(() => {
const myEcharts = echarts.init(echartsRef.value)
const option = {
grid: {
bottom: 30,
left: 30,
right: 30
},
xAxis: {
data: ['2022-02-21', '2022-02-21', '2022-02-21', '2022-02-21', '2022-02-21', '2022-02-21'],
axisTick: {
show: false
}
},
color: ['#BF9D6B'],
yAxis: {},
series: [
{
type: 'bar',
barWidth: '18',
data: [5, 20, 36, 10, 10, 20]
}
],
}
//设置配置
myEcharts.setOption(option)
})
const listOptions = {
columns: [
{ label: '访问时间', prop: 'name', align: 'center' },
{ label: '姓名', prop: 'bumen', align: 'center' },
{ label: '所在项目', prop: 'update', align: 'center' },
{ label: '访问时长', prop: 'time', align: 'center' }
],
data: [
{ time: '111', id: 1, name: '宏观经济学.pptx', type: '1', index: '1', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
{ time: '111', id: 2, name: '宏观经济学.pptx', type: '2', index: '2', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
{ time: '111', id: 3, name: '宏观经济学.pptx', type: '3', index: '3', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
{ time: '111', id: 4, name: '宏观经济学.pptx', type: '4', index: '4', bumen: '吉林师范大学', update: '王重阳', relation: '22' },
]
}
</script>
<template>
<div class="data-box">
<div class="echart">
<div class="name">访问量/关联量一周走势图</div>
<div
class="echarts"
ref="echartsRef"
:style="{
width: '600px',
height: '300px'
}"
></div>
</div>
<div class="label-box">
<div class="name">最近访问</div>
<AppList v-bind="listOptions" ref="appList" stripe></AppList>
</div>
</div>
<!-- <div
class="echarts"
ref="echartsRef"
:style="{
width: '600px',
height: '300px'
}"
></div> -->
</template>
<style lang="scss" scoped>
.data-box{
display: flex;
.echart{
flex: 1;
height: 369px;
box-sizing: border-box;
border: 1px solid #E0E0E0;
border-radius: 10px;
margin-right: 10px;
padding: 20px;
.name{
font-size: 16px;
line-height: 100%;
color: #333333;
}
}
.label-box{
box-sizing: border-box;
flex: 1;
height: 369px;
border: 1px solid #E0E0E0;
border-radius: 10px;
margin-left: 10px;
padding: 20px;
.name{
font-size: 16px;
line-height: 100%;
color: #333333;
}
}
}
</style>
<script setup lang="ts">
</script>
<template>
<div class="center-video-box">
<video width="812" height="433" controls>
<source src="https://video.shipin520.com/videos/17/36/71/b_KSyZ5ujXfz7R1567173671.mp4" type="video/mp4">
</video>
<div class="right-statistics">
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon1.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">使用项目/学校</div>
</div>
</div>
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon2.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">使用课程</div>
</div>
</div>
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon3.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">累计学习人次</div>
</div>
</div>
<div class="stat-item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/view-vicon4.png">
<div class="content">
<div class="unit">758<span></span></div>
<div class="tag">累计学习时长</div>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.center-video-box{
padding: 20px 0;
display: flex;
.right-statistics{
flex: 1;
padding-top: 15px;
.stat-item{
width: 210px;
height: 85px;
background: #B41E47;
border-radius: 6px;
display: flex;
align-items: center;
margin: 0 auto 20px;
&:nth-child(even){
background: #BF9D6B;
}
img{
width: 52px;
height: 52px;
display: block;
margin-left: 18px;
}
.content{
margin-left: 18px;
.unit{
font-size: 26px;
line-height: 100%;
color: #FFFFFF;
span{
font-size: 12px;
line-height: 100%;
}
}
.tag{
font-size: 14px;
line-height: 100%;
color: #FFFFFF;
margin-top: 10px;
}
}
}
}
}
</style>
<script setup lang="ts">
</script>
<template>
<div class="video-info">
<div class="video-img">
<img src="https://iph.href.lu/211x146">
<div class="name">视频封面</div>
</div>
<div class="info-items">
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon1.png" class="icons">
<div class="text-box">
<div class="name">状态</div>
<div class="value active">有效</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon12.png" class="icons">
<div class="text-box">
<div class="name">创建者</div>
<div class="value">张三丰</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon3.png" class="icons">
<div class="text-box">
<div class="name">创建时间</div>
<div class="value">2021-08-09 12:32:21</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon4.png" class="icons">
<div class="text-box">
<div class="name">更新时间</div>
<div class="value">2021-08-09 12:32:21</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon5.png" class="icons">
<div class="text-box">
<div class="name">视频名称</div>
<div class="value">基金产品(中)(初级)</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon6.png" class="icons">
<div class="text-box">
<div class="name">资源来源</div>
<div class="value">金融产品数字化营销-黄老师</div>
</div>
</div>
<div class="i-items">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon7.png" class="icons">
<div class="text-box">
<div class="name">视频分类</div>
<div class="value">金融产品数字化营销-黄老师</div>
</div>
</div>
<div class="i-items" style="align-items: flex-start;">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/video-view-icon8.png" class="icons">
<div class="text-box">
<div class="name">知识点</div>
<div class="textarea-box">
某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某某
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.video-info{
background: #F7F7F7;
margin-top: 20px;
padding: 20px;
display: flex;
.video-img{
width: 211px;
img{
width: 211px;
display: block;
}
.name{
font-size: 16px;
line-height: 100%;
color: #666666;
margin-top: 12px;
text-align: center;
}
}
.info-items{
display: flex;
flex-wrap: wrap;
padding-left: 12px;
.i-items{
display: flex;
align-items: center;
height: fit-content;
margin-right: 80px;
margin-bottom: 30px;
.textarea-box{
padding: 18px 18px 51px;
background: #FFFFFF;
border-radius: 4px;
font-size: 16px;
line-height: 24px;
color: #505050;
margin-top: 14px;
}
.text-box{
margin-left: 16px;
.name{
font-size: 14px;
line-height: 100%;
color: #999999;
}
.value{
font-size: 16px;
font-weight: bold;
line-height: 100%;
color: #333333;
margin-top: 8px;
&.active{
color: #1AB226;
}
}
}
}
}
}
</style>
......@@ -7,8 +7,10 @@ export const routes: Array<RouteRecordRaw> = [
component: AppLayout,
children: [
{ path: '', component: () => import('./views/List.vue') },
{ path: 'create', component: () => import('./views/Update.vue') },
{ path: 'update/:id', component: () => import('./views/Update.vue'), props: true }
{ path: 'update', component: () => import('./views/Update.vue') },
{ path: 'view', component: () => import('./views/View.vue') },
{ path: 'edit-courseware', component: () => import('./views/EditCourseware.vue') }
// { path: 'update/:id', component: () => import('./views/Update.vue'), props: true }
]
}
]
<script setup lang="ts">
import TopInfo from '../components/view/TopInfo.vue'
const listOptions = {
columns: [
{ label: '课程图片', prop: 'img', align: 'center' },
{ label: '文件名', prop: 'file_name', align: 'center' },
{ label: '时码', slots: 'table-operate', align: 'center' }
],
data: [
{ img: 1, cursor_name: '宏观经济学.pptx', type_name: '1', zhang: '1', jie: '吉林师范大学', update: '王重阳' },
{ img: 2, cursor_name: '宏观经济学.pptx', type_name: '2', zhang: '2', jie: '吉林师范大学', update: '王重阳' },
{ img: 3, cursor_name: '宏观经济学.pptx', type_name: '3', zhang: '3', jie: '吉林师范大学', update: '王重阳' },
{ img: 4, cursor_name: '宏观经济学.pptx', type_name: '4', zhang: '4', jie: '吉林师范大学', update: '王重阳' },
{ img: 5, cursor_name: '宏观经济学.pptx', type_name: '5', zhang: '5', jie: '吉林师范大学', update: '王重阳' }
]
}
</script>
<template>
<AppCard title="编辑视频资源">
<!-- <div class="btn-box">
<div class="btn-item">编辑视频信息</div>
<div class="btn-item">编辑视频课件</div>
<div class="btn-item">部门共享</div>
<div class="btn-item">平台共享</div>
<div class="btn-item">资源下线</div>
<div class="btn-item">更改负责人</div>
</div> -->
<TopInfo></TopInfo>
</AppCard>
<AppCard>
<el-button type="primary">关联课件</el-button>
<AppList v-bind="listOptions" ref="appList" stripe>
<template #table-operate="{ row }">
<el-space>
<router-link :to="`/video/update/${row.id}`">
<el-button
style="color: #399EE8;"
type="primary"
link
>查看</el-button
>
</router-link>
</el-space>
</template>
</AppList>
</AppCard>
</template>
<style lang="scss" scoped>
.btn-box{
display: flex;
justify-content: right;
.btn-item{
width: 127px;
line-height: 36px;
background: #AA1941;
border-radius: 20px;
margin-right: 10px;
font-size: 14px;
color: #FFFFFF;
text-align: center;
}
}
</style>
<script setup lang="ts">
// import { getVideoList } from '../api'
import { getVideoList } from '../api'
import CardListItem from '../components/CardListItem.vue'
import { Expand, Search } from '@element-plus/icons-vue'
......@@ -9,8 +9,8 @@ const isCard = ref(true)
const listOptions = {
remote: {
// httpRequest: getVideoList,
params: { type: '' },
httpRequest: getVideoList,
params: { title: '' },
beforeRequest(params: any) {
// params.type = 选项卡类型
return params
......@@ -20,20 +20,20 @@ const listOptions = {
{ type: 'select', prop: 'type', label: '状态' },
{ type: 'select', prop: 'project_id', label: '项目' },
{ type: 'select', prop: 'category_id', label: '类别' },
{ prop: 'search', slots: 'filter-search' }
{ prop: 'title', slots: 'filter-search' }
// { type: 'input', prop: 'category_id', prefixIcon: 'Search' }
],
columns: [
{ label: '视频标题', prop: 'title' },
{ label: '视频分类', prop: 'type' },
{ label: '知识点', prop: 'zsd' },
{ label: '封面', slots: 'table-cover', width: 100 },
{ label: '资源状态', prop: 'state' },
{ label: '审核状态', prop: 'state2' },
{ label: '更新人', prop: 'update' },
{ label: '更新人部门', prop: 'updatebm' },
{ label: '更新日期', prop: 'update_time' },
{ label: '操作', slots: 'table-operate', align: 'right' }
{ label: '视频标题', prop: 'name', align: 'center' },
{ label: '视频分类', prop: 'classification_name', align: 'center' },
{ label: '知识点', prop: 'knowledge_points', align: 'center' },
{ label: '封面', slots: 'table-cover', width: 150, align: 'center' },
{ label: '资源状态', prop: 'status_name', align: 'center' },
{ label: '审核状态', prop: 'audit_status_name', align: 'center' },
{ label: '更新人', prop: 'updated_operator_name', align: 'center' },
{ label: '更新人部门', prop: 'organ_id_name', align: 'center' },
{ label: '更新日期', prop: 'updated_time', align: 'center' },
{ label: '操作', slots: 'table-operate', align: 'center' }
],
data: [
{ id: 1, title: '视频标题', type: '视频分类' },
......@@ -44,31 +44,33 @@ const listOptions = {
<template>
<AppCard>
<!-- <el-switch v-model="isCard"></el-switch> -->
<div class="video-head">
<el-tabs>
<el-tab-pane label="个人资源"></el-tab-pane>
<el-tab-pane label="我的资源"></el-tab-pane>
<el-tab-pane label="部门资源"></el-tab-pane>
<el-tab-pane label="公开资源"></el-tab-pane>
</el-tabs>
<el-icon class="video-head-icon" @click="isCard = !isCard"><Expand /></el-icon>
</div>
<div class="video-tool-btn">
<router-link to="/resource/video/create">
<router-link to="/resource/video/update">
<el-button type="primary" round>新建视频资源</el-button>
</router-link>
</div>
<AppList v-bind="listOptions" ref="appList">
<template #header-aside></template>
<template #table-cover="{ row }">
<img :src="row.cover" style="width:150px;display: block;">
</template>
<template #filter-search="{ params }">
<el-input v-model="params.search" placeholder="搜索" :prefix-icon="Search" />
<el-input v-model="params.title" placeholder="搜索" :prefix-icon="Search" />
</template>
<template #table-operate="{ row }">
<el-space>
<router-link :to="`/video/update/${row.id}`">
<router-link :to="`/resource/video/update/${row.id}`">
<el-button plain>编辑</el-button>
</router-link>
<router-link :to="`/video/view/${row.id}`">
<router-link :to="`/resource/video/view/${row.id}`">
<el-button type="primary" plain>查看</el-button>
</router-link>
</el-space>
......@@ -76,7 +78,7 @@ const listOptions = {
<!-- 卡片 -->
<template #body="{ data }" v-if="isCard">
<div class="card-list">
<div class="card-list" v-if="data.length">
<CardListItem v-for="(item, index) in data" :data="item" :key="index"></CardListItem>
</div>
<!-- <div class="resource-video-item" v-for="item in data" :key="item.id">{{ item.title }}</div> -->
......
<script setup lang="ts">
import { ElMessage } from 'element-plus'
import type { FormInstance } from 'element-plus'
import { createVideo, updateVideo, getVideo } from '../api'
import { PictureFilled, ArrowLeftBold, ArrowRightBold } from '@element-plus/icons-vue'
import type { FormInstance } from 'element-plus'
import { ElMessage } from 'element-plus'
import Upload from '../components/Upload.vue'
import UploadAuth from '@/components/base/UploadAuth.vue'
// import { useMapStore } from '@/stores/map'
import { getCategoryList, getCoverList, createVideo } from '../api'
// const store= useMapStore()
// console.log(store)
// const statusList = store.mapList.filter((item: any) => item.key === 'system_status')[0].values
const props = defineProps<{ id?: string }>()
// 路由
const router = useRouter()
const router = useRouter()
// 下拉选择tree 视频分类
let selectTree = $ref([])
getCategoryList({ type: 'tree' }).then((res) => {
selectTree = res.data
})
const defaultProps = {
children: 'children',
label: 'category_name',
value: 'id'
}
const formRef = ref<FormInstance>()
const form = reactive({ course_name: '', type: '', cover_page: '', aliyun_video_id: '', weight: '' })
const rules = {
course_name: [{ required: true, message: '请输入标题', trigger: 'blur' }],
type: [{ required: true, message: '请选择类型', trigger: 'change' }],
cover_page: [{ required: true, message: '请上传视频封面图片', trigger: 'change' }],
aliyun_video_id: [{ required: true, message: '请输入阿里云播放视频ID', trigger: 'blur' }]
}
const typeList = [
{ label: '入学指南', value: '1' },
{ label: '学习地图', value: '2' },
{ label: '考试攻略', value: '3' }
]
// 提交
const onSubmit = () => {
if (!formRef.value) return
formRef.value.validate().then(() => {
props.id ? update() : create()
// 视频封面图轮播
let swiperCovers: [{ id: string, url: string }[]] = $ref([[]])
// 获取封面
getCoverList().then(res => {
let arr:object[] = []
swiperCovers = res.data.list.reduce((a: any, b: any, index: number) => {
if (index === 0) {
arr.push(b)
a.push(arr)
} else {
if (index % 8 === 0) {
arr = []
a.push(arr)
} else {
arr.push(b)
}
}
return a
}, [])
})
}
// 取消
const onCancel = () => {
router.replace('/video')
}
// 创建
const create = () => {
createVideo(form).then(() => {
// 获取swiper 自定义左右切换按钮
let swiper = ref()
const swiperChange = (type?: string) => {
type === 'prev' ? swiper.value.prev() : swiper.value.next()
}
const swiperItemHandle = (url: string) => {
form.cover = url
console.log(url)
}
// form表单 提交
const form = reactive({ name: '', source: '2', classification: '', knowledge_points: '', cover: '', source_id: '' })
// 表单验证
const rules = {
name: [{ required: true, message: '请输入标题', trigger: 'blur' }],
classification: [{ required: true, message: '请选择分类', trigger: 'change' }],
source_id: [{ required: true, message: '' }]
}
const ruleFormRef = ref<FormInstance>()
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
if (!protocol.value) {
ElMessage('请勾选用户协议')
return
}
createVideo(form).then((res:any) => {
if (res.code === 0) {
ElMessage({ message: '创建成功', type: 'success' })
router.push('/video')
setTimeout(() => {
router.push({
path: '/resource/video'
})
}
// 修改
const update = () => {
const params = { ...form, id: props.id as string }
updateVideo(params).then(() => {
ElMessage({ message: '修改成功', type: 'success' })
router.push('/video')
}, 1000)
}
})
}
onMounted(() => {
props.id &&
getVideo({ id: props.id }).then(res => {
Object.assign(form, res.data)
} else {
ElMessage('请完善信息')
console.log('error submit!', fields)
}
})
})
}
// 协议勾选
const protocol = ref(false)
// 上传视频过程返回值
const videoUpload = reactive({ code: -1, msg: '', progress: 0, fileName: '' })
// 上传视频回调
const uploadProgress = (res: any) => {
videoUpload.progress = res
}
const upload = (res: any) => {
const { code, msg, name, videoId } = res
videoUpload.code = code
videoUpload.msg = msg
videoUpload.fileName = name
videoUpload.progress = 0
form.source_id = videoId
}
</script>
<template>
<AppCard>
<el-form ref="formRef" :model="form" :rules="rules" label-width="140px">
<el-form-item label="标题" prop="course_name">
<el-input v-model="form.course_name" />
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select v-model="form.type">
<el-option v-for="item in typeList" :label="item.label" :value="item.value" :key="item.value"></el-option>
</el-select>
<AppCard title="新建视频资源">
<div class="tool-btn-box" v-if="$route.query.id">
<div class="btn-item">部门共享</div>
<div class="btn-item">平台共享</div>
<div class="btn-item">资源下线</div>
<div class="btn-item">更改负责人</div>
</div>
<el-form ref="ruleFormRef" :model="form" :rules="rules" style="width: 70%">
<el-form-item label="视频文件:" prop="source_id">
<div>
<div class="upload-video">
<div class="upload-btn">
本地文件
<UploadAuth @progress="uploadProgress" @upload="upload"></UploadAuth>
</div>
<div class="demo-progress" v-if="videoUpload.code === 1">
<el-progress :percentage="videoUpload.progress" status="success" />
</div>
<div class="error video-info" v-if="videoUpload.code === 2">
<div class="name">上传失败</div>
</div>
<div class="video-info" v-if="videoUpload.code === 0">
<div class="name">{{ videoUpload.fileName }}</div>
<!-- <div class="view">查阅</div> -->
</div>
</div>
<div class="tips">推荐视频格式:帧率为25fps\输出码率为4M\输出格式为mp4,建议采用格式工厂等工具处理后上传。</div>
</div>
</el-form-item>
<el-form-item label="权重" prop="weight">
<el-input type="number" v-model="form.weight" controls-position="right" />
<el-form-item label="视频名称:" prop="name">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="视频封面" prop="cover_page">
<AppUpload v-model="form.cover_page"></AppUpload>
<el-form-item label="视频分类:" prop="classification">
<el-tree-select :props="defaultProps" style="width:100%" v-model="form.classification" :data="selectTree" />
</el-form-item>
<el-form-item label="阿里云播放视频ID" prop="aliyun_video_id">
<el-input v-model="form.aliyun_video_id" />
<el-form-item label="&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;知识点:">
<el-input
v-model="form.knowledge_points"
:rows="2"
type="textarea"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" auto-insert-space @click="onSubmit">保存</el-button>
<el-button auto-insert-space @click="onCancel">取消</el-button>
<el-form-item label="&nbsp;&nbsp;视频封面:">
<div class="video-cover">
<div class="img-box">
<el-icon :size="50" color="#ccc" v-if="form.cover == ''">
<PictureFilled></PictureFilled>
</el-icon>
<img :src="form.cover" v-else>
</div>
<div class="video-cover_right">
<Upload v-model="form.cover"></Upload>
<div class="list">
<div class="item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/upload-video-icon.png" class="icon">
<div class="text">该图片作为课程的宣传图,用于课程主要的显示</div>
</div>
<div class="item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/upload-video-icon.png" class="icon">
<div class="text">支持jpg/jpeg/gif/png格式</div>
</div>
<div class="item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/upload-video-icon.png" class="icon">
<div class="text">支持小鱼4M,最好宽240*高175*及以上尺寸 </div>
</div>
<div class="item">
<img src="https://webapp-pub.oss-cn-beijing.aliyuncs.com/center_resource/upload-video-icon.png" class="icon">
<div class="text">想可以自己上传图片,也可以从下面这些图片中选择使用</div>
</div>
</div>
</div>
</div>
<div class="swiper-box">
<div class="block text-center" v-if="swiperCovers.length">
<el-carousel height="202px" :autoplay="false" arrow="never" trigger="click" ref="swiper">
<el-carousel-item v-for="(item, index) in swiperCovers" :key="index" class="cover-list">
<img @click="swiperItemHandle(cItem.url)" :key="cItem.id" v-for="cItem in item" :src="cItem.url" class="cover-list_item">
</el-carousel-item>
</el-carousel>
</div>
<el-icon class="arrow left" @click="swiperChange('prev')"><ArrowLeftBold /></el-icon>
<el-icon class="arrow right" @click="swiperChange"><ArrowRightBold /></el-icon>
</div>
</el-form-item>
</el-form>
<div class="protocol-box">
<el-checkbox v-model="protocol" size="large">
我已阅读并同意<span>《紫荆教育用户入驻及网络教学资源协议》</span>
</el-checkbox>
</div>
<div class="btn-box">
<div class="confirm" @click="submitForm(ruleFormRef)">保存</div>
<div class="cancel">取消</div>
</div>
</AppCard>
</template>
<style lang="scss" scoped>
.tips{
font-size: 12px;
line-height: 100%;
color: #999999;
margin-top: 8px;
}
.tool-btn-box{
display: flex;
justify-content: right;
.btn-item{
width: 127px;
line-height: 36px;
background: #AA1941;
border-radius: 20px;
margin-right: 10px;
font-size: 14px;
color: #FFFFFF;
text-align: center;
}
}
.demo-progress{
width: 350px;
}
.video-cover{
display: flex;
.img-box{
width: 208px;
height: 130px;
border-radius: 4px;
background: #F7F7F7;
font-size: 20px;
display: flex;
align-items: center;
justify-content: center;
img{
width: 100%;
// height: 100%;
display: block;
}
}
.video-cover_right{
margin-left: 20px;
.list{
.item{
display: flex;
align-items: center;
margin-top: 12px;
img{
width: 9px;
display: block;
margin-right: 5px;
}
.text{
font-size: 12px;
color: #999999;
line-height: 100%;
}
}
}
}
}
.swiper-box{
min-width: 660px;
margin-top: 20px;
padding: 0 40px;
position: relative;
.arrow{
position: absolute;
top: 50%;
transform: translateY(-50%);
font-size: 30px;
color: #D5D5D5;
cursor: pointer;
&.left{
left: 0;
}
&.right{
right: 10px;
}
}
.cover-list{
display: flex;
flex-wrap: wrap;
.cover-list_item{
display: block;
width: 155px;
height: 96px;
margin: 0 10px 10px 0;
border-radius: 4px;
cursor: pointer;
}
}
}
:deep(.el-carousel__indicators--horizontal){
display: none;
}
.protocol-box{
font-size: 14px;
line-height: 24px;
padding-left: 90px;
padding-top: 20px;
color: #666666;
span{
color: #AA1941;
}
}
.btn-box{
display: flex;
margin-top: 20px;
margin-left: 90px;
.confirm{
width: 94px;
background: #AA1941;
border-radius: 20px;
text-align: center;
line-height: 36px;
color: #fff;
margin-right: 26px;
cursor: pointer;
}
.cancel{
width: 94px;
line-height: 36px;
border: 1px solid #AA1941;
border-radius: 20px;
text-align: center;
color: #AA1941;
cursor: pointer;
}
}
.upload-video{
display: flex;
align-items: center;
.upload-btn{
position: relative;
width: 94px;
line-height: 36px;
background: rgba(250, 223, 230, 0.39);
border: 1px solid #AA1941;
border-radius: 20px;
font-size: 14px;
color: #AA1941;
margin-right: 30px;
text-align: center;
}
.video-info{
display: flex;
.name{
color: #333333;
font-size: 16px;
line-height: 100%;
}
.view{
font-size: 16px;
line-height: 100%;
color: #399EE8;
margin-left: 20px;
cursor: pointer;
}
}
}
</style>
<!-- <script setup lang="ts">
import { ElMessage } from 'element-plus'
import type { FormInstance } from 'element-plus'
import { createVideo, updateVideo, getVideo } from '../api'
const props = defineProps<{ id?: string }>()
const router = useRouter()
const formRef = ref<FormInstance>()
const form = reactive({ course_name: '', type: '', cover_page: '', aliyun_video_id: '', weight: '' })
const rules = {
course_name: [{ required: true, message: '请输入标题', trigger: 'blur' }],
type: [{ required: true, message: '请选择类型', trigger: 'change' }],
cover_page: [{ required: true, message: '请上传视频封面图片', trigger: 'change' }],
aliyun_video_id: [{ required: true, message: '请输入阿里云播放视频ID', trigger: 'blur' }]
}
const typeList = [
{ label: '入学指南', value: '1' },
{ label: '学习地图', value: '2' },
{ label: '考试攻略', value: '3' }
]
// 提交
const onSubmit = () => {
if (!formRef.value) return
formRef.value.validate().then(() => {
props.id ? update() : create()
})
}
// 取消
const onCancel = () => {
router.replace('/video')
}
// 创建
const create = () => {
createVideo(form).then(() => {
ElMessage({ message: '创建成功', type: 'success' })
router.push('/video')
})
}
// 修改
const update = () => {
const params = { ...form, id: props.id as string }
updateVideo(params).then(() => {
ElMessage({ message: '修改成功', type: 'success' })
router.push('/video')
})
}
onMounted(() => {
props.id &&
getVideo({ id: props.id }).then(res => {
Object.assign(form, res.data)
})
})
</script>
<template>
<AppCard>
<el-form ref="formRef" :model="form" :rules="rules" label-width="140px">
<el-form-item label="标题" prop="course_name">
<el-input v-model="form.course_name" />
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select v-model="form.type">
<el-option v-for="item in typeList" :label="item.label" :value="item.value" :key="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="权重" prop="weight">
<el-input type="number" v-model="form.weight" controls-position="right" />
</el-form-item>
<el-form-item label="视频封面" prop="cover_page">
<AppUpload v-model="form.cover_page"></AppUpload>
</el-form-item>
<el-form-item label="阿里云播放视频ID" prop="aliyun_video_id">
<el-input v-model="form.aliyun_video_id" />
</el-form-item>
<el-form-item>
<el-button type="primary" auto-insert-space @click="onSubmit">保存</el-button>
<el-button auto-insert-space @click="onCancel">取消</el-button>
</el-form-item>
</el-form>
</AppCard>
</template> -->
<script setup lang="ts">
import TopInfo from '../components/view/TopInfo.vue'
import CenterInfo from '../components/view/CenterInfo.vue'
import BottomInfo from '../components/view/BottomInfo.vue'
const listOptions = {
columns: [
{ label: '课程图片', prop: 'img', align: 'center' },
{ label: '课程名称', prop: 'cursor_name', align: 'center' },
{ label: '分类名称', prop: 'type_name', align: 'center' },
{ label: '所在章', slots: 'zhang', align: 'center' },
{ label: '所在小结', prop: 'jie', align: 'center' },
{ label: '创建日期', prop: 'update', align: 'center' },
{ label: '操作', slots: 'table-operate', align: 'center' }
],
data: [
{ img: 1, cursor_name: '宏观经济学.pptx', type_name: '1', zhang: '1', jie: '吉林师范大学', update: '王重阳' },
{ img: 2, cursor_name: '宏观经济学.pptx', type_name: '2', zhang: '2', jie: '吉林师范大学', update: '王重阳' },
{ img: 3, cursor_name: '宏观经济学.pptx', type_name: '3', zhang: '3', jie: '吉林师范大学', update: '王重阳' },
{ img: 4, cursor_name: '宏观经济学.pptx', type_name: '4', zhang: '4', jie: '吉林师范大学', update: '王重阳' },
{ img: 5, cursor_name: '宏观经济学.pptx', type_name: '5', zhang: '5', jie: '吉林师范大学', update: '王重阳' }
]
}
</script>
<template>
<AppCard title="视频资源信息">
<div class="btn-box">
<div class="btn-item">编辑视频信息</div>
<div class="btn-item">编辑视频课件</div>
<div class="btn-item">部门共享</div>
<div class="btn-item">平台共享</div>
<div class="btn-item">资源下线</div>
<div class="btn-item">更改负责人</div>
</div>
<TopInfo></TopInfo>
<CenterInfo></CenterInfo>
<BottomInfo></BottomInfo>
</AppCard>
<AppCard title="视频资源信息">
<AppList v-bind="listOptions" ref="appList" stripe>
<template #table-operate="{ row }">
<el-space>
<router-link :to="`/video/update/${row.id}`">
<el-button
style="color: #399EE8;"
type="primary"
link
>查看</el-button
>
</router-link>
</el-space>
</template>
</AppList>
</AppCard>
</template>
<style lang="scss" scoped>
.btn-box{
display: flex;
justify-content: right;
.btn-item{
width: 127px;
line-height: 36px;
background: #AA1941;
border-radius: 20px;
margin-right: 10px;
font-size: 14px;
color: #FFFFFF;
text-align: center;
}
}
</style>
......@@ -26,6 +26,12 @@ export default defineConfig(({ mode }) => ({
cert: fs.readFileSync(path.join(__dirname, './https/dev.ezijing.com.pem'))
},
proxy: {
'/api/resource': {
// target: 'http://localhost-activity-frontend.ezijing.com',
target: 'http://localhost-resource-backend.ezijing.com',
changeOrigin: true,
rewrite: path => path.replace(/^\/api\/resource/, '')
},
'/api': 'https://learn-api.ezijing.com'
}
},
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论