优化课程列表,添加课程列表详细
8
.env.development
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# 页面标题
|
||||||
|
VITE_APP_TITLE = 若依管理系统
|
||||||
|
|
||||||
|
# 开发环境配置
|
||||||
|
VITE_APP_ENV = 'development'
|
||||||
|
|
||||||
|
# 若依管理系统/开发环境
|
||||||
|
VITE_APP_BASE_API = '/dev-api'
|
11
.env.production
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# 页面标题
|
||||||
|
VITE_APP_TITLE = 若依管理系统
|
||||||
|
|
||||||
|
# 生产环境配置
|
||||||
|
VITE_APP_ENV = 'production'
|
||||||
|
|
||||||
|
# 若依管理系统/生产环境
|
||||||
|
VITE_APP_BASE_API = '/prod-api'
|
||||||
|
|
||||||
|
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
||||||
|
VITE_BUILD_COMPRESS = gzip
|
11
.env.staging
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# 页面标题
|
||||||
|
VITE_APP_TITLE = 若依管理系统
|
||||||
|
|
||||||
|
# 生产环境配置
|
||||||
|
VITE_APP_ENV = 'staging'
|
||||||
|
|
||||||
|
# 若依管理系统/生产环境
|
||||||
|
VITE_APP_BASE_API = '/stage-api'
|
||||||
|
|
||||||
|
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
||||||
|
VITE_BUILD_COMPRESS = gzip
|
BIN
public/img/course/avatar/c-1.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
public/img/course/avatar/c-2.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
public/img/course/list/list-1.png
Normal file
After Width: | Height: | Size: 88 KiB |
BIN
public/img/course/list/list-2.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
public/img/course/list/list-3.png
Normal file
After Width: | Height: | Size: 102 KiB |
BIN
public/img/course/teacher/c-1.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
public/img/course/teacher/c-2.png
Normal file
After Width: | Height: | Size: 25 KiB |
11
src/net/index.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
|
||||||
|
const request = axios.create({
|
||||||
|
// axios中请求配置有baseURL选项,表示请求URL公共部分
|
||||||
|
baseURL: import.meta.env.VITE_APP_BASE_API,
|
||||||
|
// 超时
|
||||||
|
timeout: 10000
|
||||||
|
})
|
||||||
|
|
||||||
|
export default request
|
@ -19,6 +19,10 @@ const router = createRouter({
|
|||||||
path: 'grid',
|
path: 'grid',
|
||||||
name: 'course-grid',
|
name: 'course-grid',
|
||||||
component: () => import('@/views/course/CourseGrid.vue')
|
component: () => import('@/views/course/CourseGrid.vue')
|
||||||
|
}, {
|
||||||
|
path: 'detail/:id',
|
||||||
|
name: 'course-detail',
|
||||||
|
component: () => import('@/views/course/CourseDetail.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,20 @@
|
|||||||
export function createRandomInt() {
|
export function createRandomInt() {
|
||||||
return Math.floor(Math.random() * 100)
|
return Math.floor(Math.random() * 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatTime(seconds) {
|
||||||
|
// 计算小时数
|
||||||
|
const hours = Math.floor(seconds / 3600);
|
||||||
|
// 计算剩余的分钟数
|
||||||
|
const minutes = Math.floor((seconds % 3600) / 60);
|
||||||
|
// 计算剩余的秒数
|
||||||
|
const secs = seconds % 60;
|
||||||
|
|
||||||
|
// 格式化为两位数
|
||||||
|
const formattedHours = String(hours).padStart(2, '0');
|
||||||
|
const formattedMinutes = String(minutes).padStart(2, '0');
|
||||||
|
const formattedSeconds = String(secs).padStart(2, '0');
|
||||||
|
|
||||||
|
// 返回格式化的时间字符串
|
||||||
|
return `${formattedHours}小时 ${formattedMinutes}分 ${formattedSeconds}秒`;
|
||||||
}
|
}
|
224
src/views/course/CourseDetail.vue
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
<script setup>
|
||||||
|
import {useRoute} from "vue-router";
|
||||||
|
import request from "@/net/index.js";
|
||||||
|
import router from "@/router/index.js";
|
||||||
|
import {ref} from "vue";
|
||||||
|
import {createRandomInt, formatTime} from "../../utils/data.js";
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
const id = route.params.id
|
||||||
|
|
||||||
|
const data = ref({})
|
||||||
|
|
||||||
|
if(!id) {
|
||||||
|
router.push('/course/list')
|
||||||
|
}
|
||||||
|
|
||||||
|
request.get(`/system/course/${route.params.id}`).then((res) => {
|
||||||
|
data.value = res.data.data
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="breadcrumb-area-2 bg-overlay-3 relative bg-img"
|
||||||
|
style="background-image: url(/img/bg-img/home-3/bg.png);margin-top: 40px">
|
||||||
|
<div class="container h-100">
|
||||||
|
<div class="row h-100 align-items-center">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="breadcrumb-conetnt">
|
||||||
|
<ul class="bread-list">
|
||||||
|
<li><a href="#">主页</a></li>
|
||||||
|
<li><i class="icon-down-arrow-11"></i></li>
|
||||||
|
<li>{{ data.title }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h4 class="mb-0">{{ data.title }}
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="course-details-area">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<div class="course-details-content-area">
|
||||||
|
<div class="course-heading-details">
|
||||||
|
<div class="course-title">
|
||||||
|
<h2>{{ data.title }}</h2>
|
||||||
|
<a class="inner-btn" href="#">¥{{ data.price }}</a>
|
||||||
|
</div>
|
||||||
|
<div class="course-info-card-area">
|
||||||
|
<!-- Card -->
|
||||||
|
<div class="course-info-card">
|
||||||
|
<h4> 讲师</h4>
|
||||||
|
<div class="course-auth-info-4 d-flex align-items-center">
|
||||||
|
<img class="auth-img" :src="`/img/course/avatar/c-${data.id}.png`" alt="">
|
||||||
|
<p>By <a href="#">{{ data.teacher }}</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Card -->
|
||||||
|
<div class="course-info-card">
|
||||||
|
<h4>评分</h4>
|
||||||
|
<p class="course-rating mb-0"><i class="icon-star1"></i> 4.5 <span>(100 次购买)</span></p>
|
||||||
|
</div>
|
||||||
|
<!-- Card -->
|
||||||
|
<div class="course-info-card">
|
||||||
|
<h4>观看</h4>
|
||||||
|
<p class="course-desc"> {{ createRandomInt() }} 学生正在观看</p>
|
||||||
|
</div>
|
||||||
|
<!-- Card -->
|
||||||
|
<div class="course-info-card">
|
||||||
|
<h4>分类</h4>
|
||||||
|
<p class="course-desc"> 少儿编程</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="course-bg-img">
|
||||||
|
<img :src="`/img/course/list/list-${data.id}.png`" alt="">
|
||||||
|
</div>
|
||||||
|
<div class="course-detials-tab">
|
||||||
|
<ul class="nav nav-pills course-tab-title" id="pills-tab" role="tablist">
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link active" id="pills-home-tab" data-bs-toggle="pill" data-bs-target="#pills-home" type="button" role="tab" aria-controls="pills-home" aria-selected="true"><i class="icon-inclined-pencil"></i> Description</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content" id="pills-tabContent">
|
||||||
|
<div class="tab-pane fade show active" id="pills-home" role="tabpanel" aria-labelledby="pills-home-tab" tabindex="0">
|
||||||
|
<div class="course-details-tab-content">
|
||||||
|
<h4>关于此课程</h4>
|
||||||
|
<p>{{ data.description }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="other-ins-area">
|
||||||
|
<!-- Faq area -->
|
||||||
|
<div class="faq-area course-details">
|
||||||
|
<div class="faq-content-area single-page-faq">
|
||||||
|
<h4>常见问题和解答</h4>
|
||||||
|
<div class="accordion" id="accordionExample">
|
||||||
|
<div class="accordion-item wow fadeInUp" data-wow-delay="700ms" style="visibility: visible; animation-delay: 700ms; animation-name: fadeInUp;">
|
||||||
|
<h2 class="accordion-header">
|
||||||
|
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
|
||||||
|
1. 学习少儿编程有什么好处呢?
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div id="collapseOne" class="accordion-collapse collapse show" data-bs-parent="#accordionExample">
|
||||||
|
<div class="accordion-body">
|
||||||
|
<p>"锻炼宝宝体制,促进大脑发育,保证学生身心健康。从小学习编程,可以领先别人一大截,别人到了
|
||||||
|
大学才开始学,而你家宝宝小学就可以去打竞赛了,随随便便都可以吊打大学生,直接赢在起跑线上,
|
||||||
|
这样过年回家就可以在亲戚面前炫耀一番了"</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="accordion-item wow fadeInUp" data-wow-delay="900ms" style="visibility: visible; animation-delay: 900ms; animation-name: fadeInUp;">
|
||||||
|
<h2 class="accordion-header">
|
||||||
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
|
||||||
|
2. Do you offer any extracurricular activities for the
|
||||||
|
students?
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div id="collapseTwo" class="accordion-collapse collapse" data-bs-parent="#accordionExample">
|
||||||
|
<div class="accordion-body">
|
||||||
|
<p>"Edumastery has been an amazing experience for our
|
||||||
|
daughter, Lily.
|
||||||
|
The
|
||||||
|
inclusive and enriching atmosphere has not only helped
|
||||||
|
her academic
|
||||||
|
growth
|
||||||
|
but has also fostered her social and emotional
|
||||||
|
development. We are
|
||||||
|
grateful
|
||||||
|
for the caring and dedicated staff."</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="accordion-item wow fadeInUp" data-wow-delay="1100ms" style="visibility: visible; animation-delay: 1100ms; animation-name: fadeInUp;">
|
||||||
|
<h2 class="accordion-header">
|
||||||
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
|
||||||
|
3. What is your approach to handling children ?
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div id="collapseThree" class="accordion-collapse collapse" data-bs-parent="#accordionExample">
|
||||||
|
<div class="accordion-body">
|
||||||
|
<p>"Edumastery has been an amazing experience for our
|
||||||
|
daughter, Lily.
|
||||||
|
The
|
||||||
|
inclusive and enriching atmosphere has not only helped
|
||||||
|
her academic
|
||||||
|
growth
|
||||||
|
but has also fostered her social and emotional
|
||||||
|
development. We are
|
||||||
|
grateful
|
||||||
|
for the caring and dedicated staff."</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="accordion-item wow fadeInUp" data-wow-delay="1300ms" style="visibility: visible; animation-delay: 1300ms; animation-name: fadeInUp;">
|
||||||
|
<h2 class="accordion-header">
|
||||||
|
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseFour" aria-expanded="false" aria-controls="collapseFour">
|
||||||
|
4. How do you ensure the safety of the children on the
|
||||||
|
premises?
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div id="collapseFour" class="accordion-collapse collapse" data-bs-parent="#accordionExample">
|
||||||
|
<div class="accordion-body">
|
||||||
|
<p>"Edumastery has been an amazing experience for our
|
||||||
|
daughter, Lily.
|
||||||
|
The
|
||||||
|
inclusive and enriching atmosphere has not only helped
|
||||||
|
her academic
|
||||||
|
growth
|
||||||
|
but has also fostered her social and emotional
|
||||||
|
development. We are
|
||||||
|
grateful
|
||||||
|
for the caring and dedicated staff."</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<div class="sidebar-content-single-area">
|
||||||
|
<div class="side-bar-video-area">
|
||||||
|
<div class="how-it-work-content-3 relative">
|
||||||
|
<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=113440119063884&bvid=BV1T6DmYUE93&cid=26651593869&p=1"
|
||||||
|
scrolling="no" width="100%" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>
|
||||||
|
</div>
|
||||||
|
<div class="enroll-course-content">
|
||||||
|
<div class="enroll-heading text-center">
|
||||||
|
<a class="auth-btn w-100" href="login.html">购买此课程</a>
|
||||||
|
<p>30天无理由退款</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="course-info-list">
|
||||||
|
<li>课程节数 : <span>{{ data.lessone }}</span></li>
|
||||||
|
<li>课程时长 : <span>{{ formatTime(data.duration) }}</span></li>
|
||||||
|
<li>最大学生数: <span>{{ data.maxStudents }}</span></li>
|
||||||
|
<li>是否下证 : <span>包的</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -1,14 +1,13 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import CourseBreadcrumb from "@/components/course/CourseBreadcrumb.vue";
|
import CourseBreadcrumb from "@/components/course/CourseBreadcrumb.vue";
|
||||||
import axios from "axios";
|
|
||||||
import {ref} from "vue";
|
import {ref} from "vue";
|
||||||
import {createRandomInt} from "@/utils/data.js";
|
import {createRandomInt} from "@/utils/data.js";
|
||||||
|
import request from "@/net/index.js";
|
||||||
|
|
||||||
const data = ref([])
|
const data = ref([])
|
||||||
|
|
||||||
axios.get('http://localhost:8080/system/course/list').then((res) => {
|
request.get('/system/course/list')
|
||||||
data.value = res.data.rows
|
.then((res) => data.value = res.data.rows)
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import axios from "axios";
|
|
||||||
import {ref} from "vue";
|
import {ref} from "vue";
|
||||||
import {createRandomInt} from "@/utils/data.js";
|
import {createRandomInt} from "@/utils/data.js";
|
||||||
import CourseBreadcrumb from "@/components/course/CourseBreadcrumb.vue";
|
import CourseBreadcrumb from "@/components/course/CourseBreadcrumb.vue";
|
||||||
|
import request from "@/net";
|
||||||
|
|
||||||
const data = ref([])
|
const data = ref([])
|
||||||
|
|
||||||
axios.get('http://localhost:8080/system/course/list').then((res) => {
|
request.get('/system/course/list')
|
||||||
data.value = res.data.rows
|
.then((res) => data.value = res.data.rows)
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -31,7 +30,7 @@ axios.get('http://localhost:8080/system/course/list').then((res) => {
|
|||||||
<i class="icon-icon_ribbon_alt"></i>
|
<i class="icon-icon_ribbon_alt"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h2><a href="course-details.html">{{ course.title }}</a></h2>
|
<h2><a :href="`/course/detail/${course.id}`">{{ course.title }}</a></h2>
|
||||||
<!-- info -->
|
<!-- info -->
|
||||||
<div class="course-info-meta-4 d-flex align-items-center">
|
<div class="course-info-meta-4 d-flex align-items-center">
|
||||||
<p><i class="icon-Home"></i> {{ createRandomInt() }} 名学生正在学习</p>
|
<p><i class="icon-Home"></i> {{ createRandomInt() }} 名学生正在学习</p>
|
||||||
|
@ -8,6 +8,19 @@ export default defineConfig({
|
|||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
],
|
],
|
||||||
|
server: {
|
||||||
|
port: 5173,
|
||||||
|
host: true,
|
||||||
|
open: true,
|
||||||
|
proxy: {
|
||||||
|
// https://cn.vitejs.dev/config/#server-proxy
|
||||||
|
'/dev-api': {
|
||||||
|
target: 'http://localhost:8080',
|
||||||
|
changeOrigin: true,
|
||||||
|
rewrite: (p) => p.replace(/^\/dev-api/, '')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||||
|