优化课程列表,添加课程列表详细
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',
|
||||
name: 'course-grid',
|
||||
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() {
|
||||
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>
|
||||
import CourseBreadcrumb from "@/components/course/CourseBreadcrumb.vue";
|
||||
import axios from "axios";
|
||||
import {ref} from "vue";
|
||||
import {createRandomInt} from "@/utils/data.js";
|
||||
import request from "@/net/index.js";
|
||||
|
||||
const data = ref([])
|
||||
|
||||
axios.get('http://localhost:8080/system/course/list').then((res) => {
|
||||
data.value = res.data.rows
|
||||
})
|
||||
request.get('/system/course/list')
|
||||
.then((res) => data.value = res.data.rows)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -1,14 +1,13 @@
|
||||
<script setup>
|
||||
import axios from "axios";
|
||||
import {ref} from "vue";
|
||||
import {createRandomInt} from "@/utils/data.js";
|
||||
import CourseBreadcrumb from "@/components/course/CourseBreadcrumb.vue";
|
||||
import request from "@/net";
|
||||
|
||||
const data = ref([])
|
||||
|
||||
axios.get('http://localhost:8080/system/course/list').then((res) => {
|
||||
data.value = res.data.rows
|
||||
})
|
||||
request.get('/system/course/list')
|
||||
.then((res) => data.value = res.data.rows)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -31,7 +30,7 @@ axios.get('http://localhost:8080/system/course/list').then((res) => {
|
||||
<i class="icon-icon_ribbon_alt"></i>
|
||||
</div>
|
||||
</div>
|
||||
<h2><a href="course-details.html">{{ course.title }}</a></h2>
|
||||
<h2><a :href="`/course/detail/${course.id}`">{{ course.title }}</a></h2>
|
||||
<!-- info -->
|
||||
<div class="course-info-meta-4 d-flex align-items-center">
|
||||
<p><i class="icon-Home"></i> {{ createRandomInt() }} 名学生正在学习</p>
|
||||
|
@ -8,6 +8,19 @@ export default defineConfig({
|
||||
plugins: [
|
||||
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: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
|