web-课程列表

This commit is contained in:
2025-10-21 17:59:34 +08:00
parent 9824a7d686
commit eef1c029b4
26 changed files with 2742 additions and 602 deletions

View File

@@ -0,0 +1,92 @@
<template>
<div class="resource-head">
<div class="head-title">{{ title }}</div>
<div class="breadcrumb">
<span class="breadcrumb-label">当前位置</span>
<div class="breadcrumb-nav">
<span class="breadcrumb-item">{{ title }}</span>
<span class="separator">/</span>
<span class="breadcrumb-item">{{ categoryName }}</span>
<span class="separator" v-if="showArticleMode">/</span>
<span class="breadcrumb-item active" v-if="showArticleMode">正文</span>
</div>
</div>
</div>
</template>
<script setup lang="ts">
interface Props {
title?: string;
categoryName?: string;
showArticleMode?: boolean;
}
withDefaults(defineProps<Props>(), {
title: '',
categoryName: '',
showArticleMode: false
});
</script>
<style lang="scss" scoped>
.resource-head {
width: 100%;
height: 250px;
background: url('@/assets/imgs/resource-head-bg.jpg') center/cover;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 10px;
}
.head-title {
font-family: 'MiSans VF', 'PingFang SC';
font-weight: 630;
font-size: 40px;
line-height: 1.2;
letter-spacing: 0.05em;
color: #FFFFFF;
text-align: center;
}
.breadcrumb {
display: flex;
align-items: center;
height: 24px;
}
.breadcrumb-label {
font-family: 'PingFang SC';
font-weight: 500;
font-size: 14px;
line-height: 22px;
color: #F1F1F1;
margin-right: 4px;
}
.breadcrumb-nav {
display: flex;
align-items: center;
gap: 4px;
}
.breadcrumb-item {
font-family: 'PingFang SC';
font-weight: 500;
font-size: 14px;
line-height: 22px;
color: #FFFFFF;
&.active {
color: #FFFFFF;
}
}
.separator {
font-family: 'PingFang SC';
font-size: 14px;
color: #C9CDD4;
}
</style>

View File

@@ -1,36 +1,91 @@
<template>
<div class="menu-nav">
<MenuItem
v-for="menu in menus"
:key="menu.menuID"
:menu="menu"
:collapsed="collapsed"
@menu-click="$emit('menu-click', $event)"
/>
<div class="menu-container">
<div
v-for="menu in menus"
:key="menu.menuID"
class="menu-item"
:class="{ active: isActive(menu) }"
@click="handleMenuClick(menu)"
>
{{ menu.name }}
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useRoute } from 'vue-router';
import type { SysMenu } from '@/types';
// @ts-ignore - Vue 3.5 defineOptions支持递归组件
import MenuItem from './MenuItem.vue';
// Props
interface Props {
menus: SysMenu[];
collapsed?: boolean;
}
defineProps<Props>();
// Emits
defineEmits<{
const emit = defineEmits<{
'menu-click': [menu: SysMenu];
}>();
const route = useRoute();
// 判断菜单是否激活
function isActive(menu: SysMenu): boolean {
if (!menu.url) return false;
return route.path === menu.url || route.path.startsWith(menu.url + '/');
}
// 处理菜单点击
function handleMenuClick(menu: SysMenu) {
emit('menu-click', menu);
}
</script>
<style lang="scss" scoped>
.menu-nav {
padding: 8px 0;
background: #fff;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
.menu-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 24px;
display: flex;
align-items: center;
gap: 20px;
}
.menu-item {
padding: 26px 21px;
height: 62px;
display: flex;
align-items: center;
justify-content: center;
font-family: 'PingFang SC', sans-serif;
font-weight: 500;
font-size: 16px;
line-height: 1.5em;
color: #141F38;
cursor: pointer;
transition: all 0.3s;
white-space: nowrap;
&:hover {
color: #C62828;
}
&.active {
width: 106px;
background: #C62828;
color: #FFFFFF;
font-weight: 600;
&:hover {
color: #FFFFFF;
background: #A82020;
}
}
}
</style>

View File

@@ -0,0 +1,36 @@
<template>
<div class="menu-nav">
<MenuItem
v-for="menu in menus"
:key="menu.menuID"
:menu="menu"
:collapsed="collapsed"
@menu-click="$emit('menu-click', $event)"
/>
</div>
</template>
<script setup lang="ts">
import type { SysMenu } from '@/types';
// @ts-ignore - Vue 3.5 defineOptions支持递归组件
import MenuItem from './MenuItem.vue';
// Props
interface Props {
menus: SysMenu[];
collapsed?: boolean;
}
defineProps<Props>();
// Emits
defineEmits<{
'menu-click': [menu: SysMenu];
}>();
</script>
<style lang="scss" scoped>
.menu-nav {
padding: 8px 0;
}
</style>

View File

@@ -2,6 +2,8 @@ export { default as Breadcrumb } from './Breadcrumb.vue';
export { default as FloatingSidebar } from './FloatingSidebar.vue';
export { default as MenuItem } from './MenuItem.vue';
export { default as MenuNav } from './MenuNav.vue';
export { default as MenuSidebar } from './MenuSidebar.vue';
export { default as TopNavigation } from './TopNavigation.vue';
export { default as UserDropdown } from './UserDropdown.vue';
export { default as Search } from './Search.vue';
export { default as Search } from './Search.vue';
export { default as CenterHead } from './CenterHead.vue';