This commit is contained in:
@hhgxylj 2022-10-11 15:01:28 +08:00
commit 6a8e5e1929
102 changed files with 11040 additions and 0 deletions

24
.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@ -0,0 +1,7 @@
# Vue 3 + Vite
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
## Recommended IDE Setup
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar)

View File

@ -0,0 +1 @@
# Vue 3 + Vite

View File

@ -0,0 +1 @@
# Vue 3 + Vite + pinia

View File

@ -0,0 +1,13 @@
import request from '@/utils/request'
export function getShopCarList(){
return request({
url:'/shopcar/getShopCarList'
})
}
export function deleteShopCar(){
return request({
url:'/shopcar/deleteShopCar'
})
}

View File

@ -0,0 +1,13 @@
import request from '@/utils/request'
export function getShopCarList(){
return request({
url:'/shopcar/getShopCarList'
})
}
export function deleteShopCar(){
return request({
url:'/shopcar/deleteShopCar'
})
}

View File

@ -0,0 +1,13 @@
import request from '@/utils/request'
export function getShopCarList(){
return request({
url:'/shopcar/getShopCarList'
})
}
export function deleteShopCar(){
return request({
url:'/shopcar/deleteShopCar'
})
}

View File

@ -0,0 +1,22 @@
import request from '@/utils/request'
export function getFirstCategorys(){
return request({
url:'/course/category/getFirstCategorys'
})
}
export function getSecondCategorys(data){
return request({
url:'/course/category/getSecondCategorys',
params:data
})
}
export function searchCourse(data){
return request({
url:'/course/search',
method:'POST',
data
})
}

View File

@ -0,0 +1,22 @@
import request from '@/utils/request`'
export function getFirstCategorys(){
return request({
url:'/course/category/getFirstCategorys'
})
}
export function getSecondCategorys(data){
return request({
url:'/course/category/getSecondCategorys',
params:data
})
}
export function searchCourse(data){
return request({
url:'/course/search',
method:'POST',
data
})
}

View File

@ -0,0 +1,25 @@
import request from '@/utils/request`'
import $http from '@/utils/request';
export function getFirstCategorys(){
return request({
url:'/course/category/getFirstCategorys'
})
}
// export function getSecondCategorys(data){
// return request({
// url:'/course/category/getSecondCategorys',
// params:data
// })
// }
export function searchCourse(data){
return request({
url:'/course/search',
method:'POST',
data
})
}
export function getSecondCategorys(){
return $http.get('/api/course/category/getSecondCategorys')
}

View File

@ -0,0 +1,50 @@
import request from '@/utils/request'
export function getFirstCategorys(){
return request({
url:'/course/category/getFirstCategorys'
})
}
export function getSecondCategorys( data ){
return request({
url:'/course/category/getSecondCategorys',
params: data
})
}
export function tagsList(data){
return request({
url:'/course/tags/list',
method:'POST',
data
})
}
export function search(data){
return request({
url:'/course/search',
method:'POST',
data
})
}
export function getSliders(){
return request({
url:'/slider/getSliders'
})
}
export function mostNewCourse( data ){
return request({
url:'/course/mostNew',
method:'post',
data
})
}
export function getSetting(){
return request({
url:'/setting/get'
})
}

View File

