|
|
@@ -0,0 +1,561 @@
|
|
|
+<template>
|
|
|
+ <div class="Info">
|
|
|
+ <Back />
|
|
|
+ <div class="topImg">
|
|
|
+ <img :src="baseURL + data.filePath" alt="" />
|
|
|
+ </div>
|
|
|
+ <div class="name">{{ data.name }}</div>
|
|
|
+ <!-- 活动时间 -->
|
|
|
+ <div class="time">
|
|
|
+ <p>
|
|
|
+ 活动时间  <span>{{ data.startDay }}-{{ data.endDay }}</span>
|
|
|
+ </p>
|
|
|
+ <div class="week">
|
|
|
+ <div class="weekBox" :style="`width:${week.length * 100 + 50}px`">
|
|
|
+ <div
|
|
|
+ v-for="(item, index) in week"
|
|
|
+ :key="index"
|
|
|
+ :class="{ active: weekId === index }"
|
|
|
+ @click="selectWeek(index, item.tempFlag, item.date)"
|
|
|
+ >
|
|
|
+ <div class="one">{{ item.name }}</div>
|
|
|
+ <div>{{ item.num }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="xian"></div>
|
|
|
+ <!-- 活动时段 -->
|
|
|
+ <div class="section time">
|
|
|
+ <p>活动时段</p>
|
|
|
+ <div class="week">
|
|
|
+ <div class="weekBox" :style="`width:${section.length * 170 + 50}px`">
|
|
|
+ <div
|
|
|
+ v-for="(item, index) in section"
|
|
|
+ :key="index"
|
|
|
+ :class="{ active: sectionId === index, dis: timeFlag && item.dis }"
|
|
|
+ @click="selectSection(index, item.startTime, item.endTime, item.id)"
|
|
|
+ >
|
|
|
+ <div class="one">{{ item.startTime }}-{{ item.endTime }}</div>
|
|
|
+ <div v-if="timeFlag && item.dis">已结束预约</div>
|
|
|
+ <div v-else>剩余:{{ item.quota }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="xian"></div>
|
|
|
+ <!-- 个人信息 -->
|
|
|
+ <div class="time">
|
|
|
+ <p>个人信息</p>
|
|
|
+ <div class="from">
|
|
|
+ <div class="row">
|
|
|
+ <div class="name">姓  名:</div>
|
|
|
+ <input
|
|
|
+ onblur="value=value.replace(/[^a-zA-Z\u4e00-\u9fa5]/g,'')"
|
|
|
+ maxlength="10"
|
|
|
+ type="text"
|
|
|
+ v-model="from.name"
|
|
|
+ placeholder="请输入参与活动者的姓名"
|
|
|
+ />
|
|
|
+ <div class="tit" v-show="fromFlag.name">请输入正确的姓名</div>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <div class="name">身份证号:</div>
|
|
|
+ <input
|
|
|
+ @blur="blurInput"
|
|
|
+ type="text"
|
|
|
+ v-model="from.identity"
|
|
|
+ placeholder="请输入参与活动者的身份证号"
|
|
|
+ />
|
|
|
+ <div class="tit" v-show="fromFlag.identity">请输入正确的身份证号</div>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <div class="name">手 机 号:</div>
|
|
|
+ <input
|
|
|
+ type="text"
|
|
|
+ @blur="blurPhone"
|
|
|
+ v-model="from.phone"
|
|
|
+ placeholder="请输入手机号"
|
|
|
+ />
|
|
|
+ <div class="tit" v-show="fromFlag.phone">请输入正确的手机号</div>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <div class="name">人  数:</div>
|
|
|
+ <input type="text" disabled v-model="from.num" />
|
|
|
+ <div class="numChange">
|
|
|
+ <van-icon
|
|
|
+ name="minus"
|
|
|
+ :class="{ none: from.num > 1 }"
|
|
|
+ @click.native="from.num--"
|
|
|
+ />
|
|
|
+ <van-icon
|
|
|
+ name="plus"
|
|
|
+ :class="{ none: from.num < 3 }"
|
|
|
+ @click.native="from.num++"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="row">
|
|
|
+ <div class="name">年  龄:</div>
|
|
|
+ <input type="text" disabled v-model="from.age" />
|
|
|
+ <div class="tit" v-if="fromFlag.age">
|
|
|
+ 您的年龄不符合要求({{ data.age.split(",")[0] }}岁-{{
|
|
|
+ data.age.split(",")[1]
|
|
|
+ }}岁)
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 按钮 -->
|
|
|
+ <div class="btn" @click="save">立即预约</div>
|
|
|
+ </div>
|
|
|
+ <ToIndex />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { Dialog } from "vant";
|
|
|
+import Back from "../components/Back.vue";
|
|
|
+import ToIndex from "../components/ToIndex.vue";
|
|
|
+import axios from "@/utlis/request";
|
|
|
+import { webDetailApi, timeBucketDetail, activityApply } from "../utlis/api";
|
|
|
+export default {
|
|
|
+ name: "Info",
|
|
|
+ components: { Back, ToIndex },
|
|
|
+ data() {
|
|
|
+ //这里存放数据
|
|
|
+ return {
|
|
|
+ baseURL: "",
|
|
|
+ data: {},
|
|
|
+ // 活动时间
|
|
|
+ week: [],
|
|
|
+ weekId: null,
|
|
|
+ // 活动时段
|
|
|
+ section: [],
|
|
|
+ sectionId: null,
|
|
|
+ timeFlag: false,
|
|
|
+ from: {
|
|
|
+ activityId: "", //活动id
|
|
|
+ name: "说说", //姓名
|
|
|
+ age: "", //年龄
|
|
|
+ identity: "421083199504071211", //身份证号
|
|
|
+ joinTime: "", //参加时间,yyyy-MM-dd
|
|
|
+ num: 1, //参加人数, 最多3人
|
|
|
+ phone: "18702020202", //手机号
|
|
|
+ timeBucket: "", //活动时间段
|
|
|
+ timeBucketId: "", //活动时间段id
|
|
|
+ },
|
|
|
+ fromFlag: {
|
|
|
+ name: false,
|
|
|
+ identity: false,
|
|
|
+ phone: false,
|
|
|
+ age: false,
|
|
|
+ },
|
|
|
+ };
|
|
|
+ },
|
|
|
+ //监听属性 类似于data概念
|
|
|
+ computed: {},
|
|
|
+ //监控data中的数据变化
|
|
|
+ watch: {},
|
|
|
+ //方法集合
|
|
|
+ methods: {
|
|
|
+ async save() {
|
|
|
+ if (this.weekId === null) {
|
|
|
+ Dialog.alert({
|
|
|
+ message: "请选择活动时间!",
|
|
|
+ }).then(() => {
|
|
|
+ // on close
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (this.sectionId === null) {
|
|
|
+ Dialog.alert({
|
|
|
+ message: "请选择活动时段!",
|
|
|
+ }).then(() => {
|
|
|
+ // on close
|
|
|
+ });
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.from.name.trim() === "") {
|
|
|
+ this.fromFlag.name = true;
|
|
|
+ return;
|
|
|
+ } else this.fromFlag.name = false;
|
|
|
+ this.blurInput();
|
|
|
+ this.blurPhone();
|
|
|
+ let ageArr = this.data.age.split(",");
|
|
|
+ if (
|
|
|
+ this.from.age < Number(ageArr[0]) ||
|
|
|
+ this.from.age > Number(ageArr[1])
|
|
|
+ ) {
|
|
|
+ this.fromFlag.age = true;
|
|
|
+ return;
|
|
|
+ } else this.fromFlag.age = false;
|
|
|
+ if (this.fromFlag.identity || this.fromFlag.phone) return;
|
|
|
+
|
|
|
+ // 发送请求
|
|
|
+ let res = await activityApply(this.from);
|
|
|
+ if (res.code === 0) {
|
|
|
+ this.$router.push({
|
|
|
+ path: "/succOrder",
|
|
|
+ query: {
|
|
|
+ name: this.data.name,
|
|
|
+ time: this.from.joinTime,
|
|
|
+ time2: this.from.timeBucket,
|
|
|
+ num: this.from.num,
|
|
|
+ nowTime: res.timestamp,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ Dialog.alert({
|
|
|
+ message: res.msg,
|
|
|
+ }).then(() => {
|
|
|
+ // on close
|
|
|
+ });
|
|
|
+ }
|
|
|
+ console.log(res);
|
|
|
+ },
|
|
|
+ // 检查身份证格式
|
|
|
+ blurInput() {
|
|
|
+ let idcardReg =
|
|
|
+ /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/;
|
|
|
+ let temp = idcardReg.test(this.from.identity);
|
|
|
+ this.fromFlag.identity = !temp;
|
|
|
+ // 根据身份证,自动算年龄
|
|
|
+ let userCard = this.from.identity;
|
|
|
+ if (temp) {
|
|
|
+ let yearBirth, monthBirth, dayBirth;
|
|
|
+ if (userCard.length == 15) {
|
|
|
+ let org_birthday = userCard.substring(6, 12);
|
|
|
+ //获取出生年月日
|
|
|
+ yearBirth = "19" + org_birthday.substring(0, 2);
|
|
|
+ monthBirth = org_birthday.substring(2, 4);
|
|
|
+ dayBirth = org_birthday.substring(4, 6);
|
|
|
+ } else if (userCard.length == 18) {
|
|
|
+ //获取出生年月日
|
|
|
+ yearBirth = userCard.substring(6, 10);
|
|
|
+ monthBirth = userCard.substring(10, 12);
|
|
|
+ dayBirth = userCard.substring(12, 14);
|
|
|
+ }
|
|
|
+ //获取当前年月日并计算年龄
|
|
|
+ let myDate = new Date();
|
|
|
+ let monthNow = myDate.getMonth() + 1;
|
|
|
+ let dayNow = myDate.getDate();
|
|
|
+ let age = myDate.getFullYear() - yearBirth;
|
|
|
+ if (
|
|
|
+ monthNow < monthBirth ||
|
|
|
+ (monthNow == monthBirth && dayNow < dayBirth)
|
|
|
+ ) {
|
|
|
+ age--;
|
|
|
+ }
|
|
|
+ //返回年龄
|
|
|
+ this.from.age = age;
|
|
|
+ }
|
|
|
+ let ageArr = this.data.age.split(",");
|
|
|
+ if (
|
|
|
+ this.from.age < Number(ageArr[0]) ||
|
|
|
+ this.from.age > Number(ageArr[1])
|
|
|
+ ) {
|
|
|
+ this.fromFlag.age = true;
|
|
|
+ } else this.fromFlag.age = false;
|
|
|
+ },
|
|
|
+ // 手机号验证
|
|
|
+ blurPhone() {
|
|
|
+ let idcardReg = /^1[3-9]\d{9}$/;
|
|
|
+ this.fromFlag.phone = !idcardReg.test(this.from.phone);
|
|
|
+ },
|
|
|
+ selectWeek(index, flag, date) {
|
|
|
+ this.weekId = index;
|
|
|
+ this.sectionId = null;
|
|
|
+ this.from.joinTime = date;
|
|
|
+ this.timeBucketDetail(this.from.activityId, date);
|
|
|
+ if (flag) this.timeFlag = false;
|
|
|
+ else this.timeFlag = true;
|
|
|
+ },
|
|
|
+ selectSection(index, startTime, endTime, id) {
|
|
|
+ this.sectionId = index;
|
|
|
+ this.from.timeBucket = `${startTime}-${endTime}`;
|
|
|
+ this.from.timeBucketId = id;
|
|
|
+ },
|
|
|
+ // 封装一个获取时间段详情的方法
|
|
|
+ async timeBucketDetail(id, date) {
|
|
|
+ let res = await timeBucketDetail(id, date);
|
|
|
+ // --------------活动时段处理
|
|
|
+ let tempHH = new Date().getHours();
|
|
|
+ let temp = [];
|
|
|
+ res.data.forEach((v) => {
|
|
|
+ let hh = v.endTime.substring(0, 2);
|
|
|
+ let dis = true;
|
|
|
+ if (Number(hh) - Number(tempHH) > 3) {
|
|
|
+ dis = false;
|
|
|
+ }
|
|
|
+ temp.push({ ...v, dis });
|
|
|
+ });
|
|
|
+ this.section = temp;
|
|
|
+ },
|
|
|
+ },
|
|
|
+ //生命周期 - 创建完成(可以访问当前this实例)
|
|
|
+ async created() {
|
|
|
+ // 获取服务器前缀地址
|
|
|
+ this.baseURL = axios.defaults.baseURL;
|
|
|
+
|
|
|
+ let id = this.$route.params.id;
|
|
|
+ if (id) {
|
|
|
+ id = Number(id);
|
|
|
+ this.from.activityId = id;
|
|
|
+ let res = await webDetailApi(id);
|
|
|
+ this.data = res.data;
|
|
|
+ // ---------------活动时间处理
|
|
|
+ // 开始日期的时间戳
|
|
|
+ let Statime = new Date(res.data.startDay).getTime();
|
|
|
+ let day =
|
|
|
+ (new Date(res.data.endDay) - new Date(res.data.startDay)) /
|
|
|
+ 1000 /
|
|
|
+ 60 /
|
|
|
+ 60 /
|
|
|
+ 24;
|
|
|
+ let timeChange = {
|
|
|
+ 1: "周一",
|
|
|
+ 2: "周二",
|
|
|
+ 3: "周三",
|
|
|
+ 4: "周四",
|
|
|
+ 5: "周五",
|
|
|
+ 6: "周六",
|
|
|
+ 0: "周日",
|
|
|
+ };
|
|
|
+ let tempArr = [];
|
|
|
+ let temp = Date.now();
|
|
|
+ for (let i = 0; i <= day; i++) {
|
|
|
+ // 之后的每一天的时间戳
|
|
|
+ let tt = Statime + 86400000 * i;
|
|
|
+ // 时间戳转换成年月日
|
|
|
+ let toDou = (n) => (n < 10 ? `0${n}` : `${n}`);
|
|
|
+ let ttS = new Date(tt);
|
|
|
+ let date = `${ttS.getFullYear()}-${toDou(ttS.getMonth() + 1)}-${toDou(
|
|
|
+ ttS.getDate()
|
|
|
+ )}`;
|
|
|
+ // 之后的每一天是几号
|
|
|
+ let a = new Date(tt);
|
|
|
+ let b = a.getDate();
|
|
|
+ // 之后的每一天的星期几
|
|
|
+ let c = a.getDay();
|
|
|
+ let d = timeChange[c];
|
|
|
+ // 判断在今天之前
|
|
|
+ let tempFlag = temp < tt;
|
|
|
+ if (temp - tt < 86400000) {
|
|
|
+ tempArr.push({
|
|
|
+ name: d,
|
|
|
+ num: b,
|
|
|
+ tempFlag,
|
|
|
+ date,
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.week = tempArr;
|
|
|
+
|
|
|
+ this.timeBucketDetail(id, res.data.startDay);
|
|
|
+
|
|
|
+ console.log(123, res);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //生命周期 - 挂载完成(可以访问DOM元素)
|
|
|
+ mounted() {},
|
|
|
+ beforeCreate() {}, //生命周期 - 创建之前
|
|
|
+ beforeMount() {}, //生命周期 - 挂载之前
|
|
|
+ beforeUpdate() {}, //生命周期 - 更新之前
|
|
|
+ updated() {}, //生命周期 - 更新之后
|
|
|
+ beforeDestroy() {}, //生命周期 - 销毁之前
|
|
|
+ destroyed() {}, //生命周期 - 销毁完成
|
|
|
+ activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
|
|
|
+};
|
|
|
+</script>
|
|
|
+<style lang='less' scoped>
|
|
|
+.Info {
|
|
|
+ padding-bottom: 100px;
|
|
|
+ .topImg {
|
|
|
+ margin-bottom: 30px;
|
|
|
+ & > img {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .name {
|
|
|
+ color: #6f774f;
|
|
|
+ font-weight: 700;
|
|
|
+ font-size: 24px;
|
|
|
+ text-align: center;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ }
|
|
|
+ .time {
|
|
|
+ padding: 0 24px;
|
|
|
+ color: #6f774f;
|
|
|
+ & > p {
|
|
|
+ font-size: 22px;
|
|
|
+ font-weight: 700;
|
|
|
+ & > span {
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .week {
|
|
|
+ margin-top: 30px;
|
|
|
+ width: 100%;
|
|
|
+ height: 80px;
|
|
|
+ overflow-x: auto;
|
|
|
+ overflow-y: hidden;
|
|
|
+ .weekBox {
|
|
|
+ height: 70px;
|
|
|
+ display: flex;
|
|
|
+ & > div {
|
|
|
+ margin-right: 20px;
|
|
|
+ width: 80px;
|
|
|
+ height: 70px;
|
|
|
+ border: 1px solid #6f774f;
|
|
|
+ border-radius: 3px;
|
|
|
+ & > div {
|
|
|
+ color: #858b6b;
|
|
|
+ text-align: center;
|
|
|
+ height: 40px;
|
|
|
+ line-height: 40px;
|
|
|
+ font-size: 22px;
|
|
|
+ }
|
|
|
+ .one {
|
|
|
+ font-size: 20px;
|
|
|
+ height: 30px;
|
|
|
+ line-height: 29px;
|
|
|
+ border-bottom: 1px solid #858b6b;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .active {
|
|
|
+ background-color: #6f774f;
|
|
|
+ pointer-events: none;
|
|
|
+ & > div {
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+ .one {
|
|
|
+ border-bottom: 1px solid #fff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .week::-webkit-scrollbar {
|
|
|
+ width: 0;
|
|
|
+ height: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .xian {
|
|
|
+ width: 100%;
|
|
|
+ height: 4px;
|
|
|
+ background-color: #f8f8f8;
|
|
|
+ margin: 30px 0;
|
|
|
+ }
|
|
|
+ .section {
|
|
|
+ padding: 0 24px;
|
|
|
+ color: #6f774f;
|
|
|
+ & > p {
|
|
|
+ font-size: 22px;
|
|
|
+ font-weight: 700;
|
|
|
+ }
|
|
|
+ .week {
|
|
|
+ .weekBox {
|
|
|
+ & > div {
|
|
|
+ width: 150px;
|
|
|
+ height: 70px;
|
|
|
+ border: 1px solid #6f774f;
|
|
|
+ border-radius: 3px;
|
|
|
+ & > div {
|
|
|
+ color: #858b6b;
|
|
|
+ text-align: center;
|
|
|
+ height: 35px;
|
|
|
+ line-height: 25px;
|
|
|
+ font-size: 20px;
|
|
|
+ }
|
|
|
+ .one {
|
|
|
+ font-size: 20px;
|
|
|
+ height: 35px;
|
|
|
+ line-height: 40px;
|
|
|
+ border-bottom: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .active {
|
|
|
+ background-color: #6f774f;
|
|
|
+ & > div {
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+ .one {
|
|
|
+ border-bottom: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .dis {
|
|
|
+ border: none;
|
|
|
+ background-color: #f8f8f8;
|
|
|
+ pointer-events: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .from {
|
|
|
+ margin-top: 35px;
|
|
|
+ .row {
|
|
|
+ position: relative;
|
|
|
+ margin-bottom: 24px;
|
|
|
+ display: flex;
|
|
|
+ height: 40px;
|
|
|
+ .numChange {
|
|
|
+ z-index: 99;
|
|
|
+ font-size: 20px;
|
|
|
+ color: #858b6b;
|
|
|
+ position: absolute;
|
|
|
+ right: 10px;
|
|
|
+ top: 0;
|
|
|
+ height: 100%;
|
|
|
+ width: 80px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ /deep/.van-icon {
|
|
|
+ opacity: 0;
|
|
|
+ pointer-events: none;
|
|
|
+ }
|
|
|
+ .none {
|
|
|
+ opacity: 1;
|
|
|
+ pointer-events: initial;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .name {
|
|
|
+ height: 40px;
|
|
|
+ line-height: 40px;
|
|
|
+ font-size: 20px;
|
|
|
+ width: 100px;
|
|
|
+ min-width: 100px;
|
|
|
+ text-align: right;
|
|
|
+ }
|
|
|
+ input {
|
|
|
+ height: 40px;
|
|
|
+ padding: 0 5px;
|
|
|
+ border: 1px solid #c7c7c7;
|
|
|
+ border-radius: 5px;
|
|
|
+ flex: 1;
|
|
|
+ }
|
|
|
+ input:disabled {
|
|
|
+ background-color: #c9c9c9;
|
|
|
+ }
|
|
|
+ .tit {
|
|
|
+ color: #be9c6c;
|
|
|
+ font-size: 12px;
|
|
|
+ position: absolute;
|
|
|
+ bottom: -18px;
|
|
|
+ left: 100px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .btn {
|
|
|
+ background-color: #858b6b;
|
|
|
+ color: #fff;
|
|
|
+ width: 100%;
|
|
|
+ height: 40px;
|
|
|
+ border-radius: 20px;
|
|
|
+ line-height: 40px;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 700;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|