소스 검색

合并分支

钱新宇 1 개월 전
부모
커밋
be842a878c
9개의 변경된 파일472개의 추가작업 그리고 34개의 파일을 삭제
  1. 6 0
      pages.json
  2. 10 9
      pages/car/order.vue
  3. 218 0
      pages/orders/confirm.vue
  4. 1 1
      pages/orders/index.vue
  5. 17 13
      pages/product/index.vue
  6. 9 1
      pages/score/clockin.vue
  7. 0 6
      pages/score/index.vue
  8. 22 2
      pages/video/detail.vue
  9. 189 2
      pages/video/record.vue

+ 6 - 0
pages.json

@@ -273,6 +273,12 @@
       "style": {
         "navigationBarTitleText": "余额红包"
       }
+    },
+    {
+      "path": "pages/orders/confirm",
+      "style": {
+        "navigationBarTitleText": "确认支付"
+      }
     }
   ],
   "globalStyle": {

+ 10 - 9
pages/car/order.vue

@@ -86,7 +86,7 @@
         合计:
         <text class="price_total">¥{{ priceTotal }}</text>
       </view>
-      <button class="to_order" @click="createOrder()" data-eventsync="true">提交预约</button>
+      <button class="to_order" @click="createOrder()" data-eventsync="true">立即支付</button>
     </view>
     <uni-popup ref="popup" type="bottom" class="popup" background-color="#FFFFFF" @touchmove.stop.prevent="() => {}">
       <view class="coupon_list">
@@ -363,7 +363,7 @@ export default {
       }
       if (productList.length <= 0) {
         uni.showToast({
-          title: "未选择可预约的产品",
+          title: "未选择可购买的产品",
           icon: "none",
         });
         return;
@@ -410,15 +410,16 @@ export default {
         .then((re) => {
           // 判断结果
           if (re.code == "success") {
-            // 跳转到报单完成页面
-            uni.redirectTo({
-              url: `/pages/orders/completion?params=${encodedArray}`,
-            });
+            // 跳转到支付确认页面
+            let orderInfo = re.data;
+            orderInfo = JSON.stringify(orderInfo);
+            let params = encodeURIComponent(orderInfo);
+            uni.navigateTo({ url: `/pages/orders/confirm?params=${params}` });
             return;
           } else {
-			  uni.showModal({
-				title: re.msg,
-				showCancel: false,
+            uni.showModal({
+            title: re.msg,
+            showCancel: false,
 			  });
             
           }

+ 218 - 0
pages/orders/confirm.vue

@@ -0,0 +1,218 @@
+<template>
+  <view class="whole">
+    <view class="pay">
+      <view class="header">
+        <div>
+          <view class="pay">支付金额</view>
+          <view class="payNum">
+            <span style="font-size: 34rpx;">¥</span>{{price}}
+          </view>
+        </div>
+      </view>
+      <view class="listPay">
+        <uni-icons type="weixin" size="60rpx" color="#00aa00"></uni-icons>
+        <view class="text">
+          <view class="wx">微信支付</view>
+          <view class="subWx">推荐使用微信支付</view>
+        </view>
+        <view class="btn">
+          <label class="radio">
+            <radio value="1" :checked="boolWx"
+                   color="#FFCC33" style="transform:scale(0.7)"
+                   @click="changePayType(1)" />
+          </label>
+        </view>
+      </view>
+<!--      <view class="listPay">
+        <uni-icons type="weibo" size="60rpx" color="#ff5500"></uni-icons>
+        <view class="text">
+          <view class="wx">线下支付(到付)</view>
+        </view>
+        <view class="btn">
+          <label class="radio">
+            <radio value="2" :checked="boolWb"
+                   color="#FFCC33" style="transform:scale(0.7)"
+                   @click="changePayType(3)" />
+          </label>
+        </view>
+      </view>-->
+      <view class="bootom">
+        <button type="warn" style="color: #fff;" @click="confirm">确认支付</button>
+      </view>
+    </view>
+
+  </view>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      boolWx: true,
+      boolWb: false,
+      payType: 1, //支付类型
+      price: 0, //支付金额
+      orderNo: "", //订单号
+      parentOrderNo: "", //父订单号
+      submiting: false//控制再次确认支付的弹出框
+    }
+  },
+  onLoad(options) {
+    //接受参数
+    let orderInfo =  options.params;
+    if( orderInfo ){
+      //解密参数
+      orderInfo = decodeURIComponent(orderInfo);
+      //转成js数组对象
+      orderInfo	=  JSON.parse(orderInfo);
+    }
+    this.price = orderInfo.pay_total
+    if (orderInfo.order_id) {
+      this.orderNo = orderInfo.order_id
+    } else {
+      this.parentOrderNo = orderInfo.snowflake_id
+    }
+  },
+  methods: {
+    // 选择支付方式
+    changePayType(type) {
+      if(1==type){
+        this.boolWx=true;
+        this.boolWb=false;
+      }else{
+        this.boolWx=false;
+        this.boolWb=true;
+      }
+      this.payType = type
+      console.log(this.payType,"this.payType");
+    },
+    // 确认支付
+    confirm() {
+      const that = this;
+      //微信支付
+      if(1===that.payType){
+        that.submiting = true;
+        this.pay();
+      }
+    },
+    //调起微信支付
+    pay(){
+      uni.login({
+        provider: 'weixin',
+        success: (loginRes) => {
+          // 登录成功,获取用户code
+          const { code } = loginRes;
+          // 微信支付下单
+          this.$http.request('api/wechat_pay/pay',{code:code,order_id:this.orderNo},'post').then((e)=>{
+            const price = this.price
+            // 成功的话
+            if( e.code == 'success'){
+              //获取openid
+              // 授权成功以后,调用登录
+              //调用微信官方支付接口弹出付款界面,输入密码扣款
+              wx.requestPayment({
+                timeStamp: e.data.timeStamp,  //时间戳
+                nonceStr:  e.data.nonceStr,   //随机字符串
+                package:   e.data.package,    //prepay_id
+                signType:  e.data.signType,   //签名算法MD5
+                paySign:   e.data.paySign,    //签名
+                success:function (res) {
+                  if (res.errMsg == "requestPayment:ok"){
+                    console.log('支付成功3', price)
+                    uni.navigateTo({url:`/pages/orders/completion?price=${price}`});
+                  }else{
+                    console.log('支付失败')
+                    uni.showToast({
+                      title: '支付失败',
+                      icon: 'none'
+                    });
+                  }
+                },
+                fail:function (res) {
+                  console.log('支付失败', res)
+                  uni.showToast({
+                    title: '支付失败',
+                    icon: 'none'
+                  });
+                }
+              })
+
+            }else{
+              console.log('支付失败2', e)
+              uni.showToast({
+                title: '支付失败',
+                icon: 'none'
+              });
+            }
+          });
+        },
+        fail: (err) => {
+          console.log('uni.login 接口调用失败,无法获取openid', err);
+          uni.showToast({
+            title: '支付失败',
+            icon: 'none'
+          });
+        }
+      });
+    },
+  }
+}
+</script>
+
+<style lang="scss">
+.whole {
+  display: flex;
+  justify-content: center;
+
+  .header {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    text-align: center;
+    flex-wrap: wrap;
+    height: 300rpx;
+
+    .pay {
+      width: 100%;
+      color: #717171;
+    }
+
+    .payNum {
+      width: 100%;
+      font-size: 44rpx;
+      margin: 10rpx 0px 20rpx;
+    }
+  }
+
+  .pay {
+    width: 100%;
+
+    .listPay {
+      height: 130rpx;
+      display: flex;
+      align-items: center;
+
+      .uni-icons {
+        margin-left: 20rpx;
+      }
+
+      .text {
+        width: 40%;
+        margin: 0px 20rpx 0px;
+      }
+
+      .btn {
+        width: 40%;
+        text-align: right;
+      }
+    }
+
+    .bootom {
+      width: 90%;
+      margin: auto;
+      margin-top: 20rpx;
+    }
+  }
+
+}
+</style>

+ 1 - 1
pages/orders/index.vue

@@ -2,7 +2,7 @@
   <view>
     <view class="order_status_list">
       <view class="order_status_item" :class="requestParam.status == 0 ? 'active' : ''" @click="setStatus(0)"> 全部 </view>
-      <view class="order_status_item" :class="requestParam.status == 1 ? 'active' : ''" @click="setStatus(1)"> 待跟进 </view>
+      <view class="order_status_item" :class="requestParam.status == 1 ? 'active' : ''" @click="setStatus(1)"> 待付款 </view>
       <view class="order_status_item" :class="requestParam.status == 4 ? 'active' : ''" @click="setStatus(4)"> 已取消 </view>
       <view class="order_status_item" :class="requestParam.status == 8 ? 'active' : ''" @click="setStatus(8)"> 已完成 </view>
     </view>

+ 17 - 13
pages/product/index.vue

@@ -78,7 +78,7 @@
         <image src="https://kailin-mp.oss-cn-shenzhen.aliyuncs.com/static/icon/car.png" class="car_icon"></image>
       </navigator>
       <button class="show_order" data-eventsync="true" @click="showSpecPopup(3)">{{ this.productInfo.regiment_title }}专享/{{ this.productInfo.regiment_price }}</button>
-      <button class="show_car" data-eventsync="true" @click="showSpecPopup(1)">单独预约/{{ this.productInfo.price }}</button>
+      <button class="show_car" data-eventsync="true" @click="showSpecPopup(1)">单独购买/{{ this.productInfo.price }}</button>
     </view>
     <view class="order_car" v-else-if="productInfo.regiment_type === 1">
       <navigator url="/pages/car/index" open-type="switchTab" class="to_car">
@@ -101,7 +101,7 @@
       <navigator url="/pages/car/index" open-type="switchTab" class="to_car">
         <image src="https://kailin-mp.oss-cn-shenzhen.aliyuncs.com/static/icon/car.png" class="car_icon"></image>
       </navigator>
-      <button class="show_order" v-if="!productInfo.hide_orderbtn" data-eventsync="true" @click="showSpecPopup(1)">立即预约</button>
+      <button class="show_order" v-if="!productInfo.hide_orderbtn" data-eventsync="true" @click="showSpecPopup(1)">立即购买</button>
       <button :class="productInfo.hide_orderbtn?'show_car hide_orderbtn ':'show_car'"  data-eventsync="true" @click="showSpecPopup(2)">加入购物车</button>
     </view>
     <view class="to_bottom"> --- 到底了 --- </view>
@@ -170,10 +170,10 @@
         </view>
         <view class="order_price" v-if="specBtnType == 1 || specBtnType == 3">合计: ¥{{ priceTotal }}</view>
         <view class="order_btn">
-          <button class="to_order" @click="createOrder()" v-if="specBtnType == 1" data-eventsync="true">预约</button>
+          <button class="to_order" @click="createOrder()" v-if="specBtnType == 1" data-eventsync="true">购买</button>
           <button class="to_car" @click="createCart()" v-if="specBtnType == 2" data-eventsync="true">加入购物车</button>
-          <button class="to_order" @click="createOrder()" v-if="specBtnType == 3" data-eventsync="true">拼团预约</button>
-          <button class="to_order" @click="createOrder()" v-if="specBtnType == 4" data-eventsync="true">{{ productInfo.regiment_title }}预约</button>
+          <button class="to_order" @click="createOrder()" v-if="specBtnType == 3" data-eventsync="true">拼团购买</button>
+          <button class="to_order" @click="createOrder()" v-if="specBtnType == 4" data-eventsync="true">{{ productInfo.regiment_title }}购买</button>
         </view>
       </view>
     </uni-popup>
@@ -687,10 +687,12 @@ export default {
               this.productInfo.stock = this.productInfo.stock - this.quantity;
               // 关闭弹窗
               this.$refs.specPopup.close();
-              // 跳转到报单完成页面
-              uni.navigateTo({
-                url: `/pages/orders/completion?params=${encodedArray}`,
-              });
+              //订单详情
+              let orderInfo = re.data;
+              orderInfo = JSON.stringify(orderInfo)
+              let params = encodeURIComponent(orderInfo);
+              // 跳转到确认支付页面
+              uni.navigateTo({url:`/pages/orders/confirm?params=${params}`});
             } else {
               uni.showModal({
                 title: re.msg,
@@ -717,10 +719,12 @@ export default {
               this.productInfo.stock = this.productInfo.stock - this.quantity;
               // 关闭弹窗
               this.$refs.specPopup.close();
-              // 跳转到报单完成页面
-              uni.navigateTo({
-                url: `/pages/orders/completion?params=${encodedArray}`,
-              });
+              //订单详情
+              let orderInfo = re.data;
+              orderInfo = JSON.stringify(orderInfo)
+              let params = encodeURIComponent(orderInfo);
+              // 跳转到确认支付页面
+              uni.navigateTo({url:`/pages/orders/confirm?params=${params}`});
             } else {
               uni.showModal({
                 title: re.msg,

+ 9 - 1
pages/score/clockin.vue

@@ -13,7 +13,7 @@
             <view class="wait_score">{{ scoreInfo.wait_score ? scoreInfo.wait_score : 0 }}</view>
           </view>
         </view>
-        <view class="right_box">
+        <view class="right_box" v-if="show_lottery">
           <navigator url="/pages/score/lottery" class="lottery_enter">
             <image class="lottery_img" src="https://mall.findit.ltd/uploads/images/default/lottery_record.png" mode=""></image>
             <view class="lottery_text">点我抽奖</view>
@@ -83,6 +83,7 @@ export default {
       listLength: 0,
       active_id: 0,
       active_rule: "",
+	  show_lottery:0,
     };
   },
   onLoad() {
@@ -139,6 +140,13 @@ export default {
         this.scoreInfo = re.data;
       }
     });
+	// 请求
+	this.$http.request('api/lottery_score/get_detail').then((re) => {
+	  // 成功结果
+	  if (re.code == 'success') {
+	    this.show_lottery = 1;
+	  }
+	});
   },
   methods: {
     showRule() {

+ 0 - 6
pages/score/index.vue

@@ -74,8 +74,6 @@ export default {
     return shareObj;
   },
   onShow() {
-	// 如果登录才请求
-	if( !this.$checkAccess.checkLogin() ) return ;
     // 没有数据的话,或者请求中,不允许刷新
     if (this.isReqing) return;
     // 请求参数
@@ -98,8 +96,6 @@ export default {
     });
   },
   onPullDownRefresh() {
-	// 如果登录才请求
-	if( !this.$checkAccess.checkLogin() ) return ;
     // 如果请求中,不允许请求,
     if (this.isReqing) return uni.stopPullDownRefresh();
     // 初始化页码为1
@@ -121,8 +117,6 @@ export default {
     uni.stopPullDownRefresh();
   },
   onReachBottom() {
-	// 如果登录才请求
-	if( !this.$checkAccess.checkLogin() ) return ;
     // 如果页码是0,避免第一页重复
     if (this.requestParam.page < 1) return;
     // 最后一页不再请求

+ 22 - 2
pages/video/detail.vue

@@ -15,7 +15,7 @@
         @ended="_videoEnd"
         @fullscreenchange="screenChange"
       ></video>
-      <cover-view v-if="videoInfo.learn_status == 0" :class="bigsScreen ? 'bigScreen' : 'cover'"></cover-view>
+      <cover-view v-if="videoInfo.learn_status == 0" :class="bigsScreen ? 'bigScreen' : 'cover'" @touchmove="bigScreenTouch"></cover-view>
     </view>
     <view class="video_title">{{ videoInfo.name }}</view>
     <view class="rich_text">
@@ -92,6 +92,7 @@ export default {
       countdown: 0, // 新增变量用于存储倒计时时间
       bigsScreen: false,
       isVip: true,
+	  bigsScreenTouch:false,
     };
   },
   onLoad(param) {
@@ -174,9 +175,28 @@ export default {
   onReady: function (res) {},
   onShow() {},
   methods: {
+	bigScreenTouch(e){
+		if( this.bigsScreenTouch ) return;
+		this.bigsScreenTouch = true;
+		// 如果学习状态为0,表示未完成过学习
+		if( this.videoInfo.learn_status == 0 ){
+		  // 判断结果
+		  var is_alter 	= uni.getStorageSync("video_learn_status_alter_"+this.videoInfo.id);
+		  // 弹出结果
+		  if( !is_alter ){
+			uni.showModal({
+				content:"您未完成第一次学习,暂无法快进",
+				showCancel:false,
+				success: (res) => {
+					// 已经弹出过
+					uni.setStorageSync("video_learn_status_alter_"+this.videoInfo.id,1);
+				}
+			})
+		  }
+		}
+	},
     openCustomer() {
       // #ifdef MP-WEIXIN
-      console.log(1);
       wx.openCustomerServiceChat({
         extInfo: { url: this.videoInfo.service?.url },
         corpId: this.videoInfo.service?.corpid,

+ 189 - 2
pages/video/record.vue

@@ -32,9 +32,25 @@
       </view>
     </view>
     <view class="bottom_btn">
-      <view class="submit_btn defult" @click="_backList">返回课程列表</view>
-      <view class="submit_btn" @click="_continue">{{ type == "exam" ? "重新练习" : "继续课后评测" }}</view>
+      <view class="submit_btn defult" v-if="reportInfo?.is_self"  @click="showShareImage">生成分享图</view>
+	  <view class="submit_btn start_learn" v-if="!reportInfo?.is_self" @click="toLearn">开启我的学习计划</view>
+      <view class="submit_btn" v-if="reportInfo?.is_self" @click="_continue">{{ type == "exam" ? "重新练习" : "继续课后评测" }}</view>
     </view>
+	<uni-popup ref="filePathPopup" type="center" class="center_popup" >
+		<view class="cover_black" :style="windowWidth">
+			<image v-if="filePath" :src="filePath" mode="heightFix" class="file_path_image"></image>
+			<view class="bottom_box">
+				<view class="info_title">
+					<view class="title_center">分享至</view>
+					<button class="close_popup" @click.stop="closePupop"> X </button>
+				</view>
+				<button class="save_image_btn" @click.stop="saveImage">
+					<image class="save_icon" src="https://kailin-mp.oss-cn-shenzhen.aliyuncs.com/static/video/savepic.png" mode=""></image>
+					<view class="save_text">保存图片</view>
+				</button>
+			</view>
+		</view>
+	</uni-popup>
   </view>
 </template>
 
@@ -47,10 +63,13 @@ export default {
         isanswer_total: 0,
         answer_total: 0,
         get_score: 0,
+		is_self:1,
       },
+	  filePath:"",
       queston_list: [],
       record_id: null,
       type: null, // 确保 type 在 data 中定义
+	  windowWidth:{},
     };
   },
   onLoad(params) {
@@ -66,14 +85,84 @@ export default {
   onShow() {
     this._getRecord(this.type);
     this._getAnswerList(this.type);
+	this.windowWidth = {height:uni.getWindowInfo().windowHeight+'px'};
   },
   onShareAppMessage(obj) {
     return {
       title: `999智控终端平台\n学习报告`,
       path: `/pages/video/record?type=${this.type}&record_id=${this.record_id}`,
+	  promise: new Promise((resolve, reject) => {
+	    this.$http.request(`api/${this.type}_report_share_image/get`, {course_id: this.reportInfo.course_id,record_id:this.record_id}).then((callback) => {
+	      let obj = {
+	        title: callback.data?.title,
+	        path: `/pages/video/record?type=${this.type}&record_id=${this.record_id}`,
+	      };
+		  if (callback.data?.image_url !== "") {
+		    obj.imageUrl = callback.data.image_url;
+		  }
+		  resolve(obj);
+	    });
+	  }),
     };
   },
   methods: {
+	toLearn(){
+		if( !this.reportInfo?.course_id ) {
+			uni.showToast({
+				icon:"none",
+				title:"无对应课程ID",
+			})
+			return ;
+		}
+		uni.redirectTo({
+		  url: `/pages/video/detail?id=${this.reportInfo.course_id}`,
+		});
+	},
+	showShareImage(){
+		this.$http.request(`api/${this.type}_report_share_image/get_after`, {course_id: this.reportInfo.course_id,record_id:this.record_id,scene:`type=${this.type}&record_id=${this.record_id}`}).then((callback) => {
+		  if( callback.code == 'success'){
+				// 分离base64中的数据部分
+			  const imgSrc = callback.data?.base64_image; // 假设这是你的base64字符串,例如:"data:image/png;base64,iVBORw0K..."
+			  const imgFormat = imgSrc.split(',')[1]; // 获取base64编码的图片数据部分
+			  const fileExt = imgSrc.split(';')[0].split('/')[1]; // 获取图片格式,例如:jpeg, png等
+			  const filePath = `${uni.env.USER_DATA_PATH}/${Date.now()}.${fileExt}`; // 临时文件路径,使用用户数据路径确保有权限写入
+			  // 使用uni.getFileSystemManager()将base64转换为文件并保存到相册
+			  const fs = uni.getFileSystemManager();
+			  fs.writeFile({
+				filePath: filePath,
+				data: imgFormat, // 直接写入base64编码的数据部分,不需要转换ArrayBuffer
+				encoding: 'base64', // 指定编码为base64
+				success: () => {
+				  this.filePath = filePath
+				  // 显示
+				  this.$refs.filePathPopup.open("center");
+				},
+				fail: function (err) {
+				  console.log('文件写入失败', err);
+				  uni.showToast({ title: '文件写入失败', icon: 'none' });
+				}
+			  });
+		  }
+		});
+	},
+	saveImage(){
+		if( this.filePath ){
+			uni.saveImageToPhotosAlbum({
+			  filePath: this.filePath,
+			  success:()=>{
+				// 关闭结果
+				this.$refs.filePathPopup.close();
+			    uni.showToast({ title: '保存成功', icon: 'success' });
+			  },
+			  fail:(err)=> {
+			    uni.showToast({ title: '保存失败', icon: 'none' });
+			  }
+			});
+		}
+	},
+	closePupop(){
+		this.$refs.filePathPopup.close();
+	},
     _backList() {
       uni.redirectTo({
         url: `/pages/video/index`,
@@ -223,6 +312,104 @@ export default {
         color: #333;
       }
     }
+	.submit_btn.start_learn{
+		width: 90%;
+		margin: 0rpx auto;
+	}
   }
 }
+.center_popup{
+	.cover_black{
+		display: block;
+		width: 750rpx;
+		position: relative;
+		padding-top: 120rpx;
+		background-color: rgba(0, 0, 0, 0.9);
+		.file_path_image{
+			top: 50%;
+			left: 50%;
+			width: 622rpx;
+			height: 892rpx;
+			display: block;
+			position: absolute;
+			margin-top: -560rpx;
+			margin-left: -311rpx;
+		}
+		.bottom_box{
+			left: 0rpx;
+			bottom: 0rpx;
+			width: 750rpx;
+			height: 300rpx;
+			position: absolute;
+			background-color: #FFFFFF;
+			border-top-left-radius: 20rpx;
+			border-top-right-radius: 20rpx;
+			.info_title{
+				display: block;
+				border: none;
+				width: 750rpx;
+				height: 60rpx;
+				line-height: 60rpx;
+				font-size: 28rpx;
+				text-align: center;
+				position: relative;
+				.title_center{
+					display: block;
+					border: none;
+					width: 120rpx;
+					height: 60rpx;
+					line-height: 60rpx;
+					font-size: 28rpx;
+					margin: 0rpx auto;
+					text-align: center;
+				}
+				.close_popup{
+					top: 0rpx;
+					right: 0rpx;
+					border: none;
+					width: 60rpx;
+					height: 60rpx;
+					font-size: 32rpx;
+					padding: 0rpx 0rpx;
+					line-height: 60rpx;
+					position: absolute;
+					background-color: transparent;
+				}
+				.close_popup::after{
+					border: none;
+					background-color: transparent;
+				}
+			}
+			.save_image_btn{
+				display: block;
+				border: none;
+				width: 300rpx;
+				height: 120rpx;
+				margin: 0rpx auto;
+				overflow: hidden;
+				margin-top: 40rpx;
+				padding: 0rpx 0rpx;
+				text-align: center;
+				line-height: 80rpx;
+				vertical-align: middle;
+				background-color: transparent;
+				.save_icon{
+					float: left;
+					width: 80rpx;
+					height: 80rpx;
+				}
+				.save_text{
+					float: left;
+					width: 180rpx;
+					height: 80rpx;
+					font-size: 32rpx;
+				}
+			}
+			.save_image_btn::after{
+				border: none;
+				background-color: transparent;
+			}
+		}
+	}
+}
 </style>