前端界面的设计
CourseDetail.cshtml页面
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta charset="utf-8">
<title>课程详情</title>
<link href="~/css/swiper-bundle.min.css" rel="stylesheet" />
<link href="~/css/couseDetail.css" rel="stylesheet" />
<script src="~/js/swiper-bundle.min.js" type="text/javascript" charset="utf-8"></script>
<script src="~/js/vue.js" type="text/javascript" charset="utf-8"></script>
<script src="~/js/jquery.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app" class="app" v-cloak>
<!-- 已购买课程用户列表 -->
<div class="shopUserList">
<!-- 文字走马灯效果实现 -->
<div class="home">
<div class="home-box">
<div>
<div class="marquee">
<div class="marquee_box">
<ul class="marquee_list" :class="{marquee_top:animate}">
<li v-for="(item, index) in shopUserList" :key="index">
<span>{{item+'购买了该课程'}}</span>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 轮播图 -->
<div class="swiper-banner">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="(item,index) in carouselList"> <img :src="item"></div>
</div>
<div class="swiper-pagination"></div>
</div>
<div class="courseDetail">
<div class="title">
<div class="courseName">@ViewBag.title</div>
<div class="coursePrice"> <span>¥</span>{{coursePrice}}</div>
</div>
<div class="courseList" v-if="courseList&&courseList.length>0">
<div v-for="(item,index) in courseList" :class="item.selected?'active courseItem':' courseItem'" @@click="selected(item.count)">
<div>{{item.count=="all"?"全部":item.count}}</div>
<div>{{item.count=="all"?"购买":"节课"}}</div>
</div>
</div>
<div class="other">
<div class="payFreight">
<div class="key">运费 </div>
<div class="value">无需配送</div>
</div>
<hr>
<div class="saleCount">
<div class="key">销量</div>
<div class="value">@ViewBag.buyNum</div>
</div>
<hr>
<div class="remainCount">
<div class="key">剩余</div>
<div class="value">3423</div>
</div>
</div>
<div class="courseIntro">
<div class="courseTitle"> <div class="line"></div><div class="text">课程详情</div><div class="line"></div></div>
<div class="picList">
<div class="picItem" v-for="(item,index) in coursePicList">
<img :src="item">
</div>
</div>
</div>
</div>
<div class="bottom">
<div class="payPrice">{{"¥"+realityPrice}} </div>
<div class="payBtn">立即购买</div>
</div>
</div>
<script type="text/javascript">
var host = "http://kimimath.kyd2002.cn";
//var host = "https://localhost:5001";
var canBuyNum=@ViewBag.canBugNumber;
var price = @ViewBag.price;
var userId = @ViewBag.userId;
var courseId=@ViewBag.courseId;
$(function() {
var swiper = new Swiper('.swiper-banner', {
autoplay: true,
pagination: {
el: '.swiper-pagination',
dynamicBullets: true,
},
});
})
var container = new Vue({
el: "#app",
data() {
return {
animate: false,
carouselList: ["/image/banner1.png", "/image/banner2.png", "/image/banner3.png", "/image/banner4.png"],
shopUserList: ['沫**', '沫**1'],
courseList:[],
coursePrice: "90.00",
coursePicList: [
"/image/details_02.png",
"/image/details_03.png",
"/image/details_04.png",
"/image/detail_05.png"
],
realityPrice:0.01,
}
},
methods: {
showMarquee: function() {
this.animate = true;
setTimeout(() => {
this.shopUserList.push(this.shopUserList[0]);
this.shopUserList.shift();
this.animate = false
}, 1000)
},
selected:function(countId){
this.courseList.forEach(function(item){
if(item.count==countId){
item.selected=!item.selected;
}
else {
item.selected=false;
}
})
var _this = this;
var number=@ViewBag.canBugNumber;
if (countId != "all") {
number = countId;
}
var url = host + "/api/Order/RealityPrice";
var datas = { userId: userId, curriculumPackageId: courseId, purchaseQuantity: number };
$.ajax({
url: url,
type: "Get",
data: datas,
dataType: "json",
success: function (result) {
_this.realityPrice = result.Data;
}
})
},
getcourseList() {
var _this = this;
var data = { count: "all", selected: false };
var data1 = { count: "3", selected: false };
var data2 = { count: "6", selected: false };
var data3 = { count: "12", selected: false };
var data4 = { count: "24", selected: false };
if (courseId==4) {
_this.courseList.push(data);
}
else if (canBuyNum < 3) {
_this.courseList.push(data);
}
else if (canBuyNum < 6) {
_this.courseList.push(data1);
_this.courseList.push(data);
}
else if (canBuyNum < 12) {
_this.courseList.push(data1);
_this.courseList.push(data2);
_this.courseList.push(data);
}
else if (canBuyNum < 24) {
_this.courseList.push(data1);
_this.courseList.push(data2);
_this.courseList.push(data3);
_this.courseList.push(data);
}
else {
_this.courseList.push(data1);
_this.courseList.push(data2);
_this.courseList.push(data3);
_this.courseList.push(data4);
_this.courseList.push(data);
}
},
GetPrice() {
if (price > 90) {
if (courseId == 4) {
this.coursePrice = price;
}
else {
this.coursePrice = "90 -" + price;
}
}
else {
this.coursePrice = price;
}
},
},
mounted() {
this.getcourseList();
this.getPrice();
setInterval(this.showMarquee, 2000);
},
})
</script>
</body>
</html>
couseDetail.css
html, body { position: relative; height: 100%; font-family: "Microsoft YaHei"; } html { font-size: 16px; } body { margin: 0; padding: 0; } [v-cloak] { display: none; } /* 轮播样式 */ .swiper-banner { width: 100%; height: 300px; position: relative; overflow-x: hidden; } .swiper-slide { width: 100%; height: 100%; } .swiper-slide img { width: 100%; height: auto; max-height: 100%; } .shopUserList { position: fixed; top: 26px; width: 40%; height: 40px; border-radius: 0px 30px 30px 0px; z-index: 10; z-index: 10; background: rgba(0, 0, 0, 0.7); } /* 走马灯效果实现 */ .home { height: 100%; width: 100%; display: flex; justify-content: center; align-items: center; } .home-box { width: 100%; height: 100%; } .marquee { width: 100%; height: 100%; align-items: center; display: flex; box-sizing: border-box; } .marquee_box { display: block; position: relative; width: 100%; height: 40px; overflow: hidden; } .marquee_list { display: block; position: absolute; top: 0; left: 0; list-style: none; padding: 0; margin: 0; width: 100%; height: 100%; } .marquee_top { transition: all 0.5s; margin-top: -40px } .marquee_list li { height: 100%; padding: 0 5px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; } .marquee_list li span { font-size: 13px; font-size: 0.8125rem; color: #ffffff; } /* 课程详情样式 */ .courseDetail { padding-top: 20px; box-sizing: border-box; padding-bottom: 55px; } .courseDetail .title { margin-bottom: 10px; } .courseDetail .title, .courseDetail .courseList { padding: 0 10px; box-sizing: border-box; display: flex; } .courseDetail .courseName, .courseDetail .coursePrice { display: flex; align-items: center; height: 100%; } .courseDetail .courseName { width: 80%; justify-content: flex-start; } .courseDetail .coursePrice { width: 60%; color: #ff4e00; justify-content: flex-end; font-weight: bold; font-size: 24px; font-size: 1.5rem; } .courseDetail .coursePrice span { font-size: 14px; font-size: 0.875rem; padding-right: 2px; box-sizing: border-box; } .courseName { color: #1e3276; font-size: 18px; font-size: 1.125rem; } .courseDetail .courseList { flex-wrap: wrap; justify-content: space-between; flex-wrap: wrap; } .courseList .courseItem { display: flex; flex-direction: column; align-items: center; justify-content: center; width: 60px; margin-right: 5px; height: 60px; border-radius: 12px; border: solid 1px #a6a7ff; color: #1e3276; margin-bottom: 10px; font-weight: bold; } .courseList .active{ background-color: #ff4e00; color: #fff; border: none; } .courseList .courseItem, .courseDetail .other, .courseIntro .text{ font-size: 15px; font-size: 0.9375rem; } .courseIntro hr { display: inline; height: 30%; } /* 运费等 */ .courseDetail .other { background-color: #f2f2ff; display: flex; height: 50px; margin-top: 10px; flex-direction: row; flex-wrap: nowrap; justify-content: center; align-items: center; padding: 0 10px; } .payFreight, .saleCount, .remainCount { height: 100%; display: flex; justify-content: center; align-items: center; } .other hr { height: 30%; } .other .key { padding-right: 5px; box-sizing: border-box; color: #6d6d9a; } .other .value, .courseIntro .text { color: #1e3276; font-weight: bold; } .picList { width: 100%; } .picList img { width: 100%; height: auto; } .courseTitle { width: 80%; height: 50px; display: flex; align-items: center; margin: 0 auto; justify-content: space-between; } .courseTitle .line { width: 30%; height: 100%; height: 1px; background-color: #e6e5ff; } .bottom { position: fixed; bottom: 0; width: 100%; height: 55px; background-color: #ff4800; border-radius: 20px 20px 0px 0px; padding: 0 20px; box-sizing: border-box; display: flex; justify-content: space-between; align-items: center; font-weight: bold; } .payPrice { height: 100%; display: flex; justify-content: flex-start; align-items: center; width: 30%; color: #ffffff; font-size: 23.5px; font-size: 1.46875rem; } .payBtn { width: 32%; height: 65%; display: flex; background-color: yellow; justify-content: center; align-items: center; background-color: #ffffff; border-radius: 27px; color: #fe6d52; font-size: 15.5px; font-size: 0.96875rem; }
CourseList.cshtml 页面
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<meta charset="utf-8">
<title>课程列表</title>
<link rel="stylesheet" type="text/css" href="~/css/courseList.css" />
<link href="~/js/layer/theme/default/layer.css" rel="stylesheet" />
</head>
<body>
<div id="app" class="app" v-cloak>
<div class="dialog" v-if="showDialog" v-cloak>
<div class="mask">
<div class="maskContent">
<img src="/image/del_press.png" class="closeBtn" @@click="closeDialog">
<img src="/image/popup_img_bg.png" class="dialogBg">
<div class="submitContent" >
<div class="title">
<div>请使用购买课程的手机号码</div>
<div>登录奇米儿童数学APP</div>
</div>
<form>
<div class="phoneNum">
<input type="number" placeholder="请输入手机号" maxlength="11" v-model="phone" />
</div>
<div class="verity">
<div class="verityCode"><input type="number" placeholder="请输入验证码" v-model="verifyCode" /></div>
<div class="verityBtn" @@click="getCode">{{SendverifyCode}}</div>
</div>
<div class="checkbox" @@click="choice">
<div><img :src="selected?'/image/pay_jcon_selected.png':'/image/pay_jcon_unselected.png'"></div>
<div>绑定我的手机号到该公众号</div>
</div>
<div class="submit" @@click="submit">提交</div>
</form>
</div>
</div>
</div>
</div>
<div class="container">
<img src="/image/banner.png" class="banner">
<div class="courseList">
<div class="item" v-for="(item,index) in courseList" @@click="jumpDetail(item.Id,item.Title,item.BuyNum,item.CanBugNumber,item.Price )">
<img :src="item.VerticalIconUrl">
<div class="courseName">{{item.Title}}</div>
<div class="price">
<div class="nowPrice"><span>¥</span>{{item.Price}}</div>
<div class="prePrice">{{"原价¥"+item.OriginalPrice}}</div>
</div>
</div>
</div>
<img src="/image/logo.png" class="logo">
</div>
</div>
<script src="~/js/vue.js" type="text/javascript" charset="utf-8"></script>
<script src="~/js/jquery.js" type="text/javascript" charset="utf-8"></script>
<script src="~/js/layer/layer.js"></script>
<script type="text/javascript">
var openId ="@ViewBag.OpenId";
var host = "http://kimimath.kyd2002.cn";
//var host = " http://192.168.100.3:33003";
var container = new Vue({
el: "#app",
data() {
return {
showDialog: true,
selected: false,
courseList:[],
phone: "",
SendverifyCode: "发送验证码",
time: 120, //验证码发送的间隔(秒)
verifyCode: "",
submitContent: true,
userId: '',
}
},
methods: {
choice: function () {
this.selected = !this.selected;
},
closeDialog: function () {
this.showDialog = false;
},
jumpDetail: function (id, title, buyNum,canBugNumber,price) {
var href = "/Team/WXPay?userId=" + this.userId + "&openId=" + openId + "&courseId=" + id + "&title=" + title + "&buyNum=" + buyNum + "&canBugNumber=" + canBugNumber + "&price=" + price;
window.location.href = href;
},
getCode() {
var _this = this;
var url = host + "/api/UserInfo/SendVerifyCode?phone=" + _this.phone + "";
$.ajax({
url: url,
type: "POST",
async: true,
success: function (result) {
if (result.Code == 1) {
var interval = window.setInterval(function () {
_this.SendverifyCode = '(' + _this.time + '秒)后重发';
_this.time--;
if (_this.time < 0) {
_this.SendverifyCode = "发送验证码";
_this.time = 120;
window.clearInterval(interval);
}
}, 1000);
}
else {
if (result.Code == 7) {
layer.alert('手机号格式不正确, 请输入正确的手机号码!');
}
else if (result.Code == 13) {
layer.alert('短信发送失败,请稍后重试!');
}
else {
layer.alert('服务器异常,请稍后重试!');
}
}
}
})
},
submit() {
var _this = this;
var webPage = true;
var url = host + "/api/UserInfo/Register?phone=" + _this.phone + "&verificationcode=" + _this.verifyCode + "&webPageClient=" + webPage;
$.ajax({
url: url,
type: "POST",
dataType: "json",
contentType: "application/json",
success: function (result) {
if (result.Code == 1) {
_this.userId = result.Data.Id;
_this.GetCourseList();
if (_this.selected == true) {
var dataBing = { phone: _this.phone, openId: openId };
var urlhome = "/home/BingOpenId";
$.ajax({
url: urlhome,
type: "POST",
dataType: "json",
async: true,
data: dataBing,
success: function (res) {
if (res == 1) {
_this.showDialog = false;
}
}
})
}
else {
_this.showDialog = false;
}
}
else {
//注册异常处理
if (result.Code == 4) {
layer.alert('手机号或验证码缺失,请填写完整!');
}
else if (result.Code == 9) {
layer.alert('未发送验证码!');
}
else if (result.Code == 10) {
layer.alert('验证码已过期!');
}
else if (result.Code == 8) {
layer.alert('验证码错误!');
}
else {
layer.alert('服务器异常,请重新发送验证码');
}
}
}
});
},
GetCourseList() {
var _this = this;
var userId = _this.userId;
var url = host + "/api/Course/ProductList";
var data = { userId: userId };
$.ajax({
url: url,
data: data,
dataType: "json",
type: "GET",
success: function (result) {
var list = result.Data.curriculumPackageDtoList;
var newList = list.sort(function (a, b) { return a.Id - b.Id });
newList.pop();
_this.courseList = newList;
}
})
},
JudgeIsBindPhone() {
var _this = this;
var url = "GetUserId?openId=" + openId;
$.ajax({
url: url,
type: "POST",
dataType: "JSON",
success: function (result) {
if (result != 0) {
_this.showDialog = false;
_this.userId = result;
_this.GetCourseList();
}
else {
_this.showDialog = true;
}
}
})
},
},
mounted() {
this.JudgeIsBindPhone();
// 页面开始加载时修改font-size
var html = document.getElementsByTagName("html")[0];
var oWidth = document.body.clientWidth || document.documentElement.clientWidth;
// 这里的750是指设计图的大小,自己根据实际情况改变
html.style.fontSize = oWidth / 750 * 30 + "px";
console.log('rem:', html.style.fontSize);
}
})
</script>
</body>
</html>
courseList.css
body { padding: 0; margin: 0; } /* 弹框效果 */ .dialog { position: fixed; width: 100%; height: 100%; z-index: 1; } .mask { width: 100%; height: 100%; background: rgba(0, 0, 0, 0.7); display: flex; position: relative; } .closeBtn { position: absolute; top: 10%; right: 10px; width: 20px; height: auto; z-index: 10; } .maskContent { width: 85%; height: 500px; display: flex; align-self: center; position: relative; justify-content: center; align-items: center; margin: 0 auto; } .dialogBg { position: absolute; top: 0; width: 100%; height: auto; max-height: 100%; z-index: 3; } .submitContent { position: absolute; top: 15%; width: 100%; height: 90%; z-index: 4; } .submitContent .title { width: 100%; text-align: center; margin: 0 auto; color: #000000; font-size: 16px; font-size: 1rem; } form { width: 100%; height: 100%; margin-top: 10px; } .phoneNum { width: 90%; height: 40px; margin: 0 auto; display: flex; justify-content: center; align-items: center; } .phoneNum input { width: 100%; height: 100%; border-radius: 41px; border: solid 1px #d2d0ef; padding: 0 10px; box-sizing: border-box; text-align:center } input { border: none; outline: none; } .verity { display: flex; width: 90%; justify-content: space-between; height: 40px; margin: 0 auto; margin-top: 15px; } .verity .verityCode { width:50%; height: 100%; } .verity input { width: 100%; height: 100%; border-radius: 41px; border: solid 1px #d2d0ef; padding: 0 10px; text-align:center; } .verityBtn { width: 40%; height: 100%; background-color: #e8e6ff; border-radius: 41px; display: flex; justify-content: center; align-items: center; color: #7f7bb8; } .checkbox { display: flex; width: 80%; margin: 0 auto; height: 40px; align-items: center; margin-top: 10px; color: #969696; font-size: 14px; font-size: 0.875rem; } .checkbox img { width: 35px; height: auto; padding-right: 10px; box-sizing: border-box; } .submit { width: 90%; height: 40px; margin: 0 auto; margin-top: 5px; background-color: #fd7c48; border-radius: 41px; display: flex; align-items: center; justify-content: center; color: #ffffff; font-size: 18px; font-size: 1.125rem; } /*top */ .container { width: 100%; padding-bottom: 20px; } .container .banner { display: block; width: 100%; height: auto; } .courseList { padding: 12px; box-sizing: border-box; display: flex; flex-wrap: wrap; justify-content: space-between; } .courseList .item { width: 47%; margin-bottom: 20px; } .courseList .courseName { margin-top: 5px; font-size: 16.8px; font-size: 1.05rem; color: #585858; } .courseList img { display: block; width: 100%; height: auto; border-radius: 10px; } .courseList .price { margin-top: 5px; display: flex; justify-content: space-between; align-items: center; } .nowPrice { color: #ff3600; font-weight: bold; font-size: 18px; font-size: 1.125rem; } .nowPrice span { font-size: 14px; } .courseList .prePrice { text-decoration: line-through; color: #979797; font-size: 14px; font-size: 0.875rem; } .logo{ width:30%; height: auto; display: block; margin: 0 auto; } .Message { height: 50%; justify-content: center; align-items: center; display: flex; font-size: 20px; }
下载layer时,要整个包都导入,否则会报错找不到文件(虽然这个报错不影响整体,看着不舒服)
2 遇到的一些问题
在方法中定义 var _this=this;
_this只是一个变量名,this代表父函数,如果在子函数(比如ajax中的success)还用this,this的指向就变成子函数了
浙公网安备 33010602011771号