@ -0,0 +1,19 @@
import $http from '@/utils/request';
const API = {
getdemo(arg) {
return $http.get(`/smart/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
},
get() {
return $http.get(`/smart/getinfo?pageNo=1&pageSize=100`)
},
add(params) {
return $http.post('/smart/send', params);
},
uploadfile(arg) {
return $http.post(`/smart/upload`, arg)
},
downloadfile(params) {
return $http.get(`/smart/download?fileId=${params.fileId}`, { responseType: 'blob', })
},
};
export default API;

View File

@ -0,0 +1,19 @@
import $http from '@/utils/request';
const API = {
getdemo(arg) {
return $http.get(`/api/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
},
get() {
return $http.get(`/api/getinfo?pageNo=1&pageSize=100`)
},
add(params) {
return $http.post('/api/send', params);
},
uploadfile(arg) {
return $http.post(`/api/upload`, arg)
},
downloadfile(params) {
return $http.get(`/api/download?fileId=${params.fileId}`, { responseType: 'blob', })
},
};
export default API;

View File

@ -0,0 +1,22 @@
import $http from '@/utils/request';
const API = {
getdemo(arg) {
return $http.get(`/api/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
},
get() {
return $http.get(`/api/getinfo?pageNo=1&pageSize=100`)
},
add(params) {
return $http.post('/api/send', params);
},
uploadfile(arg) {
return $http.post(`/api/upload`, arg)
},
downloadfile(params) {
return $http.get(`/api/download?fileId=${params.fileId}`, { responseType: 'blob', })
},
getShopCarList(){
return $http.get('/api/shopcar/getShopCarList')
}
};
export default API;

View File

@ -0,0 +1,27 @@
import $http from '@/utils/request';
// const API = {
// getdemo(arg) {
// return $http.get(`/api/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
// },
// get() {
// return $http.get(`/api/getinfo?pageNo=1&pageSize=100`)
// },
// add(params) {
// return $http.post('/api/send', params);
// },
// uploadfile(arg) {
// return $http.post(`/api/upload`, arg)
// },
// downloadfile(params) {
// return $http.get(`/api/download?fileId=${params.fileId}`, { responseType: 'blob', })
// },
// getShopCarList(){
// return $http.get('/api/shopcar/getShopCarList')
// }
// };
// export default API;
export function getShopCarList(){
return request({
url:'/api/shopcar/getShopCarList'
})
}

View File

@ -0,0 +1,25 @@
import $http from '@/utils/request';
// const API = {
// getdemo(arg) {
// return $http.get(`/api/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
// },
// get() {
// return $http.get(`/api/getinfo?pageNo=1&pageSize=100`)
// },
// add(params) {
// return $http.post('/api/send', params);
// },
// uploadfile(arg) {
// return $http.post(`/api/upload`, arg)
// },
// downloadfile(params) {
// return $http.get(`/api/download?fileId=${params.fileId}`, { responseType: 'blob', })
// },
// getShopCarList(){
// return $http.get('/api/shopcar/getShopCarList')
// }
// };
// export default API;
export function getShopCarList(){
return $http.get('/api/shopcar/getShopCarList')
}

View File

@ -0,0 +1,25 @@
import $http from '@/utils/request';
// const API = {
// getdemo(arg) {
// return $http.get(`/api/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
// },
// get() {
// return $http.get(`/api/getinfo?pageNo=1&pageSize=100`)
// },
// add(params) {
// return $http.post('/api/send', params);
// },
// uploadfile(arg) {
// return $http.post(`/api/upload`, arg)
// },
// downloadfile(params) {
// return $http.get(`/api/download?fileId=${params.fileId}`, { responseType: 'blob', })
// },
// getShopCarList(){
// return $http.get('/api/shopcar/getShopCarList')
// }
// };
// export default API;
export function getShopCarList(){
return $http.get('/api/shopcar/getShopCarList')
}

View File

@ -0,0 +1,25 @@
import $http from '@/utils/request';
// const API = {
// getdemo(arg) {
// return $http.get(`/api/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
// },
// get() {
// return $http.get(`/api/getinfo?pageNo=1&pageSize=100`)
// },
// add(params) {
// return $http.post('/api/send', params);
// },
// uploadfile(arg) {
// return $http.post(`/api/upload`, arg)
// },
// downloadfile(params) {
// return $http.get(`/api/download?fileId=${params.fileId}`, { responseType: 'blob', })
// },
// getShopCarList(){
// return $http.get('/api/shopcar/getShopCarList')
// }
// };
// export default API;
export function getShopCarList(){
return $http.get('/api/shopcar/getShopCarList')
}

View File

@ -0,0 +1,43 @@
import request from '@/utils/request'
export function loginByJson(data){
return request({
url:'/u/loginByJson',
method:'POST',
data
})
}
export function sendRegisterOrLoginCaptcha(params){
return request({
url:'/sms/sendRegisterOrLoginCaptcha',
params
})
}
export function loginByMobile(data){
return request({
url:'/u/loginByMobile',
method:'POST',
data
})
}
export function createToken(data){
return request({
url:'/token/createToken'
})
}
export function getInfo(params){
return request({
url:'/member/getInfo',
params
})
}
export function logout(){
return request({
url:'/u/logout',
})
}

View File

@ -0,0 +1 @@
import $http from '@/utils/request';

View File

@ -0,0 +1,39 @@
import $http from '@/utils/request';
export function loginByJson(data){
return $http.get(`/api/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
}
export function sendRegisterOrLoginCaptcha(params){
return request({
url:'/sms/sendRegisterOrLoginCaptcha',
params
})
}
export function loginByMobile(data){
return request({
url:'/u/loginByMobile',
method:'POST',
data
})
}
export function createToken(data){
return request({
url:'/token/createToken'
})
}
export function getInfo(params){
return request({
url:'/member/getInfo',
params
})
}
export function logout(){
return request({
url:'/u/logout',
})
}

View File

@ -0,0 +1,39 @@
import $http from '@/utils/request';
export function loginByJson(arg){
return $http.get(`/api/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
}
export function sendRegisterOrLoginCaptcha(params){
return request({
url:'/sms/sendRegisterOrLoginCaptcha',
params
})
}
export function loginByMobile(data){
return request({
url:'/u/loginByMobile',
method:'POST',
data
})
}
export function createToken(data){
return request({
url:'/token/createToken'
})
}
export function getInfo(params){
return request({
url:'/member/getInfo',
params
})
}
export function logout(){
return request({
url:'/u/logout',
})
}

View File

@ -0,0 +1,30 @@
import $http from '@/utils/request';
export function loginByJson(arg){
return $http.get(`/api/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
}
export function loginByMobile(params){
return $http.post('/api/send', params);
}
export function createToken(data){
return request({
url:'/token/createToken'
})
}
export function getInfo(params){
return request({
url:'/member/getInfo',
params
})
}
export function logout(){
return request({
url:'/u/logout',
})
}

View File

@ -0,0 +1,28 @@
import $http from '@/utils/request';
export function loginByJson(arg){
return $http.get(`/api/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
}
export function loginByMobile(params){
return $http.post('/api/send', params);
}
export function createToken(data){
return $http.get(`/api/download?fileId=${params.fileId}`, { responseType: 'blob', })
}
export function getInfo(params){
return request({
url:'/member/getInfo',
params
})
}
export function logout(){
return request({
url:'/u/logout',
})
}

View File

@ -0,0 +1,28 @@
import $http from '@/utils/request';
export function loginByJson(arg){
return $http.get(`/api/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
}
export function loginByMobile(params){
return $http.post('/api/send', params);
}
export function createToken(params){
return $http.get(`/api/download?fileId=${params.fileId}`, { responseType: 'blob', })
}
export function getInfo(params){
return request({
url:'/member/getInfo',
params
})
}
export function logout(){
return request({
url:'/u/logout',
})
}

View File

@ -0,0 +1,22 @@
import $http from '@/utils/request';
export function loginByJson(arg){
return $http.get(`/api/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
}
export function loginByMobile(params){
return $http.post('/api/send', params);
}
export function createToken(params){
return $http.get(`/api/download?fileId=${params.fileId}`, { responseType: 'blob', })
}
export function logout(){
return request({
url:'/u/logout',
})
}

View File

@ -0,0 +1,16 @@
import $http from '@/utils/request';
export function loginByJson(arg){
return $http.get(`/api/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
}
export function loginByMobile(params){
return $http.post('/api/send', params);
}
export function createToken(params){
return $http.get(`/api/download?fileId=${params.fileId}`, { responseType: 'blob', })
}

View File

@ -0,0 +1,623 @@
<template>
<div class="coursemain">
<div class="course-main">
<section class="search-container">
<div class="search-item">
<div class="title-name">课程方向</div>
<div class="all-items">
<el-tag
:class="
curryType['1'].id ? 'category-poniter-item' : 'category-poniter'
"
effect="plain"
type="info"
@click="handleAllData"
>全部</el-tag
>
<el-tag
:class="
curryType['1'].id == item.id
? 'category-poniter'
: 'category-poniter-item'
"
effect="plain"
type="info"
v-for="item in courseFirstList"
:key="item.id"
@click="handleFirstItem('1', item.id)"
>
{{ item.categoryName }}
</el-tag>
</div>
</div>
<div class="search-item search-item-transition" style="top: 45px">
<div class="title-name">课程分类</div>
<div class="all-items">
<el-tag
:class="
curryType['2'].id ? 'category-poniter-item' : 'category-poniter'
"
effect="plain"
type="info"
>全部</el-tag
>
<el-tag
:class="
curryType['2'].id == item.id
? 'category-poniter'
: 'category-poniter-item'
"
effect="plain"
type="info"
v-for="item in courseSecondList"
:key="item.id"
@click="handleFirstItem('2', item.id)"
>
{{ item.categoryName }}
</el-tag>
</div>
</div>
<div class="search-item" style="top: 90px">
<div class="title-name">课程难度</div>
<div class="all-items">
<el-tag
:class="
curryType['3'].id ? 'category-poniter-item' : 'category-poniter'
"
effect="plain"
type="info"
>全部</el-tag
>
<el-tag
:class="
curryType['3'].id == item.code
? 'category-poniter'
: 'category-poniter-item'
"
effect="plain"
type="info"
v-for="item in courseThirdList"
:key="item.code"
@click="handleFirstItem('3', item.code)"
>
{{ item.name }}
</el-tag>
</div>
</div>
</section>
</div>
<div class="main-container">
<div class="container-top">
<ul class="all">
<li class="item">综合</li>
<li class="item split">|</li>
<li class="item">最新课程</li>
<li class="item split">|</li>
<li class="item">最多购买</li>
<li class="item split">|</li>
<li class="item-price">
<span>价格</span>
<span class="arrow">
<el-icon><CaretTop /></el-icon>
<el-icon><CaretBottom /></el-icon>
</span>
</li>
</ul>
<ul class="right">
<li class="right-item">
<el-radio-group v-model="radio">
<el-radio label="1">免费课程</el-radio>
<el-radio label="2">会员课程</el-radio>
</el-radio-group>
</li>
</ul>
</div>
<div class="container-body">
<div class="newCourseContent">
<ul class="courseUl">
<li
class="courseItem"
v-for="item in courseSearchList"
:key="item.id"
>
<router-link :to="'/CourseInfo/' + item.id">
<div class="courseInfo">
<div class="courseBg">
<img :src="item.courseCover" />
</div>
<div class="courseName">{{ item.courseName }}</div>
<div class="courseDegree">
{{ courseTypeFn(item.courseLevel) }} ·
{{ item.purchaseCounter + item.purchaseCnt }}人报名
</div>
<div class="coursePriceZero" v-if="item.discountPrice == 0">
<div class="pricefree">免费学习</div>
<img src="@/assets/img/logo1.jpg" alt="" />
</div>
<div class="coursePrice" v-else-if="item.isMember == 1">
<div class="courseMemberbg">
<span class="courseMember">会员免费</span>
</div>
<div class="price">¥ {{ item.discountPrice }}</div>
</div>
<div class="coursePricePri" v-else>
<div class="pricePri">¥ {{ item.discountPrice }}</div>
</div>
</div>
</router-link>
</li>
</ul>
</div>
<div class="pages">
<el-pagination
background
layout="prev, pager, next"
:total="courseSearchListTotal"
@current-change="handleCurrentChange"
/>
</div>
</div>
</div>
</div>
</template>
<script setup>
import {
getFirstCategorys,
getSecondCategorys,
searchCourse,
} from "@/api/Course/index";
import mixins from "@/mixins/E2C.js";
import { reactive } from "@vue/reactivity";
import { computed, watch, watchEffect } from "@vue/runtime-core";
import { CaretTop , CaretBottom} from "@element-plus/icons-vue";
let { courseTypeFn } = mixins();
let CourseList = reactive({
courseFirstList: [],
courseSecondList: [],
courseSearchList: [],
courseThirdList: [
{ name: "初级", code: "1" },
{ name: "中级", code: "2" },
{ name: "高级", code: "3" },
],
pageNum: 1,
pageSize: 8,
courseSearchListTotal: 0,
entity: {
firstCategory: "",
secondCategory: "",
courseLevel: "",
isMember:"",
isFree:'',
},
});
// entity:{
// firstCategory:'', string ID
// secondCategory:'', string ID
// tags:'', string
// isMember:'', string 1
// isFree:'', string 1
// courseLevel:'', string 123
// sortBy:'', string 1clicks-desc2clicks-asc3time-desc4time-asc5price-desc6price-asc7purchase-desc6purchase-asc
// }
let {
courseFirstList,
courseSecondList,
courseThirdList,
pageNum,
pageSize,
courseSearchList,
courseSearchListTotal,
entity,
} = toRefs(CourseList);
//
const querySearchCourse = async (pageNum, pageSize, entity) => {
const res = await searchCourse({
pageNum,
pageSize,
entity,
});
courseSearchList.value = res.data.pageInfo.list;
courseSearchListTotal.value = res.data.pageInfo.total;
};
let secondCategorysParams = reactive({
categoryId: -1,
});
const getSecondCategorysFn = async (params) => {
const res = await getSecondCategorys(params);
courseSecondList.value = res.data.list;
};
onBeforeMount(async () => {
const res = await getFirstCategorys();
courseFirstList.value = res.data.list;
getSecondCategorysFn(secondCategorysParams);
querySearchCourse(pageNum.value, pageSize.value);
});
let curryType = reactive({
1: {
id: "",
},
2: {
id: "",
},
3: {
id: "",
},
});
const handleAllData = async () => {
const res = await getFirstCategorys();
courseFirstList.value = res.data.list;
getSecondCategorysFn(secondCategorysParams);
querySearchCourse(pageNum.value, pageSize.value);
curryType['1'].id = ''
}
const handleFirstItem = async (type, id) => {
if (type == 1) {
entity.value.isFree = ''
entity.value.isMember = ''
radio.value = '0'
curryType[type].id = id;
curryType["2"].id = "";
curryType["3"].id = "";
entity.value.secondCategory = "";
entity.value.courseLevel = "";
secondCategorysParams.categoryId = id;
getSecondCategorysFn(secondCategorysParams);
entity.value.firstCategory = id;
querySearchCourse(pageNum.value, pageSize.value, entity.value);
return;
}
if (type == 2) {
entity.value.isFree = ''
entity.value.isMember = ''
radio.value = '0'
curryType["3"].id = "";
curryType[type].id = id;
entity.value.courseLevel = "";
entity.value.secondCategory = id;
querySearchCourse(pageNum.value, pageSize.value, entity.value);
return;
}
if (type == 3) {
entity.value.isFree = ''
entity.value.isMember = ''
radio.value = '0'
curryType[type].id = id;
entity.value.courseLevel = id;
querySearchCourse(pageNum.value, pageSize.value, entity.value);
return;
}
};
const handleCurrentChange = (e) => {
pageNum.value = e;
querySearchCourse(pageNum.value, pageSize.value);
};
let radio = ref('0')
watch(radio, (n,o)=>{
console.log(n);
console.log(o);
})
watchEffect(()=>{
if(radio.value == '1'){
entity.value.isFree = 1
entity.value.isMember = ''
}else if(radio.value == '2'){
entity.value.isFree = ''
entity.value.isMember = 1
}
querySearchCourse(pageNum.value, pageSize.value,entity.value)
})
</script>
<style scoped>
.course-main {
padding: 20px 0;
width: 100%;
height: 130px;
background: #f3f5f9;
}
.search-container {
width: 1200px;
margin: 0 auto;
position: relative;
height: 100%;
}
.search-item {
display: flex;
overflow: hidden;
cursor: pointer;
position: absolute;
height: 45px;
transition: all 0.5s;
}
.search-item-transition:hover {
z-index: 777;
height: auto;
box-shadow: rgb(95 101 105 / 10%) 0px 12px 20px 0px;
border-radius: 8px;
background: rgba(255, 255, 255);
}
.search-item .title-name {
width: 100px;
font-size: 16px;
font-family: Microsoft YaHei;
font-weight: bold;
line-height: 25px;
text-align: justify;
color: #333333;
padding: 10px;
opacity: 1;
}
.search-item .title-name:after {
content: ".";
width: 100%;
display: inline-block;
overflow: hidden;
height: 0;
}
.search-item .all-items {
width: calc(100% - 120px);
min-height: 25px;
display: flex;
flex-wrap: wrap;
}
.title .all-list {
width: 40px;
height: 25px;
line-height: 25px;
border-radius: 4px;
padding: 0 10px;
align-items: center;
text-align: center;
}
.title .all {
opacity: 1;
color: #2c80ff;
}
.title .item {
height: 25px;
line-height: 25px;
margin: 0 15px;
font-size: 16px;
font-family: Microsoft YaHei;
font-weight: 400;
line-height: 21px;
opacity: 1;
}
.title .item .active {
color: #2c80ff;
}
.category-poniter {
height: 25px;
line-height: 25px;
margin: 10px 5px;
cursor: pointer;
border: none;
background: rgba(44, 128, 255, 0.1);
color: #2c80ff;
}
.category-poniter-item {
height: 25px;
line-height: 25px;
margin: 10px 5px;
cursor: pointer;
border: none;
background: none;
color: rgba(81, 87, 89, 1);
}
.main-container {
width: 1200px;
margin: 0 auto;
}
.container-top {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 12px;
}
.all {
display: flex;
padding-top: 20px;
font-size: 16px;
color: #515759;
}
.all .item:first-child {
margin-right: 20px;
}
.all .item {
margin: 0 10px;
cursor: pointer;
}
.right {
display: flex;
padding-top: 20px;
font-size: 16px;
color: #515759;
}
.right .right-item {
margin-left: 10px;
}
.right .right-items {
margin-right: 0px;
}
.arrow {
position: relative;
}
.arrow i:first-child {
position: absolute;
top: -1px;
}
.arrow i:last-child {
position: absolute;
top: 7px;
}
.check {
width: 15px;
height: 15px;
cursor: pointer;
}
.up {
position: absolute;
top: 5px;
left: 2px;
}
.down {
position: absolute;
top: 15px;
left: 2px;
transform: rotate(180deg);
-ms-transform: rotate(180deg); /* IE 9 */
-moz-transform: rotate(180deg); /* Firefox */
-webkit-transform: rotate(180deg); /* Safari 和 Chrome */
-o-transform: rotate(180deg); /* Opera */
}
.newCourseContent {
width: 1200px;
margin: 30px auto 0px auto;
}
.newCourseContent .courseUl {
display: flex;
flex-wrap: wrap;
}
.courseItem {
width: 285px;
height: 280px;
margin: 0 20px 20px 0;
transition: margin-top 0.2s;
}
.courseItem:hover {
margin-top: -10px;
cursor: pointer;
}
.courseItem:nth-child(4n + 0) {
margin-right: 0 !important;
}
.courseInfo {
position: relative;
width: 100%;
height: 270px;
background: #ffffff;
box-shadow: 1px 1px 10px rgb(27 39 94 / 40%);
opacity: 1;
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
overflow: hidden;
text-decoration: none;
}
.courseBg {
position: relative;
width: 100%;
height: 160px;
}
.courseBg img {
width: 100%;
height: 100%;
}
.courseName {
margin: 10px;
font-weight: bold;
font-size: 14px;
color: #333333;
display: -webkit-box;
overflow: hidden;
}
.courseDegree {
margin-left: 10px;
font-size: 12px;
color: #808080;
}
.coursePrice {
display: flex;
justify-content: space-around;
align-items: center;
width: 130px;
font-size: 14px;
margin-top: 15px;
padding: 0 5px;
}
.coursePricePri {
width: 75px;
font-size: 14px;
margin-top: 18px;
padding: 0 13px;
color: rgba(255, 114, 127, 1);
font-weight: 700;
}
.coursePriceZero {
display: flex;
justify-content: space-between;
align-items: center;
width: 75px;
font-size: 14px;
margin-top: 15px;
padding: 0 10px;
color: rgba(53, 134, 255, 1);
}
.courseMemberbg {
position: relative;
width: 80px;
height: 20px;
color: #ffffff;
background: linear-gradient(90deg, #ff928e 0%, #fe7062 99%);
border-radius: 24px 0px 24px 0px;
}
.courseMember {
position: absolute;
line-height: 20px;
left: 13px;
font-weight: 700;
}
.price {
line-height: 25px;
left: 100px;
color: #ff727f;
font-weight: 700;
}
.pages {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
margin: 50px auto !important;
}
</style>

View File

@ -0,0 +1,624 @@
<template>
<div class="coursemain">
<div class="course-main">
<section class="search-container">
<div class="search-item">
<div class="title-name">课程方向</div>
<div class="all-items">
<el-tag
:class="
curryType['1'].id ? 'category-poniter-item' : 'category-poniter'
"
effect="plain"
type="info"
@click="handleAllData"
>全部</el-tag
>
<el-tag
:class="
curryType['1'].id == item.id
? 'category-poniter'
: 'category-poniter-item'
"
effect="plain"
type="info"
v-for="item in courseFirstList"
:key="item.id"
@click="handleFirstItem('1', item.id)"
>
{{ item.categoryName }}
</el-tag>
</div>
</div>
<div class="search-item search-item-transition" style="top: 45px">
<div class="title-name">课程分类</div>
<div class="all-items">
<el-tag
:class="
curryType['2'].id ? 'category-poniter-item' : 'category-poniter'
"
effect="plain"
type="info"
>全部</el-tag
>
<el-tag
:class="
curryType['2'].id == item.id
? 'category-poniter'
: 'category-poniter-item'
"
effect="plain"
type="info"
v-for="item in courseSecondList"
:key="item.id"
@click="handleFirstItem('2', item.id)"
>
{{ item.categoryName }}
</el-tag>
</div>
</div>
<div class="search-item" style="top: 90px">
<div class="title-name">课程难度</div>
<div class="all-items">
<el-tag
:class="
curryType['3'].id ? 'category-poniter-item' : 'category-poniter'
"
effect="plain"
type="info"
>全部</el-tag
>
<el-tag
:class="
curryType['3'].id == item.code
? 'category-poniter'
: 'category-poniter-item'
"
effect="plain"
type="info"
v-for="item in courseThirdList"
:key="item.code"
@click="handleFirstItem('3', item.code)"
>
{{ item.name }}
</el-tag>
</div>
</div>
</section>
</div>
<div class="main-container">
<div class="container-top">
<ul class="all">
<li class="item">综合</li>
<li class="item split">|</li>
<li class="item">最新课程</li>
<li class="item split">|</li>
<li class="item">最多购买</li>
<li class="item split">|</li>
<li class="item-price">
<span>价格</span>
<span class="arrow">
<el-icon><CaretTop /></el-icon>
<el-icon><CaretBottom /></el-icon>
</span>
</li>
</ul>
<ul class="right">
<li class="right-item">
<el-radio-group v-model="radio">
<el-radio label="1">免费课程</el-radio>
<el-radio label="2">会员课程</el-radio>
</el-radio-group>
</li>
</ul>
</div>
<div class="container-body">
<div class="newCourseContent">
<ul class="courseUl">
<li
class="courseItem"
v-for="item in courseSearchList"
:key="item.id"
>
<router-link :to="'/CourseInfo/' + item.id">
<div class="courseInfo">
<div class="courseBg">
<img :src="item.courseCover" />
</div>
<div class="courseName">{{ item.courseName }}</div>
<div class="courseDegree">
{{ courseTypeFn(item.courseLevel) }} ·
{{ item.purchaseCounter + item.purchaseCnt }}人报名
</div>
<div class="coursePriceZero" v-if="item.discountPrice == 0">
<div class="pricefree">免费学习</div>
<img src="@/assets/img/logo1.jpg" alt="" />
</div>
<div class="coursePrice" v-else-if="item.isMember == 1">
<div class="courseMemberbg">
<span class="courseMember">会员免费</span>
</div>
<div class="price">¥ {{ item.discountPrice }}</div>
</div>
<div class="coursePricePri" v-else>
<div class="pricePri">¥ {{ item.discountPrice }}</div>
</div>
</div>
</router-link>
</li>
</ul>
</div>
<div class="pages">
<el-pagination
background
layout="prev, pager, next"
:total="courseSearchListTotal"
@current-change="handleCurrentChange"
/>
</div>
</div>
</div>
</div>
</template>
<script setup>
import {
getFirstCategorys,
getSecondCategorys,
searchCourse,
} from "@/api/Course/index";
import mixins from "@/mixins/E2C.js";
import { reactive } from "@vue/reactivity";
import { computed, watch, watchEffect } from "@vue/runtime-core";
import { CaretTop , CaretBottom} from "@element-plus/icons-vue";
let { courseTypeFn } = mixins();
let CourseList = reactive({
courseFirstList: [],
courseSecondList: [],
courseSearchList: [],
courseThirdList: [
{ name: "初级", code: "1" },
{ name: "中级", code: "2" },
{ name: "高级", code: "3" },
],
pageNum: 1,
pageSize: 8,
courseSearchListTotal: 0,
entity: {
firstCategory: "",
secondCategory: "",
courseLevel: "",
isMember:"",
isFree:'',
},
});
// entity:{
// firstCategory:'', string ID
// secondCategory:'', string ID
// tags:'', string
// isMember:'', string 1
// isFree:'', string 1
// courseLevel:'', string 123
// sortBy:'', string 1clicks-desc2clicks-asc3time-desc4time-asc5price-desc6price-asc7purchase-desc6purchase-asc
// }
let {
courseFirstList,
courseSecondList,
courseThirdList,
pageNum,
pageSize,
courseSearchList,
courseSearchListTotal,
entity,
} = toRefs(CourseList);
//
const querySearchCourse = async (pageNum, pageSize, entity) => {
const res = await searchCourse({
pageNum,
pageSize,
entity,
});
courseSearchList.value = res.data.pageInfo.list;
courseSearchListTotal.value = res.data.pageInfo.total;
};
let secondCategorysParams = reactive({
categoryId: -1,
});
const getSecondCategorysFn = async (params) => {
const res = await getSecondCategorys(params);
courseSecondList.value = res.data.list;
};
onBeforeMount(async () => {
const res = await getFirstCategorys();
console.log(res,"res")
courseFirstList.value = res.data.list;
getSecondCategorysFn(secondCategorysParams);
querySearchCourse(pageNum.value, pageSize.value);
});
let curryType = reactive({
1: {
id: "",
},
2: {
id: "",
},
3: {
id: "",
},
});
const handleAllData = async () => {
const res = await getFirstCategorys();
courseFirstList.value = res.data.list;
getSecondCategorysFn(secondCategorysParams);
querySearchCourse(pageNum.value, pageSize.value);
curryType['1'].id = ''
}
const handleFirstItem = async (type, id) => {
if (type == 1) {
entity.value.isFree = ''
entity.value.isMember = ''
radio.value = '0'
curryType[type].id = id;
curryType["2"].id = "";
curryType["3"].id = "";
entity.value.secondCategory = "";
entity.value.courseLevel = "";
secondCategorysParams.categoryId = id;
getSecondCategorysFn(secondCategorysParams);
entity.value.firstCategory = id;
querySearchCourse(pageNum.value, pageSize.value, entity.value);
return;
}
if (type == 2) {
entity.value.isFree = ''
entity.value.isMember = ''
radio.value = '0'
curryType["3"].id = "";
curryType[type].id = id;
entity.value.courseLevel = "";
entity.value.secondCategory = id;
querySearchCourse(pageNum.value, pageSize.value, entity.value);
return;
}
if (type == 3) {
entity.value.isFree = ''
entity.value.isMember = ''
radio.value = '0'
curryType[type].id = id;
entity.value.courseLevel = id;
querySearchCourse(pageNum.value, pageSize.value, entity.value);
return;
}
};
const handleCurrentChange = (e) => {
pageNum.value = e;
querySearchCourse(pageNum.value, pageSize.value);
};
let radio = ref('0')
watch(radio, (n,o)=>{
console.log(n);
console.log(o);
})
watchEffect(()=>{
if(radio.value == '1'){
entity.value.isFree = 1
entity.value.isMember = ''
}else if(radio.value == '2'){
entity.value.isFree = ''
entity.value.isMember = 1
}
querySearchCourse(pageNum.value, pageSize.value,entity.value)
})
</script>
<style scoped>
.course-main {
padding: 20px 0;
width: 100%;
height: 130px;
background: #f3f5f9;
}
.search-container {
width: 1200px;
margin: 0 auto;
position: relative;
height: 100%;
}
.search-item {
display: flex;
overflow: hidden;
cursor: pointer;
position: absolute;
height: 45px;
transition: all 0.5s;
}
.search-item-transition:hover {
z-index: 777;
height: auto;
box-shadow: rgb(95 101 105 / 10%) 0px 12px 20px 0px;
border-radius: 8px;
background: rgba(255, 255, 255);
}
.search-item .title-name {
width: 100px;
font-size: 16px;
font-family: Microsoft YaHei;
font-weight: bold;
line-height: 25px;
text-align: justify;
color: #333333;
padding: 10px;
opacity: 1;
}
.search-item .title-name:after {
content: ".";
width: 100%;
display: inline-block;
overflow: hidden;
height: 0;
}
.search-item .all-items {
width: calc(100% - 120px);
min-height: 25px;
display: flex;
flex-wrap: wrap;
}
.title .all-list {
width: 40px;
height: 25px;
line-height: 25px;
border-radius: 4px;
padding: 0 10px;
align-items: center;
text-align: center;
}
.title .all {
opacity: 1;
color: #2c80ff;
}
.title .item {
height: 25px;
line-height: 25px;
margin: 0 15px;
font-size: 16px;
font-family: Microsoft YaHei;
font-weight: 400;
line-height: 21px;
opacity: 1;
}
.title .item .active {
color: #2c80ff;
}
.category-poniter {
height: 25px;
line-height: 25px;
margin: 10px 5px;
cursor: pointer;
border: none;
background: rgba(44, 128, 255, 0.1);
color: #2c80ff;
}
.category-poniter-item {
height: 25px;
line-height: 25px;
margin: 10px 5px;
cursor: pointer;
border: none;
background: none;
color: rgba(81, 87, 89, 1);
}
.main-container {
width: 1200px;
margin: 0 auto;
}
.container-top {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 12px;
}
.all {
display: flex;
padding-top: 20px;
font-size: 16px;
color: #515759;
}
.all .item:first-child {
margin-right: 20px;
}
.all .item {
margin: 0 10px;
cursor: pointer;
}
.right {
display: flex;
padding-top: 20px;
font-size: 16px;
color: #515759;
}
.right .right-item {
margin-left: 10px;
}
.right .right-items {
margin-right: 0px;
}
.arrow {
position: relative;
}
.arrow i:first-child {
position: absolute;
top: -1px;
}
.arrow i:last-child {
position: absolute;
top: 7px;
}
.check {
width: 15px;
height: 15px;
cursor: pointer;
}
.up {
position: absolute;
top: 5px;
left: 2px;
}
.down {
position: absolute;
top: 15px;
left: 2px;
transform: rotate(180deg);
-ms-transform: rotate(180deg); /* IE 9 */
-moz-transform: rotate(180deg); /* Firefox */
-webkit-transform: rotate(180deg); /* Safari 和 Chrome */
-o-transform: rotate(180deg); /* Opera */
}
.newCourseContent {
width: 1200px;
margin: 30px auto 0px auto;
}
.newCourseContent .courseUl {
display: flex;
flex-wrap: wrap;
}
.courseItem {
width: 285px;
height: 280px;
margin: 0 20px 20px 0;
transition: margin-top 0.2s;
}
.courseItem:hover {
margin-top: -10px;
cursor: pointer;
}
.courseItem:nth-child(4n + 0) {
margin-right: 0 !important;
}
.courseInfo {
position: relative;
width: 100%;
height: 270px;
background: #ffffff;
box-shadow: 1px 1px 10px rgb(27 39 94 / 40%);
opacity: 1;
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
overflow: hidden;
text-decoration: none;
}
.courseBg {
position: relative;
width: 100%;
height: 160px;
}
.courseBg img {
width: 100%;
height: 100%;
}
.courseName {
margin: 10px;
font-weight: bold;
font-size: 14px;
color: #333333;
display: -webkit-box;
overflow: hidden;
}
.courseDegree {
margin-left: 10px;
font-size: 12px;
color: #808080;
}
.coursePrice {
display: flex;
justify-content: space-around;
align-items: center;
width: 130px;
font-size: 14px;
margin-top: 15px;
padding: 0 5px;
}
.coursePricePri {
width: 75px;
font-size: 14px;
margin-top: 18px;
padding: 0 13px;
color: rgba(255, 114, 127, 1);
font-weight: 700;
}
.coursePriceZero {
display: flex;
justify-content: space-between;
align-items: center;
width: 75px;
font-size: 14px;
margin-top: 15px;
padding: 0 10px;
color: rgba(53, 134, 255, 1);
}
.courseMemberbg {
position: relative;
width: 80px;
height: 20px;
color: #ffffff;
background: linear-gradient(90deg, #ff928e 0%, #fe7062 99%);
border-radius: 24px 0px 24px 0px;
}
.courseMember {
position: absolute;
line-height: 20px;
left: 13px;
font-weight: 700;
}
.price {
line-height: 25px;
left: 100px;
color: #ff727f;
font-weight: 700;
}
.pages {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
margin: 50px auto !important;
}
</style>

View File

@ -0,0 +1,55 @@
import { createRouter, createWebHistory } from "vue-router";
import { useUserStore } from '@/store/user'
const routes = [
{
path: "/",
name: "Home",
component: () =>import(/* webpackChunkName: "home" */ "../views/Home.vue"),
},
{
path: "/Course",
name: "Course",
component: () =>import(/* webpackChunkName: "about" */ "../views/Course.vue"),
},
{
path: "/CourseInfo/:id",
name: "CourseInfo",
component: () =>
import(/* webpackChunkName: "CourseInfo" */ "../views/CourseInfo.vue"),
},
{
path: "/Login",
name: "Login",
component: () =>
import(/* webpackChunkName: "Login" */ "../views/Login.vue"),
},
{
path:'/course-play',
name:'course-play',
component: () =>
import(/* webpackChunkName: "CoursePlay" */ "../views/CoursePlay.vue"),
},
{
path:'/cart',
name:'Cart',
component: () =>
import(/* webpackChunkName: "CoursePlay" */ "../views/Cart.vue"),
beforeEnter: (to, from, next) => {
if( useUserStore().token ){
next()
}else {
next('/login')
}
}
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;

View File

@ -0,0 +1,33 @@
import { createRouter, createWebHistory } from "vue-router";
import { useUserStore } from '@/store/user'
const routes = [
{
path: "/",
name: "Home",
component: () =>import(/* webpackChunkName: "home" */ "../views/Home.vue"),
},
// {
// path:'/cart',
// name:'Cart',
// component: () =>
// import(/* webpackChunkName: "CoursePlay" */ "../views/Cart.vue"),
// beforeEnter: (to, from, next) => {
// if( useUserStore().token ){
// next()
// }else {
// next('/login')
// }
// }
// },
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;

View File

@ -0,0 +1,7 @@
import { createPinia } from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'
const store = createPinia()
store.use(piniaPluginPersist)
export default store

View File

@ -0,0 +1,8 @@
import { createPinia } from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'
const store = createPinia()
// 使用持久化插件
store.use(piniaPluginPersist)
export default store

View File

@ -0,0 +1,42 @@
import Vue from 'vue';
import axios from 'axios';
Vue.prototype.axios = axios;
// 创建axios实例
const $axios = axios.create();
$axios.defaults.timeout = 1000 * 50; // 请求超时时间
// request拦截器
$axios.interceptors.request.use(config => {
if (sessionStorage.getItem('token')) {
config.headers.Authorization = sessionStorage.getItem('token')
}
if (navigator.userAgent.indexOf('Trident') != -1) {
if (config.method == 'post') {
config.data = {
...config.data,
t: Date.now()
};
} else if (config.method == 'get') {
config.params = {
...config.params,
t: Date.now()
};
}
}
return config;
}, error => {
return Promise.reject(error);
});
// respone 拦截器
$axios.interceptors.response.use(
response => {
return response;
},
error => {
return Promise.reject(error);
}
);
export default $axios;

View File

@ -0,0 +1,41 @@
import Vue from 'vue';
import axios from 'axios';
Vue.prototype.axios = axios;
// 创建axios实例
const $axios = axios.create();
$axios.defaults.timeout = 1000 * 50; // 请求超时时间
// request拦截器
$axios.interceptors.request.use(config => {
if (sessionStorage.getItem('token')) {
config.headers.Authorization = sessionStorage.getItem('token')
}
if (navigator.userAgent.indexOf('Trident') != -1) {
if (config.method == 'post') {
config.data = {
...config.data,
t: Date.now()
};
} else if (config.method == 'get') {
config.params = {
...config.params,
t: Date.now()
};
}
}
return config;
}, error => {
return Promise.reject(error);
});
// respone 拦截器
$axios.interceptors.response.use(
response => {
return response;
},
error => {
return Promise.reject(error);
}
);
export default $axios;

View File

@ -0,0 +1,41 @@
// import Vue from 'vue';
import axios from 'axios';
Vue.prototype.axios = axios;
// 创建axios实例
const $axios = axios.create();
$axios.defaults.timeout = 1000 * 50; // 请求超时时间
// request拦截器
$axios.interceptors.request.use(config => {
if (sessionStorage.getItem('token')) {
config.headers.Authorization = sessionStorage.getItem('token')
}
if (navigator.userAgent.indexOf('Trident') != -1) {
if (config.method == 'post') {
config.data = {
...config.data,
t: Date.now()
};
} else if (config.method == 'get') {
config.params = {
...config.params,
t: Date.now()
};
}
}
return config;
}, error => {
return Promise.reject(error);
});
// respone 拦截器
$axios.interceptors.response.use(
response => {
return response;
},
error => {
return Promise.reject(error);
}
);
export default $axios;

View File

@ -0,0 +1,41 @@
// import Vue from 'vue';
import axios from 'axios';
// Vue.prototype.axios = axios;
// 创建axios实例
const $axios = axios.create();
$axios.defaults.timeout = 1000 * 50; // 请求超时时间
// request拦截器
$axios.interceptors.request.use(config => {
if (sessionStorage.getItem('token')) {
config.headers.Authorization = sessionStorage.getItem('token')
}
if (navigator.userAgent.indexOf('Trident') != -1) {
if (config.method == 'post') {
config.data = {
...config.data,
t: Date.now()
};
} else if (config.method == 'get') {
config.params = {
...config.params,
t: Date.now()
};
}
}
return config;
}, error => {
return Promise.reject(error);
});
// respone 拦截器
$axios.interceptors.response.use(
response => {
return response;
},
error => {
return Promise.reject(error);
}
);
export default $axios;

View File

@ -0,0 +1,96 @@
import $axios from '@/utils/axios';
// import server from './server.config';
import Qs from 'qs';
import {
Message
} from 'element-ui';
import router from '@/router/index';
/**
* code为非1000是抛错 可结合自己业务进行修改
*
* **/
const dealResponse = function (response, resolve) {
let res = response.data;
if (res.code) {
if (res.code === 1000 || res.code === 200) {
resolve(res);
} else if (res.code === 401) {
Message({
type: 'error',
message: `['尚未登录授权或授权过期,请登录']`
});
router.replace({
path: '/login'
});
resolve(res);
} else {
Message({
type: 'error',
message: `[${res.code},${res.message}]`
});
resolve(res);
}
} else {
// 二进制无res.code
resolve(response);
}
};
// 封装GET方法
const get = function (url, ...args) {
return new Promise((resolve, reject) => {
$axios.get(url, Object.assign({}, ...args)).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装POST方法
const post = function (url, data = {}, ...args) {
return new Promise((resolve, reject) => {
$axios.post(url, data, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装get请求方法,自动添加参数
const addArrayParamsByGet = function (url, [params, ...args]) {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.get(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装post请求方法,自动添加参数
const addFormDataParamsByPost = (url, [params, ...args]) => {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.post(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
export default {
get,
post,
addArrayParamsByGet,
addFormDataParamsByPost
};

View File

@ -0,0 +1,96 @@
import $axios from '@/utils/axios';
// import server from './server.config';
import Qs from 'qs';
import {
Message
} from 'element-ui';
import router from '@/router/index';
/**
* code为非1000是抛错 可结合自己业务进行修改
*
* **/
const dealResponse = function (response, resolve) {
let res = response.data;
if (res.code) {
if (res.code === 1000 || res.code === 200) {
resolve(res);
} else if (res.code === 401) {
Message({
type: 'error',
message: `['尚未登录授权或授权过期,请登录']`
});
router.replace({
path: '/login'
});
resolve(res);
} else {
Message({
type: 'error',
message: `[${res.code},${res.message}]`
});
resolve(res);
}
} else {
// 二进制无res.code
resolve(response);
}
};
// 封装GET方法
const get = function (url, ...args) {
return new Promise((resolve, reject) => {
$axios.get(url, Object.assign({}, ...args)).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装POST方法
const post = function (url, data = {}, ...args) {
return new Promise((resolve, reject) => {
$axios.post(url, data, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装get请求方法,自动添加参数
const addArrayParamsByGet = function (url, [params, ...args]) {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.get(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装post请求方法,自动添加参数
const addFormDataParamsByPost = (url, [params, ...args]) => {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.post(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
export default {
get,
post,
addArrayParamsByGet,
addFormDataParamsByPost
};

View File

@ -0,0 +1,96 @@
import $axios from '@/utils/axios';
// import server from './server.config';
import Qs from 'qs';
// import {
// Message
// } from 'element-ui';
import router from '@/router/index';
/**
* code为非1000是抛错 可结合自己业务进行修改
*
* **/
const dealResponse = function (response, resolve) {
let res = response.data;
if (res.code) {
if (res.code === 1000 || res.code === 200) {
resolve(res);
} else if (res.code === 401) {
Message({
type: 'error',
message: `['尚未登录授权或授权过期,请登录']`
});
router.replace({
path: '/login'
});
resolve(res);
} else {
// Message({
// type: 'error',
// message: `[${res.code},${res.message}]`
// });
resolve(res);
}
} else {
// 二进制无res.code
resolve(response);
}
};
// 封装GET方法
const get = function (url, ...args) {
return new Promise((resolve, reject) => {
$axios.get(url, Object.assign({}, ...args)).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装POST方法
const post = function (url, data = {}, ...args) {
return new Promise((resolve, reject) => {
$axios.post(url, data, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装get请求方法,自动添加参数
const addArrayParamsByGet = function (url, [params, ...args]) {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.get(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装post请求方法,自动添加参数
const addFormDataParamsByPost = (url, [params, ...args]) => {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.post(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
export default {
get,
post,
addArrayParamsByGet,
addFormDataParamsByPost
};

View File

@ -0,0 +1,97 @@
import $axios from '@/utils/axios';
// import server from './server.config';
import Qs from 'qs';
// import {
// Message
// } from 'element-ui';
import router from '@/router/index';
/**
* code为非1000是抛错 可结合自己业务进行修改
*
* **/
const dealResponse = function (response, resolve) {
let res = response.data;
if (res.code) {
if (res.code === 1000 || res.code === 200) {
resolve(res);
} else if (res.code === 401) {
Message({
type: 'error',
message: `['尚未登录授权或授权过期,请登录']`
});
router.replace({
path: '/login'
});
resolve(res);
} else {
// Message({
// type: 'error',
// message: `[${res.code},${res.message}]`
// });
console.log("社事件")
resolve(res);
}
} else {
// 二进制无res.code
resolve(response);
}
};
// 封装GET方法
const get = function (url, ...args) {
return new Promise((resolve, reject) => {
$axios.get(url, Object.assign({}, ...args)).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装POST方法
const post = function (url, data = {}, ...args) {
return new Promise((resolve, reject) => {
$axios.post(url, data, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装get请求方法,自动添加参数
const addArrayParamsByGet = function (url, [params, ...args]) {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.get(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装post请求方法,自动添加参数
const addFormDataParamsByPost = (url, [params, ...args]) => {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.post(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
export default {
get,
post,
addArrayParamsByGet,
addFormDataParamsByPost
};

View File

@ -0,0 +1,97 @@
import $axios from '@/utils/axios';
// import server from './server.config';
import Qs from 'qs';
import {
Message
} from 'element-plus';
import router from '@/router/index';
/**
* code为非1000是抛错 可结合自己业务进行修改
*
* **/
const dealResponse = function (response, resolve) {
let res = response.data;
if (res.code) {
if (res.code === 1000 || res.code === 200) {
resolve(res);
} else if (res.code === 401) {
Message({
type: 'error',
message: `['尚未登录授权或授权过期,请登录']`
});
router.replace({
path: '/login'
});
resolve(res);
} else {
Message({
type: 'error',
message: `[${res.code},${res.message}]`
});
console.log("社事件")
resolve(res);
}
} else {
// 二进制无res.code
resolve(response);
}
};
// 封装GET方法
const get = function (url, ...args) {
return new Promise((resolve, reject) => {
$axios.get(url, Object.assign({}, ...args)).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装POST方法
const post = function (url, data = {}, ...args) {
return new Promise((resolve, reject) => {
$axios.post(url, data, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装get请求方法,自动添加参数
const addArrayParamsByGet = function (url, [params, ...args]) {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.get(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装post请求方法,自动添加参数
const addFormDataParamsByPost = (url, [params, ...args]) => {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.post(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
export default {
get,
post,
addArrayParamsByGet,
addFormDataParamsByPost
};

View File

@ -0,0 +1,95 @@
import $axios from '@/utils/axios';
// import server from './server.config';
import Qs from 'qs';
import router from '@/router/index';
/**
* code为非1000是抛错 可结合自己业务进行修改
*
* **/
const dealResponse = function (response, resolve) {
let res = response.data;
if (res.code) {
if (res.code === 1000 || res.code === 200) {
resolve(res);
} else if (res.code === 401) {
Message({
type: 'error',
message: `['尚未登录授权或授权过期,请登录']`
});
router.replace({
path: '/login'
});
resolve(res);
} else {
Message({
type: 'error',
message: `[${res.code},${res.message}]`
});
console.log("社事件")
resolve(res);
}
} else {
// 二进制无res.code
resolve(response);
}
};
// 封装GET方法
const get = function (url, ...args) {
return new Promise((resolve, reject) => {
$axios.get(url, Object.assign({}, ...args)).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装POST方法
const post = function (url, data = {}, ...args) {
return new Promise((resolve, reject) => {
$axios.post(url, data, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装get请求方法,自动添加参数
const addArrayParamsByGet = function (url, [params, ...args]) {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.get(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装post请求方法,自动添加参数
const addFormDataParamsByPost = (url, [params, ...args]) => {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.post(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
export default {
get,
post,
addArrayParamsByGet,
addFormDataParamsByPost
};

View File

@ -0,0 +1,97 @@
import $axios from '@/utils/axios';
// import server from './server.config';
import Qs from 'qs';
import {
Message
} from 'element-plus';
import router from '@/router/index';
/**
* code为非1000是抛错 可结合自己业务进行修改
*
* **/
const dealResponse = function (response, resolve) {
let res = response.data;
if (res.code) {
if (res.code === 1000 || res.code === 200) {
resolve(res);
} else if (res.code === 401) {
Message({
type: 'error',
message: `['尚未登录授权或授权过期,请登录']`
});
router.replace({
path: '/login'
});
resolve(res);
} else {
Message({
type: 'error',
message: `[${res.code},${res.message}]`
});
console.log("社事件")
resolve(res);
}
} else {
// 二进制无res.code
resolve(response);
}
};
// 封装GET方法
const get = function (url, ...args) {
return new Promise((resolve, reject) => {
$axios.get(url, Object.assign({}, ...args)).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装POST方法
const post = function (url, data = {}, ...args) {
return new Promise((resolve, reject) => {
$axios.post(url, data, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装get请求方法,自动添加参数
const addArrayParamsByGet = function (url, [params, ...args]) {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.get(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装post请求方法,自动添加参数
const addFormDataParamsByPost = (url, [params, ...args]) => {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.post(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
export default {
get,
post,
addArrayParamsByGet,
addFormDataParamsByPost
};

View File

@ -0,0 +1,97 @@
import $axios from '@/utils/axios';
// import server from './server.config';
import Qs from 'qs';
import {
ElMessage
} from 'element-plus';
import router from '@/router/index';
/**
* code为非1000是抛错 可结合自己业务进行修改
*
* **/
const dealResponse = function (response, resolve) {
let res = response.data;
if (res.code) {
if (res.code === 1000 || res.code === 200) {
resolve(res);
} else if (res.code === 401) {
ElMessage({
type: 'error',
message: `['尚未登录授权或授权过期,请登录']`
});
router.replace({
path: '/login'
});
resolve(res);
} else {
ElMessage({
type: 'error',
message: `[${res.code},${res.message}]`
});
console.log("社事件")
resolve(res);
}
} else {
// 二进制无res.code
resolve(response);
}
};
// 封装GET方法
const get = function (url, ...args) {
return new Promise((resolve, reject) => {
$axios.get(url, Object.assign({}, ...args)).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装POST方法
const post = function (url, data = {}, ...args) {
return new Promise((resolve, reject) => {
$axios.post(url, data, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装get请求方法,自动添加参数
const addArrayParamsByGet = function (url, [params, ...args]) {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.get(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装post请求方法,自动添加参数
const addFormDataParamsByPost = (url, [params, ...args]) => {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.post(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
export default {
get,
post,
addArrayParamsByGet,
addFormDataParamsByPost
};

View File

@ -0,0 +1,361 @@
<template>
<Header></Header>
<div class="fixed">
<div class="bgColor">
<h1 class="main-shopcart">购物车</h1>
</div>
<div class="container">
<div class="main">
<div class="nav">
<span class="left">全部课程</span>
</div>
<ul class="head">
<li class="item check">
<el-checkbox
v-model='checkAll'
@change='fnCheckAll'
>全选</el-checkbox>
</li>
<li class="item classInfo">课程信息</li>
<li class="item price">单价</li>
<li class="item count">数量</li>
<li class="item total">金额</li>
<li class="item function">操作</li>
</ul>
<div v-if="true">
<ul
class="haveorder"
v-for='(item,index) in cartList'
:key='item.id'
>
<li class="order-item">
<el-checkbox
v-model='item.check'
@change='cartStore.checkItem(index)'
></el-checkbox>
</li>
<li class="order-item info" >
<div class="courseimg" >
<img :src="item.courseCover" alt="">
</div>
<div class="course-name">{{item.courseName}}</div>
</li>
<li class="order-item">{{ item.discountPrice }}</li>
<li class="order-item num">1</li>
<li class="order-item totoalprice">{{ item.discountPrice }}</li>
<li class="order-item delete" >
<a href="javascript:;">
<i class="el-icon-delete"></i>
<span class="deletd-text" @click="deleteCart(item.id)">删除</span>
</a>
</li>
</ul>
</div>
<div class="noOrder" v-else>
<img src="/image/norder365.png" alt="">
<div class="order-alert">哎呦暂无订单</div>
</div>
<el-divider class="line"></el-divider>
<ul class="foot">
<li class="foot-item">已选课程<span class="unique">{{ total.number }}</span></li>
<li class="foot-item">合计<span class="unique">{{ total.price }}</span></li>
<li >
<button class="btn">去结算</button>
</li>
</ul>
</div>
</div>
</div>
<Foot></Foot>
</template>
<script setup>
//
import Header from '../components/common/Header.vue'
import Foot from '../components/common/Foot.vue'
import { storeToRefs } from 'pinia';
import { useCartStore } from '@/store/cart.js'
import { getShopCarList,deleteShopCar } from '@/api/Cart/index.js'
import { onBeforeMount } from 'vue'
import { ElMessageBox } from 'element-plus';
import { ElMessage } from 'element-plus';
let cartStore = useCartStore();
let { cartList , checkAll , total , select } = storeToRefs(cartStore);
//
onBeforeMount(async ()=>{
const res = await getShopCarList()
cartStore.getCartList( res.data.list )
})
//
const fnCheckAll = ()=>{
if( checkAll.value ){
cartStore.unAll();
}else{
cartStore.all();
}
}
const deleteCart = async (id) => {
ElMessageBox.confirm('确定删除该课程吗?', '删除', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
createToken().then(res=>{
let token = res.data.token;
deleteShopCar({
id
},token)
})
ElMessage.success({
message: '删除成功!'
});
}).catch(() => {
ElMessage.info({
message: '已取消删除'
});
});
}
</script>
<style scoped>
.fixed{
width: 100%;
height: 100%;
background: #FFFFFF;
}
.bgColor{
width: 100%;
height: 200px;
background-color: red;
background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
background-size: 400% 400%;
animation: gradient 15s ease infinite;
}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.container{
width: 1200px;
margin: -100px auto 50px auto;
background: #EBEDF2;
border-radius: 12px;
box-shadow: 0px 2px 5px #888888;
}
.main{
padding:20px;
border-radius: 5px;
}
.main-shop{
position: relative;
display: flex;
align-content: center;
}
.main-shop i{
font-size: 35px;
padding: 20px 10px 0 0;
color: #FF4400;
font-weight: bold;
}
.main-shopcart{
width: 1200px;
margin: 0 auto;
height: 42px;
font-size: 24px;
font-family: Microsoft YaHei;
font-weight: bold;
line-height: 35px;
color: #FFFFFF;
padding: 30px 0;
opacity: 1;
}
.nav{
display: flex;
justify-content: space-between;
border-bottom: 2px solid #E6E6E6;
}
.nav .left{
width: 80px;
height: 26px;
font-size: 18px;
font-family: Microsoft YaHei;
font-weight: bold;
line-height: 0px;
color: #FF4400;
opacity: 1;
border-bottom: 2px solid #FF4400;
}
.nav .right{
width: 108px;
height: 24px;
font-size: 14px;
font-family: Microsoft YaHei;
font-weight: 400;
line-height: 0px;
color: #333333;
opacity: 0.5;
}
/* 头部开始 */
.head{
display: flex;
padding: 0 10px;
margin: 20px 0;
width: 100%;
height: 35px;
line-height: 35px;
background: #FCFCFC;
opacity: 1;
border-radius: 0px;
box-sizing: border-box;
border-radius: 5px;
box-shadow: 0px 2px 5px 2px #cccccc;
}
.head .item{
width: 150px;
font-size: 14px;
color: #333333;
}
.check .all{
margin-right: 10px;
}
.check .text{
width: 1487px;
height: 40px;
}
.classInfo{
width: 400px!important;
color: #333333;
}
/* 头部结束 */
/* 订单开始 */
.haveorder{
display: flex;
width: 100%;
height: 200px;
background: #FCFCFC;
margin-bottom: 10px;
border-radius: 5px;
box-shadow: 0px 2px 5px 2px #cccccc;
}
.haveorder .order-item{
height: 200px;
line-height: 200px;
margin: 5px;
}
.order-item:first-child{
width: 30px;
}
.order-item{
width: 150px;
font-size: 16px;
color: #333333;
}
.totoalprice{
color: #E2231A;
}
.num{
width: 120px !important;
padding-left: 15px;
}
.info{
display: flex;
width: 470px !important;
height: 200px;
line-height: 200px;
}
.courseimg{
margin:40px 20px 40px 0;
width: 200px;
height: 120px;
}
.courseimg img{
width: 100%;
height: 100%;
}
.info .course-name{
width: 300px;
word-break: keep-all;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.delete{
cursor: pointer;
}
.deletd-text{
margin-left: 5px;
}
/* 订单结束 */
/* 暂无订单开始 */
.noOrder{
width: 100%;
height: 100%;
text-align: center;
margin:200px 0;
}
.order-alert{
height: 31px;
font-size: 20px;
font-family: Microsoft YaHei;
font-weight: 400;
line-height: 0px;
color: #B5B9BC;
opacity: 1;
margin:20px 120px;
}
/* 暂无订单结束 */
.foot{
display: flex;
justify-content: flex-end;
width: 100%;
height: 40px;
line-height: 40px;
color: #333333;
margin-bottom: 10px;
}
.foot-item{
width: 120px;
height: 40px;
line-height: 40px;
font-size: 14px;
font-weight: 400;
color: #333333;
}
.unique{
margin-left: 5px;
font-size: 24px;
color: #FF4400;
}
.btn{
width: 120px;
height: 40px;
margin-left: 20px;
border: none;
color: #FFFFFF;
font-size: 22px;
border-radius: 5px;
background: #FF4400;
cursor: pointer;
box-shadow: 0px 3px 5px 2px #ff727f;
}
</style>

View File

@ -0,0 +1,361 @@
<template>
<Header></Header>
<div class="fixed">
<div class="bgColor">
<h1 class="main-shopcart">购物车</h1>
</div>
<div class="container">
<div class="main">
<div class="nav">
<span class="left">全部课程</span>
</div>
<ul class="head">
<li class="item check">
<el-checkbox
v-model='checkAll'
@change='fnCheckAll'
>全选</el-checkbox>
</li>
<li class="item classInfo">课程信息</li>
<li class="item price">单价</li>
<li class="item count">数量</li>
<li class="item total">金额</li>
<li class="item function">操作</li>
</ul>
<div v-if="true">
<ul
class="haveorder"
v-for='(item,index) in cartList'
:key='item.id'
>
<li class="order-item">
<el-checkbox
v-model='item.check'
@change='cartStore.checkItem(index)'
></el-checkbox>
</li>
<li class="order-item info" >
<div class="courseimg" >
<img :src="item.courseCover" alt="">
</div>
<div class="course-name">{{item.courseName}}</div>
</li>
<li class="order-item">{{ item.discountPrice }}</li>
<li class="order-item num">1</li>
<li class="order-item totoalprice">{{ item.discountPrice }}</li>
<li class="order-item delete" >
<a href="javascript:;">
<i class="el-icon-delete"></i>
<span class="deletd-text" @click="deleteCart(item.id)">删除</span>
</a>
</li>
</ul>
</div>
<div class="noOrder" v-else>
<img src="/image/norder365.png" alt="">
<div class="order-alert">哎呦暂无订单</div>
</div>
<el-divider class="line"></el-divider>
<ul class="foot">
<li class="foot-item">已选课程<span class="unique">{{ total.number }}</span></li>
<li class="foot-item">合计<span class="unique">{{ total.price }}</span></li>
<li >
<button class="btn">去结算</button>
</li>
</ul>
</div>
</div>
</div>
<Foot></Foot>
</template>
<script setup>
//
import Header from '../components/common/Header.vue'
import Foot from '../components/common/Foot.vue'
import { storeToRefs } from 'pinia';
import { useCartStore } from '@/store/cart.js'
import { getShopCarList,deleteShopCar } from '@/api/index.js'
import { onBeforeMount } from 'vue'
import { ElMessageBox } from 'element-plus';
import { ElMessage } from 'element-plus';
let cartStore = useCartStore();
let { cartList , checkAll , total , select } = storeToRefs(cartStore);
//
onBeforeMount(async ()=>{
const res = await getShopCarList()
cartStore.getCartList( res.data.list )
})
//
const fnCheckAll = ()=>{
if( checkAll.value ){
cartStore.unAll();
}else{
cartStore.all();
}
}
const deleteCart = async (id) => {
ElMessageBox.confirm('确定删除该课程吗?', '删除', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
createToken().then(res=>{
let token = res.data.token;
deleteShopCar({
id
},token)
})
ElMessage.success({
message: '删除成功!'
});
}).catch(() => {
ElMessage.info({
message: '已取消删除'
});
});
}
</script>
<style scoped>
.fixed{
width: 100%;
height: 100%;
background: #FFFFFF;
}
.bgColor{
width: 100%;
height: 200px;
background-color: red;
background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
background-size: 400% 400%;
animation: gradient 15s ease infinite;
}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.container{
width: 1200px;
margin: -100px auto 50px auto;
background: #EBEDF2;
border-radius: 12px;
box-shadow: 0px 2px 5px #888888;
}
.main{
padding:20px;
border-radius: 5px;
}
.main-shop{
position: relative;
display: flex;
align-content: center;
}
.main-shop i{
font-size: 35px;
padding: 20px 10px 0 0;
color: #FF4400;
font-weight: bold;
}
.main-shopcart{
width: 1200px;
margin: 0 auto;
height: 42px;
font-size: 24px;
font-family: Microsoft YaHei;
font-weight: bold;
line-height: 35px;
color: #FFFFFF;
padding: 30px 0;
opacity: 1;
}
.nav{
display: flex;
justify-content: space-between;
border-bottom: 2px solid #E6E6E6;
}
.nav .left{
width: 80px;
height: 26px;
font-size: 18px;
font-family: Microsoft YaHei;
font-weight: bold;
line-height: 0px;
color: #FF4400;
opacity: 1;
border-bottom: 2px solid #FF4400;
}
.nav .right{
width: 108px;
height: 24px;
font-size: 14px;
font-family: Microsoft YaHei;
font-weight: 400;
line-height: 0px;
color: #333333;
opacity: 0.5;
}
/* 头部开始 */
.head{
display: flex;
padding: 0 10px;
margin: 20px 0;
width: 100%;
height: 35px;
line-height: 35px;
background: #FCFCFC;
opacity: 1;
border-radius: 0px;
box-sizing: border-box;
border-radius: 5px;
box-shadow: 0px 2px 5px 2px #cccccc;
}
.head .item{
width: 150px;
font-size: 14px;
color: #333333;
}
.check .all{
margin-right: 10px;
}
.check .text{
width: 1487px;
height: 40px;
}
.classInfo{
width: 400px!important;
color: #333333;
}
/* 头部结束 */
/* 订单开始 */
.haveorder{
display: flex;
width: 100%;
height: 200px;
background: #FCFCFC;
margin-bottom: 10px;
border-radius: 5px;
box-shadow: 0px 2px 5px 2px #cccccc;
}
.haveorder .order-item{
height: 200px;
line-height: 200px;
margin: 5px;
}
.order-item:first-child{
width: 30px;
}
.order-item{
width: 150px;
font-size: 16px;
color: #333333;
}
.totoalprice{
color: #E2231A;
}
.num{
width: 120px !important;
padding-left: 15px;
}
.info{
display: flex;
width: 470px !important;
height: 200px;
line-height: 200px;
}
.courseimg{
margin:40px 20px 40px 0;
width: 200px;
height: 120px;
}
.courseimg img{
width: 100%;
height: 100%;
}
.info .course-name{
width: 300px;
word-break: keep-all;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.delete{
cursor: pointer;
}
.deletd-text{
margin-left: 5px;
}
/* 订单结束 */
/* 暂无订单开始 */
.noOrder{
width: 100%;
height: 100%;
text-align: center;
margin:200px 0;
}
.order-alert{
height: 31px;
font-size: 20px;
font-family: Microsoft YaHei;
font-weight: 400;
line-height: 0px;
color: #B5B9BC;
opacity: 1;
margin:20px 120px;
}
/* 暂无订单结束 */
.foot{
display: flex;
justify-content: flex-end;
width: 100%;
height: 40px;
line-height: 40px;
color: #333333;
margin-bottom: 10px;
}
.foot-item{
width: 120px;
height: 40px;
line-height: 40px;
font-size: 14px;
font-weight: 400;
color: #333333;
}
.unique{
margin-left: 5px;
font-size: 24px;
color: #FF4400;
}
.btn{
width: 120px;
height: 40px;
margin-left: 20px;
border: none;
color: #FFFFFF;
font-size: 22px;
border-radius: 5px;
background: #FF4400;
cursor: pointer;
box-shadow: 0px 3px 5px 2px #ff727f;
}
</style>

View File

@ -0,0 +1,361 @@
<template>
<Header></Header>
<div class="fixed">
<div class="bgColor">
<h1 class="main-shopcart">购物车</h1>
</div>
<div class="container">
<div class="main">
<div class="nav">
<span class="left">全部课程</span>
</div>
<ul class="head">
<li class="item check">
<el-checkbox
v-model='checkAll'
@change='fnCheckAll'
>全选</el-checkbox>
</li>
<li class="item classInfo">课程信息</li>
<li class="item price">单价</li>
<li class="item count">数量</li>
<li class="item total">金额</li>
<li class="item function">操作</li>
</ul>
<div v-if="true">
<ul
class="haveorder"
v-for='(item,index) in cartList'
:key='item.id'
>
<li class="order-item">
<el-checkbox
v-model='item.check'
@change='cartStore.checkItem(index)'
></el-checkbox>
</li>
<li class="order-item info" >
<div class="courseimg" >
<img :src="item.courseCover" alt="">
</div>
<div class="course-name">{{item.courseName}}</div>
</li>
<li class="order-item">{{ item.discountPrice }}</li>
<li class="order-item num">1</li>
<li class="order-item totoalprice">{{ item.discountPrice }}</li>
<li class="order-item delete" >
<a href="javascript:;">
<i class="el-icon-delete"></i>
<span class="deletd-text" @click="deleteCart(item.id)">删除</span>
</a>
</li>
</ul>
</div>
<div class="noOrder" v-else>
<img src="/image/norder365.png" alt="">
<div class="order-alert">哎呦暂无订单</div>
</div>
<el-divider class="line"></el-divider>
<ul class="foot">
<li class="foot-item">已选课程<span class="unique">{{ total.number }}</span></li>
<li class="foot-item">合计<span class="unique">{{ total.price }}</span></li>
<li >
<button class="btn">去结算</button>
</li>
</ul>
</div>
</div>
</div>
<Foot></Foot>
</template>
<script setup>
//
import Header from '../components/common/Header.vue'
import Foot from '../components/common/Foot.vue'
import { storeToRefs } from 'pinia';
import { useCartStore } from '@/store/cart.js'
import { getShopCarList } from '@/api/index.js'
import { onBeforeMount } from 'vue'
import { ElMessageBox } from 'element-plus';
import { ElMessage } from 'element-plus';
let cartStore = useCartStore();
let { cartList , checkAll , total , select } = storeToRefs(cartStore);
//
onBeforeMount(async ()=>{
const res = await getShopCarList()
cartStore.getCartList( res.data.list )
})
//
const fnCheckAll = ()=>{
if( checkAll.value ){
cartStore.unAll();
}else{
cartStore.all();
}
}
const deleteCart = async (id) => {
ElMessageBox.confirm('确定删除该课程吗?', '删除', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
createToken().then(res=>{
let token = res.data.token;
deleteShopCar({
id
},token)
})
ElMessage.success({
message: '删除成功!'
});
}).catch(() => {
ElMessage.info({
message: '已取消删除'
});
});
}
</script>
<style scoped>
.fixed{
width: 100%;
height: 100%;
background: #FFFFFF;
}
.bgColor{
width: 100%;
height: 200px;
background-color: red;
background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
background-size: 400% 400%;
animation: gradient 15s ease infinite;
}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.container{
width: 1200px;
margin: -100px auto 50px auto;
background: #EBEDF2;
border-radius: 12px;
box-shadow: 0px 2px 5px #888888;
}
.main{
padding:20px;
border-radius: 5px;
}
.main-shop{
position: relative;
display: flex;
align-content: center;
}
.main-shop i{
font-size: 35px;
padding: 20px 10px 0 0;
color: #FF4400;
font-weight: bold;
}
.main-shopcart{
width: 1200px;
margin: 0 auto;
height: 42px;
font-size: 24px;
font-family: Microsoft YaHei;
font-weight: bold;
line-height: 35px;
color: #FFFFFF;
padding: 30px 0;
opacity: 1;
}
.nav{
display: flex;
justify-content: space-between;
border-bottom: 2px solid #E6E6E6;
}
.nav .left{
width: 80px;
height: 26px;
font-size: 18px;
font-family: Microsoft YaHei;
font-weight: bold;
line-height: 0px;
color: #FF4400;
opacity: 1;
border-bottom: 2px solid #FF4400;
}
.nav .right{
width: 108px;
height: 24px;
font-size: 14px;
font-family: Microsoft YaHei;
font-weight: 400;
line-height: 0px;
color: #333333;
opacity: 0.5;
}
/* 头部开始 */
.head{
display: flex;
padding: 0 10px;
margin: 20px 0;
width: 100%;
height: 35px;
line-height: 35px;
background: #FCFCFC;
opacity: 1;
border-radius: 0px;
box-sizing: border-box;
border-radius: 5px;
box-shadow: 0px 2px 5px 2px #cccccc;
}
.head .item{
width: 150px;
font-size: 14px;
color: #333333;
}
.check .all{
margin-right: 10px;
}
.check .text{
width: 1487px;
height: 40px;
}
.classInfo{
width: 400px!important;
color: #333333;
}
/* 头部结束 */
/* 订单开始 */
.haveorder{
display: flex;
width: 100%;
height: 200px;
background: #FCFCFC;
margin-bottom: 10px;
border-radius: 5px;
box-shadow: 0px 2px 5px 2px #cccccc;
}
.haveorder .order-item{
height: 200px;
line-height: 200px;
margin: 5px;
}
.order-item:first-child{
width: 30px;
}
.order-item{
width: 150px;
font-size: 16px;
color: #333333;
}
.totoalprice{
color: #E2231A;
}
.num{
width: 120px !important;
padding-left: 15px;
}
.info{
display: flex;
width: 470px !important;
height: 200px;
line-height: 200px;
}
.courseimg{
margin:40px 20px 40px 0;
width: 200px;
height: 120px;
}
.courseimg img{
width: 100%;
height: 100%;
}
.info .course-name{
width: 300px;
word-break: keep-all;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.delete{
cursor: pointer;
}
.deletd-text{
margin-left: 5px;
}
/* 订单结束 */
/* 暂无订单开始 */
.noOrder{
width: 100%;
height: 100%;
text-align: center;
margin:200px 0;
}
.order-alert{
height: 31px;
font-size: 20px;
font-family: Microsoft YaHei;
font-weight: 400;
line-height: 0px;
color: #B5B9BC;
opacity: 1;
margin:20px 120px;
}
/* 暂无订单结束 */
.foot{
display: flex;
justify-content: flex-end;
width: 100%;
height: 40px;
line-height: 40px;
color: #333333;
margin-bottom: 10px;
}
.foot-item{
width: 120px;
height: 40px;
line-height: 40px;
font-size: 14px;
font-weight: 400;
color: #333333;
}
.unique{
margin-left: 5px;
font-size: 24px;
color: #FF4400;
}
.btn{
width: 120px;
height: 40px;
margin-left: 20px;
border: none;
color: #FFFFFF;
font-size: 22px;
border-radius: 5px;
background: #FF4400;
cursor: pointer;
box-shadow: 0px 3px 5px 2px #ff727f;
}
</style>

View File

@ -0,0 +1,362 @@
<template>
<Header></Header>
<div class="fixed">
<div class="bgColor">
<h1 class="main-shopcart">购物车</h1>
</div>
<div class="container">
<div class="main">
<div class="nav">
<span class="left">全部课程</span>
</div>
<ul class="head">
<li class="item check">
<el-checkbox
v-model='checkAll'
@change='fnCheckAll'
>全选</el-checkbox>
</li>
<li class="item classInfo">课程信息</li>
<li class="item price">单价</li>
<li class="item count">数量</li>
<li class="item total">金额</li>
<li class="item function">操作</li>
</ul>
<div v-if="true">
<ul
class="haveorder"
v-for='(item,index) in cartList'
:key='item.id'
>
<li class="order-item">
<el-checkbox
v-model='item.check'
@change='cartStore.checkItem(index)'
></el-checkbox>
</li>
<li class="order-item info" >
<div class="courseimg" >
<img :src="item.courseCover" alt="">
</div>
<div class="course-name">{{item.courseName}}</div>
</li>
<li class="order-item">{{ item.discountPrice }}</li>
<li class="order-item num">1</li>
<li class="order-item totoalprice">{{ item.discountPrice }}</li>
<li class="order-item delete" >
<a href="javascript:;">
<i class="el-icon-delete"></i>
<span class="deletd-text" @click="deleteCart(item.id)">删除</span>
</a>
</li>
</ul>
</div>
<div class="noOrder" v-else>
<img src="/image/norder365.png" alt="">
<div class="order-alert">哎呦暂无订单</div>
</div>
<el-divider class="line"></el-divider>
<ul class="foot">
<li class="foot-item">已选课程<span class="unique">{{ total.number }}</span></li>
<li class="foot-item">合计<span class="unique">{{ total.price }}</span></li>
<li >
<button class="btn">去结算</button>
</li>
</ul>
</div>
</div>
</div>
<Foot></Foot>
</template>
<script setup>
//
import Header from '../components/common/Header.vue'
import Foot from '../components/common/Foot.vue'
import { storeToRefs } from 'pinia';
import { useCartStore } from '@/store/cart.js'
import { getShopCarList } from '@/api/index.js'
import { onBeforeMount } from 'vue'
import { ElMessageBox } from 'element-plus';
import { ElMessage } from 'element-plus';
let cartStore = useCartStore();
let { cartList , checkAll , total , select } = storeToRefs(cartStore);
//
onBeforeMount(async ()=>{
const res = await getShopCarList()
console.log(res,"res")
cartStore.getCartList( res.data.list )
})
//
const fnCheckAll = ()=>{
if( checkAll.value ){
cartStore.unAll();
}else{
cartStore.all();
}
}
const deleteCart = async (id) => {
ElMessageBox.confirm('确定删除该课程吗?', '删除', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
createToken().then(res=>{
let token = res.data.token;
deleteShopCar({
id
},token)
})
ElMessage.success({
message: '删除成功!'
});
}).catch(() => {
ElMessage.info({
message: '已取消删除'
});
});
}
</script>
<style scoped>
.fixed{
width: 100%;
height: 100%;
background: #FFFFFF;
}
.bgColor{
width: 100%;
height: 200px;
background-color: red;
background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
background-size: 400% 400%;
animation: gradient 15s ease infinite;
}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.container{
width: 1200px;
margin: -100px auto 50px auto;
background: #EBEDF2;
border-radius: 12px;
box-shadow: 0px 2px 5px #888888;
}
.main{
padding:20px;
border-radius: 5px;
}
.main-shop{
position: relative;
display: flex;
align-content: center;
}
.main-shop i{
font-size: 35px;
padding: 20px 10px 0 0;
color: #FF4400;
font-weight: bold;
}
.main-shopcart{
width: 1200px;
margin: 0 auto;
height: 42px;
font-size: 24px;
font-family: Microsoft YaHei;
font-weight: bold;
line-height: 35px;
color: #FFFFFF;
padding: 30px 0;
opacity: 1;
}
.nav{
display: flex;
justify-content: space-between;
border-bottom: 2px solid #E6E6E6;
}
.nav .left{
width: 80px;
height: 26px;
font-size: 18px;
font-family: Microsoft YaHei;
font-weight: bold;
line-height: 0px;
color: #FF4400;
opacity: 1;
border-bottom: 2px solid #FF4400;
}
.nav .right{
width: 108px;
height: 24px;
font-size: 14px;
font-family: Microsoft YaHei;
font-weight: 400;
line-height: 0px;
color: #333333;
opacity: 0.5;
}
/* 头部开始 */
.head{
display: flex;
padding: 0 10px;
margin: 20px 0;
width: 100%;
height: 35px;
line-height: 35px;
background: #FCFCFC;
opacity: 1;
border-radius: 0px;
box-sizing: border-box;
border-radius: 5px;
box-shadow: 0px 2px 5px 2px #cccccc;
}
.head .item{
width: 150px;
font-size: 14px;
color: #333333;
}
.check .all{
margin-right: 10px;
}
.check .text{
width: 1487px;
height: 40px;
}
.classInfo{
width: 400px!important;
color: #333333;
}
/* 头部结束 */
/* 订单开始 */
.haveorder{
display: flex;
width: 100%;
height: 200px;
background: #FCFCFC;
margin-bottom: 10px;
border-radius: 5px;
box-shadow: 0px 2px 5px 2px #cccccc;
}
.haveorder .order-item{
height: 200px;
line-height: 200px;
margin: 5px;
}
.order-item:first-child{
width: 30px;
}
.order-item{
width: 150px;
font-size: 16px;
color: #333333;
}
.totoalprice{
color: #E2231A;
}
.num{
width: 120px !important;
padding-left: 15px;
}
.info{
display: flex;
width: 470px !important;
height: 200px;
line-height: 200px;
}
.courseimg{
margin:40px 20px 40px 0;
width: 200px;
height: 120px;
}
.courseimg img{
width: 100%;
height: 100%;
}
.info .course-name{
width: 300px;
word-break: keep-all;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.delete{
cursor: pointer;
}
.deletd-text{
margin-left: 5px;
}
/* 订单结束 */
/* 暂无订单开始 */
.noOrder{
width: 100%;
height: 100%;
text-align: center;
margin:200px 0;
}
.order-alert{
height: 31px;
font-size: 20px;
font-family: Microsoft YaHei;
font-weight: 400;
line-height: 0px;
color: #B5B9BC;
opacity: 1;
margin:20px 120px;
}
/* 暂无订单结束 */
.foot{
display: flex;
justify-content: flex-end;
width: 100%;
height: 40px;
line-height: 40px;
color: #333333;
margin-bottom: 10px;
}
.foot-item{
width: 120px;
height: 40px;
line-height: 40px;
font-size: 14px;
font-weight: 400;
color: #333333;
}
.unique{
margin-left: 5px;
font-size: 24px;
color: #FF4400;
}
.btn{
width: 120px;
height: 40px;
margin-left: 20px;
border: none;
color: #FFFFFF;
font-size: 22px;
border-radius: 5px;
background: #FF4400;
cursor: pointer;
box-shadow: 0px 3px 5px 2px #ff727f;
}
</style>

View File

@ -0,0 +1,46 @@
<template>
<Header></Header>
<NavSwiper></NavSwiper>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div ref="target">
<NewGoodCourse v-if='targetIsVisible'></NewGoodCourse>
</div>
<Foot></Foot>
</template>
<script setup>
import { useIntersectionObserver } from '@vueuse/core'
import Header from '../components/common/Header.vue'
import NavSwiper from '../components/home/NavSwiper.vue'
import Foot from '../components/common/Foot.vue'
const NewGoodCourse = defineAsyncComponent(() =>
import('../components/home/NewGoodCourse.vue')
)
const target = ref(null);
const targetIsVisible = ref(false);
const { stop } = useIntersectionObserver(
target,
([{ isIntersecting }]) => {
if( isIntersecting ) {
targetIsVisible.value = isIntersecting
}
}
)
</script>

View File

@ -0,0 +1,46 @@
<template>
<Header></Header>
<NavSwiper></NavSwiper>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div ref="target">
<NewGoodCourse v-if='targetIsVisible'></NewGoodCourse>
</div>
<Foot></Foot>
</template>
<script setup>
import { useIntersectionObserver } from '@vueuse/core'
import Header from '../components/common/Header.vue'
import NavSwiper from '../components/home/NavSwiper.vue'
import Foot from '../components/common/Foot.vue'
const NewGoodCourse = defineAsyncComponent(() =>
import('../components/home/NewGoodCourse.vue')
)
const target = ref(null);
const targetIsVisible = ref(false);
const { stop } = useIntersectionObserver(
target,
([{ isIntersecting }]) => {
if( isIntersecting ) {
targetIsVisible.value = isIntersecting
}
}
)
</script>

View File

@ -0,0 +1,38 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
</template>
<script setup>
import { useIntersectionObserver } from '@vueuse/core'
import NavSwiper from '../components/home/NavSwiper.vue'
const NewGoodCourse = defineAsyncComponent(() =>
import('../components/home/NewGoodCourse.vue')
)
const target = ref(null);
const targetIsVisible = ref(false);
const { stop } = useIntersectionObserver(
target,
([{ isIntersecting }]) => {
if( isIntersecting ) {
targetIsVisible.value = isIntersecting
}
}
)
</script>

View File

@ -0,0 +1,19 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
</template>
<script setup>
</script>

View File

@ -0,0 +1,20 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button>按钮</el-button>
</template>
<script setup>
</script>

View File

@ -0,0 +1,20 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
</script>

View File

@ -0,0 +1,23 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
Message({
type: 'error',
message: `测得的和`
});
</script>

View File

@ -0,0 +1,26 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import {
Message
} from 'element-plus';
Message({
type: 'error',
message: `测得的和`
});
</script>

View File

@ -0,0 +1,26 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
// import {
// Message
// } from 'element-plus';
// Message({
// type: 'error',
// message: ``
// });
</script>

View File

@ -0,0 +1,26 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import {
Message
} from 'element-plus';
Message({
type: 'error',
message: `测得的和`
});
</script>

View File

@ -0,0 +1,21 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
</script>

View File

@ -0,0 +1,29 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
</script>

View File

@ -0,0 +1,30 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
</script>

View File

@ -0,0 +1,34 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import { onBeforeMount } from 'vue'
//
onBeforeMount(async ()=>{
openVn
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
</script>

View File

@ -0,0 +1,34 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import { onBeforeMount } from 'vue'
//
onBeforeMount(async ()=>{
openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
</script>

View File

@ -0,0 +1,34 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
// import { onBeforeMount } from 'vue'
//
onBeforeMount(async ()=>{
openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
</script>

View File

@ -0,0 +1,33 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
//
onBeforeMount(async ()=>{
openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
</script>

View File

@ -0,0 +1,36 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
//
onBeforeMount(async ()=>{
// openVn()
})
watchEffect(()=>{
openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
</script>

View File

@ -0,0 +1,37 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
//
onBeforeMount(async ()=>{
// openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
watchEffect(()=>{
openVn()
})
</script>

View File

@ -0,0 +1,39 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import {onBeforeMount} from 'vue'
//
onBeforeMount(async ()=>{
// openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
watchEffect(()=>{
openVn()
})
</script>

View File

@ -0,0 +1,39 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import {onBeforeMount,onMount} from 'vue'
//
onMount(async ()=>{
// openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
watchEffect(()=>{
openVn()
})
</script>

View File

@ -0,0 +1,39 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import {onBeforeMount,onMount} from 'vue'
//
onMount(async ()=>{
// openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
// watchEffect(()=>{
// openVn()
// })
</script>

View File

@ -0,0 +1,39 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import {onBeforeMount,onMount} from 'vue'
//
onMount(async ()=>{
openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
// watchEffect(()=>{
// openVn()
// })
</script>

View File

@ -0,0 +1,39 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import {onBeforeMount,onMount} from 'vue'
//
onMount(()=>{
openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
// watchEffect(()=>{
// openVn()
// })
</script>

View File

@ -0,0 +1,39 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div>首页啊</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import {onBeforeMount,onMounted} from 'vue'
//
onMounted(()=>{
openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
// watchEffect(()=>{
// openVn()
// })
</script>

View File

@ -0,0 +1,51 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div class="home">
<span>首页啊</span>
</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import {onBeforeMount,onMounted} from 'vue'
//
onMounted(()=>{
openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
// watchEffect(()=>{
// openVn()
// })
</script>
<style lang="scss" scoped>
.home{
width: 100%;
height: 20px;
span{
color: aqua;
}
}
</style>>

View File

@ -0,0 +1,51 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div class="home">
<span>首页啊</span>
</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import {onBeforeMount,onMounted} from 'vue'
//
onMounted(()=>{
openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
// watchEffect(()=>{
// openVn()
// })
</script>
<style lang="sass" scoped>
.home{
width: 100%;
height: 20px;
span{
color: aqua;
}
}
</style>>

View File

@ -0,0 +1,51 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div class="home">
<span>首页啊</span>
</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import {onBeforeMount,onMounted} from 'vue'
//
onMounted(()=>{
openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
// watchEffect(()=>{
// openVn()
// })
</script>
<style lang="less" scoped>
.home{
width: 100%;
height: 20px;
span{
color: aqua;
}
}
</style>>

View File

@ -0,0 +1,53 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div class="home">
<span class="btn">首页啊</span>
</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import {onBeforeMount,onMounted} from 'vue'
//
onMounted(()=>{
openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
// watchEffect(()=>{
// openVn()
// })
</script>
<style lang="less" scoped>
.home{
width: 100%;
height: 20px;
span{
}
.btn{
color: aquamarine;
}
}
</style>>

View File

@ -0,0 +1,51 @@
<template>
<!-- 两种异步加载的方法
第一个是用Suspense
第二个是用vueuse的插件
-->
<!-- <Suspense>
<template #default>
<NewGoodCourse></NewGoodCourse>
</template>
<template #fallback>
Loading······
</template>
</Suspense> -->
<div class="home">
<span class="btn">首页啊</span>
</div>
<el-button type="primary">按钮</el-button>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import {onBeforeMount,onMounted} from 'vue'
//
onMounted(()=>{
openVn()
})
const openVn = () => {
ElMessage({
message: h('p', null, [
h('span', null, 'Message can be '),
h('i', { style: 'color: teal' }, 'VNode'),
]),
})
}
// watchEffect(()=>{
// openVn()
// })
</script>
<style lang="less" scoped>
.home{
width: 100%;
height: 20px;
.btn{
color: aquamarine;
}
}
</style>>

3
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar"]
}

1
README.md Normal file
View File

@ -0,0 +1 @@
# Vue 3 + Vite + pinia

14
index.html Normal file
View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<link rel="stylesheet" href="//at.alicdn.com/t/font_3438590_p85idk0acv.css">
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

5146
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

30
package.json Normal file
View File

@ -0,0 +1,30 @@
{
"name": "saas",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@vueuse/core": "^8.5.0",
"axios": "^0.27.2",
"crypto-js": "^4.1.1",
"element-plus": "^2.2.2",
"pinia": "^2.0.14",
"pinia-plugin-persist": "^1.0.0",
"qs": "^6.11.0",
"vue": "^3.2.25",
"vue-router": "^4.0.15",
"vue3-video-play": "^1.3.1-beta.6"
},
"devDependencies": {
"@vitejs/plugin-vue": "^2.3.3",
"less": "^4.1.3",
"less-loader": "^11.1.0",
"unplugin-auto-import": "^0.8.5",
"vite": "^2.9.9",
"vite-plugin-require-transform": "^1.0.3"
}
}

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

8
src/App.vue Normal file
View File

@ -0,0 +1,8 @@
<template>
<router-view></router-view>
</template>
<style>
@import './assets/css/reset.css';
</style>

View File

25
src/api/index.js Normal file
View File

@ -0,0 +1,25 @@
import $http from '@/utils/request';
// const API = {
// getdemo(arg) {
// return $http.get(`/api/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
// },
// get() {
// return $http.get(`/api/getinfo?pageNo=1&pageSize=100`)
// },
// add(params) {
// return $http.post('/api/send', params);
// },
// uploadfile(arg) {
// return $http.post(`/api/upload`, arg)
// },
// downloadfile(params) {
// return $http.get(`/api/download?fileId=${params.fileId}`, { responseType: 'blob', })
// },
// getShopCarList(){
// return $http.get('/api/shopcar/getShopCarList')
// }
// };
// export default API;
export function getShopCarList(){
return $http.get('/api/shopcar/getShopCarList')
}

16
src/api/login/index.js Normal file
View File

@ -0,0 +1,16 @@
import $http from '@/utils/request';
export function loginByJson(arg){
return $http.get(`/api/getdemo?currentPage=${arg.currentPage}&pageSize=${arg.pageSize}`);
}
export function loginByMobile(params){
return $http.post('/api/send', params);
}
export function createToken(params){
return $http.get(`/api/download?fileId=${params.fileId}`, { responseType: 'blob', })
}

53
src/assets/css/reset.css Normal file
View File

@ -0,0 +1,53 @@
/* http://meyerweb.com/eric/tools/css/reset/ */
/* v1.0 | 20080212 */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-size: 100%;
vertical-align: baseline;
background: transparent;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
/* remember to define focus styles! */
:focus {
outline: 0;
}
/* remember to highlight inserts somehow! */
ins {
text-decoration: none;
}
del {
text-decoration: line-through;
}
/* tables still need 'cellspacing="0"' in the markup */
table {
border-collapse: collapse;
border-spacing: 0;
}

BIN
src/assets/img/logo1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

10
src/main.js Normal file
View File

@ -0,0 +1,10 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from "./router";
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import store from "./store";
createApp(App).use(router).use(store).use(ElementPlus).mount('#app')

22
src/mixins/E2C.js Normal file
View File

@ -0,0 +1,22 @@
export default function(){
let courseTypeFn = ( type )=>{
let val = '';
switch (type) {
case 1:
val = '初级';
break;
case 2:
val = '中级';
break;
case 3:
val = '高级';
break;
default:
val = '';
}
return val;
}
return {
courseTypeFn
}
}

33
src/router/index.js Normal file
View File

@ -0,0 +1,33 @@
import { createRouter, createWebHistory } from "vue-router";
import { useUserStore } from '@/store/user'
const routes = [
{
path: "/",
name: "Home",
component: () =>import(/* webpackChunkName: "home" */ "../views/Home.vue"),
},
// {
// path:'/cart',
// name:'Cart',
// component: () =>
// import(/* webpackChunkName: "CoursePlay" */ "../views/Cart.vue"),
// beforeEnter: (to, from, next) => {
// if( useUserStore().token ){
// next()
// }else {
// next('/login')
// }
// }
// },
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;

8
src/store/index.js Normal file
View File

@ -0,0 +1,8 @@
import { createPinia } from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'
const store = createPinia()
// 使用持久化插件
store.use(piniaPluginPersist)
export default store

34
src/store/user.js Normal file
View File

@ -0,0 +1,34 @@
// user模块类似于 vuex 中的moduel
import { defineStore } from 'pinia'
// defineStore 类等于 中的 moduel
// useUserStore ,类等于 中的 moduel { useUserStore }
export const useUserStore = defineStore({
// 模块ID
id: 'user',
state: () => {
return {
token: '',
userInfo:{}
}
},
actions:{
setToken( token ){
this.token = token;
} ,
removeToken(){
this.token = '';
}
},
// 开启数据缓存
persist: {
enabled: true,
strategies: [{
// localStorage 的数据 相当于 setLocalStorage
key: 'xiaoluxian_user',
// 模式
storage: localStorage,
//paths: ['token']
}]
}
})

41
src/utils/axios.js Normal file
View File

@ -0,0 +1,41 @@
// import Vue from 'vue';
import axios from 'axios';
// Vue.prototype.axios = axios;
// 创建axios实例
const $axios = axios.create();
$axios.defaults.timeout = 1000 * 50; // 请求超时时间
// request拦截器
$axios.interceptors.request.use(config => {
if (sessionStorage.getItem('token')) {
config.headers.Authorization = sessionStorage.getItem('token')
}
if (navigator.userAgent.indexOf('Trident') != -1) {
if (config.method == 'post') {
config.data = {
...config.data,
t: Date.now()
};
} else if (config.method == 'get') {
config.params = {
...config.params,
t: Date.now()
};
}
}
return config;
}, error => {
return Promise.reject(error);
});
// respone 拦截器
$axios.interceptors.response.use(
response => {
return response;
},
error => {
return Promise.reject(error);
}
);
export default $axios;

20
src/utils/lockPassWord.js Normal file
View File

@ -0,0 +1,20 @@
import CryptoJS from "crypto-js";
const key = CryptoJS.enc.Utf8.parse("AOWQ4P0YEC4YXUKS"); //十六位十六进制数作为密钥
const iv = CryptoJS.enc.Utf8.parse('O3V2GCL1K2HNZ9Y7'); //十六位十六进制数作为密钥偏移量
//解密方法
export function Decrypt(word) {
let encryptedHexStr = CryptoJS.enc.Hex.parse(word);
let srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr);
let decrypt = CryptoJS.AES.decrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
return decryptedStr.toString();
}
//加密方法
export function Encrypt(word) {
let srcs = CryptoJS.enc.Utf8.parse(word);
let encrypted = CryptoJS.AES.encrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
return encrypted.ciphertext.toString().toUpperCase();
}

97
src/utils/request.js Normal file
View File

@ -0,0 +1,97 @@
import $axios from '@/utils/axios';
// import server from './server.config';
import Qs from 'qs';
import {
ElMessage
} from 'element-plus';
import router from '@/router/index';
/**
* code为非1000是抛错 可结合自己业务进行修改
*
* **/
const dealResponse = function (response, resolve) {
let res = response.data;
if (res.code) {
if (res.code === 1000 || res.code === 200) {
resolve(res);
} else if (res.code === 401) {
ElMessage({
type: 'error',
message: `['尚未登录授权或授权过期,请登录']`
});
router.replace({
path: '/login'
});
resolve(res);
} else {
ElMessage({
type: 'error',
message: `[${res.code},${res.message}]`
});
console.log("社事件")
resolve(res);
}
} else {
// 二进制无res.code
resolve(response);
}
};
// 封装GET方法
const get = function (url, ...args) {
return new Promise((resolve, reject) => {
$axios.get(url, Object.assign({}, ...args)).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装POST方法
const post = function (url, data = {}, ...args) {
return new Promise((resolve, reject) => {
$axios.post(url, data, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装get请求方法,自动添加参数
const addArrayParamsByGet = function (url, [params, ...args]) {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.get(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
// 封装post请求方法,自动添加参数
const addFormDataParamsByPost = (url, [params, ...args]) => {
let search = Qs.stringify(params, {
arrayFormat: 'repeat'
});
url = url + '?' + search;
return new Promise((resolve, reject) => {
$axios.post(url, ...args).then(res => {
dealResponse(res, resolve);
}).catch(err => {
reject(err);
});
});
};
export default {
get,
post,
addArrayParamsByGet,
addFormDataParamsByPost
};

Some files were not shown because too many files have changed in this diff Show More