Browse Source

Merge remote-tracking branch 'origin/master'

yfh 3 days ago
parent
commit
80791eeb22
30 changed files with 3690 additions and 361 deletions
  1. 38 0
      .env.prod-fby
  2. 1 0
      package.json
  3. 53 0
      src/api/course/fsCourseProduct.js
  4. 70 0
      src/api/course/fsCourseProductOrder.js
  5. 71 0
      src/api/course/userWatchCourseStatistics.js
  6. 53 0
      src/api/course/userWatchStatistics.js
  7. 46 0
      src/api/his/packageSolarTerm.js
  8. 53 0
      src/api/his/userOnlineState.js
  9. BIN
      src/assets/logo/fby_logo.png
  10. 1 1
      src/views/company/company/index.vue
  11. 4 4
      src/views/company/companyRecharge/index.vue
  12. 249 272
      src/views/components/course/userCourseCatalogDetails.vue
  13. 165 0
      src/views/course/fsCourseProduct/CourseProduct.vue
  14. 316 0
      src/views/course/fsCourseProduct/index.vue
  15. 523 0
      src/views/course/fsCourseProductOrder/index.vue
  16. 3 4
      src/views/course/userCoursePeriod/batchRedPacket.vue
  17. 27 11
      src/views/course/userCoursePeriod/index.vue
  18. 6 9
      src/views/course/userCoursePeriod/redPacket.vue
  19. 390 0
      src/views/course/userWatchCourseStatistics/index.vue
  20. 394 0
      src/views/course/userWatchCourseTotalStatistics/index.vue
  21. 286 0
      src/views/course/userWatchStatistics/index.vue
  22. 42 2
      src/views/his/package/index.vue
  23. 336 0
      src/views/his/packageSolarTerm/index.vue
  24. 2 2
      src/views/his/storeOrder/order1.vue
  25. 44 2
      src/views/his/storeProduct/index.vue
  26. 3 2
      src/views/his/user/index.vue
  27. 400 0
      src/views/his/userOnlineState/index.vue
  28. 63 38
      src/views/statistics/section/inline.vue
  29. 39 3
      src/views/system/config/config.vue
  30. 12 11
      src/views/user/darkRoom/index.vue

+ 38 - 0
.env.prod-fby

@@ -0,0 +1,38 @@
+# 页面标题
+VUE_APP_TITLE =互联网医院管理系统
+# 公司名称
+COMPANY_NAME =福本源
+# ICP备案号
+ICP_RECORD =蜀ICP备2023036719号
+# ICP网站访问地址
+ICP_URL =https://beian.miit.gov.cn
+# 网站LOG
+VUE_APP_LOG_URL =@/assets/logo/fby_logo.png
+# 存储桶配置
+VUE_APP_OBS_ACCESS_KEY_ID = K2UTJGIN7UTZJR2XMXYG
+# 存储桶配置
+VUE_APP_OBS_SECRET_ACCESS_KEY = sbyeNJLbcYmH6copxeFP9pAoksM4NIT9Zw4x0SRX
+# 存储桶配置
+VUE_APP_OBS_SERVER = https://obs.cn-north-4.myhuaweicloud.com
+# 存储桶配置
+VUE_APP_OBS_BUCKET = fby-hw079058881
+# 存储桶配置
+VUE_APP_COS_BUCKET = fby-1323137866
+# 存储桶配置
+VUE_APP_COS_REGION = ap-chongqing
+# 线路一地址
+VUE_APP_VIDEO_LINE_1 = https://fbytcpv.ylrzcloud.com
+# 线路二地址
+VUE_APP_VIDEO_LINE_2 = https://fbyobs.ylrztop.com
+# 生产环境配置
+ENV = 'production'
+
+# FS管理系统/开发环境
+VUE_APP_BASE_API = '/prod-api'
+
+#默认 1、会员 2、企微
+VUE_APP_COURSE_DEFAULT = 1
+
+# 路由懒加载
+VUE_CLI_BABEL_TRANSPILE_MODULES = true
+

+ 1 - 0
package.json

@@ -31,6 +31,7 @@
     "build:prod-cqxzt": "vue-cli-service build --mode prod-cqxzt",
     "build:prod-bjyjb": "vue-cli-service build --mode prod-bjyjb",
     "build:prod-bjczwh": "vue-cli-service build --mode prod-bjczwh",
+    "build:prod-fby": "vue-cli-service build --mode prod-fby",
     "preview": "node build/index.js --preview",
     "lint": "eslint --ext .js,.vue src"
   },

+ 53 - 0
src/api/course/fsCourseProduct.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询拍单商品列表
+export function listFsCourseProduct(query) {
+  return request({
+    url: '/course/fsCourseProduct/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询拍单商品详细
+export function getFsCourseProduct(id) {
+  return request({
+    url: '/course/fsCourseProduct/' + id,
+    method: 'get'
+  })
+}
+
+// 新增拍单商品
+export function addFsCourseProduct(data) {
+  return request({
+    url: '/course/fsCourseProduct',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改拍单商品
+export function updateFsCourseProduct(data) {
+  return request({
+    url: '/course/fsCourseProduct',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除拍单商品
+export function delFsCourseProduct(id) {
+  return request({
+    url: '/course/fsCourseProduct/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出拍单商品
+export function exportFsCourseProduct(query) {
+  return request({
+    url: '/course/fsCourseProduct/export',
+    method: 'get',
+    params: query
+  })
+}

+ 70 - 0
src/api/course/fsCourseProductOrder.js

@@ -0,0 +1,70 @@
+import request from '@/utils/request'
+
+// 查询拍单商品订单列表
+export function listFsCourseProductOrder(query) {
+  return request({
+    url: '/course/fsCourseProductOrder/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询拍单商品订单详细
+export function getFsCourseProductOrder(courseOrderId) {
+  return request({
+    url: '/course/fsCourseProductOrder/' + courseOrderId,
+    method: 'get'
+  })
+}
+
+// 新增拍单商品订单
+export function addFsCourseProductOrder(data) {
+  return request({
+    url: '/course/fsCourseProductOrder',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改拍单商品订单
+export function updateFsCourseProductOrder(data) {
+  return request({
+    url: '/course/fsCourseProductOrder',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除拍单商品订单
+export function delFsCourseProductOrder(courseOrderId) {
+  return request({
+    url: '/course/fsCourseProductOrder/' + courseOrderId,
+    method: 'delete'
+  })
+}
+
+// 导出拍单商品订单
+export function exportFsCourseProductOrder(query) {
+  return request({
+    url: '/course/fsCourseProductOrder/export',
+    method: 'get',
+    params: query
+  })
+}
+
+// 退款拍商品订单
+export function refund(data) {
+  return request({
+    url: '/course/fsCourseProductOrder/refund',
+    method: 'post',
+    data: data
+  })
+}
+
+// 查询收货人电话
+export function getOrderUserPhone(courseOrderId) {
+  return request({
+    url: '/course/fsCourseProductOrder/queryPhone/' + courseOrderId,
+    method: 'get'
+  })
+}

+ 71 - 0
src/api/course/userWatchCourseStatistics.js

@@ -0,0 +1,71 @@
+import request from '@/utils/request'
+
+// 查询会员看课统计-按课程统计列表
+export function listUserWatchCourseStatistics(query) {
+  return request({
+    url: '/course/userWatchCourseStatistics/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询会员看课统计-按课程统计详细
+export function getUserWatchCourseStatistics(id) {
+  return request({
+    url: '/course/userWatchCourseStatistics/' + id,
+    method: 'get'
+  })
+}
+
+// 新增会员看课统计-按课程统计
+export function addUserWatchCourseStatistics(data) {
+  return request({
+    url: '/course/userWatchCourseStatistics',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改会员看课统计-按课程统计
+export function updateUserWatchCourseStatistics(data) {
+  return request({
+    url: '/course/userWatchCourseStatistics',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除会员看课统计-按课程统计
+export function delUserWatchCourseStatistics(id) {
+  return request({
+    url: '/course/userWatchCourseStatistics/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出会员看课统计-按课程统计
+export function exportUserWatchCourseStatistics(query) {
+  return request({
+    url: '/course/userWatchCourseStatistics/export',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询会员看课统计-按课程统计列表
+export function listUserWatchCourseStatisticsTotal(query) {
+  return request({
+    url: '/course/userWatchCourseStatistics/listTotal',
+    method: 'get',
+    params: query
+  })
+}
+
+// 导出会员看课统计-按课程统计汇总
+export function exportUserWatchCourseStatisticsTotal(query) {
+  return request({
+    url: '/course/userWatchCourseStatistics/exportTotal',
+    method: 'get',
+    params: query
+  })
+}

+ 53 - 0
src/api/course/userWatchStatistics.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询会员看课统计-按营期统计列表
+export function listUserWatchStatistics(query) {
+  return request({
+    url: '/course/userWatchStatistics/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询会员看课统计-按营期统计详细
+export function getUserWatchStatistics(id) {
+  return request({
+    url: '/course/userWatchStatistics/' + id,
+    method: 'get'
+  })
+}
+
+// 新增会员看课统计-按营期统计
+export function addUserWatchStatistics(data) {
+  return request({
+    url: '/course/userWatchStatistics',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改会员看课统计-按营期统计
+export function updateUserWatchStatistics(data) {
+  return request({
+    url: '/course/userWatchStatistics',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除会员看课统计-按营期统计
+export function delUserWatchStatistics(id) {
+  return request({
+    url: '/course/userWatchStatistics/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出会员看课统计-按营期统计
+export function exportUserWatchStatistics(query) {
+  return request({
+    url: '/course/userWatchStatistics/export',
+    method: 'get',
+    params: query
+  })
+}

+ 46 - 0
src/api/his/packageSolarTerm.js

@@ -0,0 +1,46 @@
+import request from '@/utils/request'
+
+export function listPackageSolarTerm(query) {
+  return request({
+    url: '/his/packageSolarTerm/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getPackageSolarTerm(solarTermId) {
+  return request({
+    url: '/his/packageSolarTerm/' + solarTermId,
+    method: 'get'
+  })
+}
+
+export function addPackageSolarTerm(data) {
+  return request({
+    url: '/his/packageSolarTerm',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updatePackageSolarTerm(data) {
+  return request({
+    url: '/his/packageSolarTerm',
+    method: 'put',
+    data: data
+  })
+}
+
+export function delPackageSolarTerm(solarTermIds) {
+  return request({
+    url: '/his/packageSolarTerm/' + solarTermIds,
+    method: 'delete'
+  })
+}
+
+export function getOptions() {
+  return request({
+    url: '/his/packageSolarTerm/getOptions',
+    method: 'get'
+  })
+}

+ 53 - 0
src/api/his/userOnlineState.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询用户上线情况列表
+export function listUserOnlineState(query) {
+  return request({
+    url: '/store/userOnlineState/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询用户上线情况详细
+export function getUserOnlineState(userId) {
+  return request({
+    url: '/store/userOnlineState/' + userId,
+    method: 'get'
+  })
+}
+
+// 新增用户上线情况
+export function addUserOnlineState(data) {
+  return request({
+    url: '/store/userOnlineState',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改用户上线情况
+export function updateUserOnlineState(data) {
+  return request({
+    url: '/store/userOnlineState',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除用户上线情况
+export function delUserOnlineState(userId) {
+  return request({
+    url: '/store/userOnlineState/' + userId,
+    method: 'delete'
+  })
+}
+
+// 导出用户上线情况
+export function exportUserOnlineState(query) {
+  return request({
+    url: '/store/userOnlineState/export',
+    method: 'get',
+    params: query
+  })
+}

BIN
src/assets/logo/fby_logo.png


+ 1 - 1
src/views/company/company/index.vue

@@ -550,7 +550,7 @@ export default {
 
     handleResetPwd(row) {
       const companyIds = row.companyId || this.ids;
-      this.$confirm('是否确认重复密码为123456?', "警告", {
+      this.$confirm('是否确认重置密码为cq654321!!', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",
           type: "warning"

+ 4 - 4
src/views/company/companyRecharge/index.vue

@@ -97,17 +97,17 @@
         <template slot-scope="scope">
           <el-button
             v-if="scope.row.isAudit==0"
-            size="mini" 
+            size="mini"
             type="text"
             icon="el-icon-edit"
             @click="handleAudit(scope.row)"
             v-hasPermi="['company:companyRecharge:audit']"
           >审核</el-button>
-          
+
         </template>
       </el-table-column>
     </el-table>
-    
+
     <pagination
       v-show="total>0"
       :total="total"
@@ -197,7 +197,7 @@ export default {
   created() {
      getCompanyList().then(response => {
       this.companys = response.data;
-       
+
     });
     this.getDicts("sys_comapny_recharge_pay_type").then((response) => {
       this.payTypeOptions = response.data;

+ 249 - 272
src/views/components/course/userCourseCatalogDetails.vue

@@ -1,17 +1,12 @@
 <template>
   <div class="app-container">
     <div style="padding-bottom: 20px">
-      <span v-if="courseName!=null">{{ courseName }}</span>
+      <span v-if="courseName != null">{{ courseName }}</span>
     </div>
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
       <el-form-item label="小节名称" prop="title">
-        <el-input
-          v-model="queryParams.title"
-          placeholder="请输入小节名称"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
+        <el-input v-model="queryParams.title" placeholder="请输入小节名称" clearable size="small"
+          @keyup.enter.native="handleQuery" />
       </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@@ -20,63 +15,33 @@
     </el-form>
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button
-          type="primary"
-          plain
-          icon="el-icon-plus"
-          size="mini"
-          @click="handleAdd"
-          v-hasPermi="['course:userCourseVideo:add']"
-        >新增目录</el-button>
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
+          v-hasPermi="['course:userCourseVideo:add']">新增目录</el-button>
       </el-col>
       <el-col :span="1.5">
-        <el-button
-          type="primary"
-          plain
-          :disabled="!ids || ids.length <= 0"
-          size="mini"
-          @click="openUpdates"
-          v-hasPermi="['course:userCourseVideo:updateTime']"
-        >修改时间</el-button>
+        <el-button type="primary" plain :disabled="!ids || ids.length <= 0" size="mini" @click="openUpdates"
+          v-hasPermi="['course:userCourseVideo:updateTime']">修改时间</el-button>
       </el-col>
       <el-col :span="1.5">
-        <el-button
-          type="primary"
-          plain
-          size="mini"
-          @click="openAdds"
-          v-hasPermi="['course:userCourseVideo:batchAdd']"
-        >批量添加</el-button>
+        <el-button type="primary" plain size="mini" @click="openAdds"
+          v-hasPermi="['course:userCourseVideo:batchAdd']">批量添加</el-button>
       </el-col>
       <el-col :span="1.5">
-        <el-button
-          type="primary"
-          plain
-          size="mini"
-          v-if="isPrivate === 1"
-          @click="updateRedPageckeOpen"
-          v-hasPermi="['course:userCourseVideo:updateRed']"
-        >修改红包</el-button>
+        <el-button type="primary" plain size="mini" v-if="isPrivate === 1" @click="updateRedPageckeOpen"
+          v-hasPermi="['course:userCourseVideo:updateRed']">修改红包</el-button>
       </el-col>
       <el-col :span="1.5">
-        <el-button
-          type="danger"
-          plain
-          icon="el-icon-delete"
-          size="mini"
-          :disabled="multiple"
-          @click="handleDelete"
-          v-hasPermi="['course:userCourseVideo:remove']"
-        >删除</el-button>
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
+          v-hasPermi="['course:userCourseVideo:remove']">删除</el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
     <el-table border v-loading="loading" :data="userCourseVideoList" @selection-change="handleSelectionChange">
       <el-table-column type="selection" width="55" align="center" />
       <el-table-column label="视频ID" align="center" prop="videoId" />
-<!--      <el-table-column label="轮次" align="center" prop="round" />-->
+      <!--      <el-table-column label="轮次" align="center" prop="round" />-->
       <el-table-column label="小节名称" align="center" show-overflow-tooltip prop="title" />
-      <el-table-column label="视频文件名称" align="center" show-overflow-tooltip  prop="fileName" >
+      <el-table-column label="视频文件名称" align="center" show-overflow-tooltip prop="fileName">
       </el-table-column>
       <el-table-column label="视频时长" align="center" prop="duration">
         <template slot-scope="{ row }">
@@ -85,13 +50,13 @@
       </el-table-column>
       <el-table-column label="看课开始时间" align="center" prop="duration">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.viewStartTime">{{row.viewStartTime}}</el-tag>
+          <el-tag v-if="row.viewStartTime">{{ row.viewStartTime }}</el-tag>
           <el-tag type="danger" v-if="!row.viewStartTime">无</el-tag>
         </template>
       </el-table-column>
       <el-table-column label="看课结束时间" align="center" prop="duration">
         <template slot-scope="{ row }">
-          <el-tag v-if="row.viewEndTime">{{row.viewEndTime}}</el-tag>
+          <el-tag v-if="row.viewEndTime">{{ row.viewEndTime }}</el-tag>
           <el-tag type="danger" v-if="!row.viewEndTime">无</el-tag>
         </template>
       </el-table-column>
@@ -101,56 +66,36 @@
           <el-tag type="danger" v-if="!row.lastJoinTime">无</el-tag>
         </template>
       </el-table-column>
-      <el-table-column label="红包金额" align="center" prop="redPacketMoney" v-if="isPrivate === 1"/>
+      <el-table-column label="红包金额" align="center" prop="redPacketMoney" v-if="isPrivate === 1" />
       <el-table-column label="排序" align="center" prop="courseSort" />
       <el-table-column label="上传时间" align="center" prop="createTime" />
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template slot-scope="scope">
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleUpdate(scope.row)"
-            v-hasPermi="['course:userCourseVideo:edit']"
-          >修改</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-edit"
-            @click="handleComment(scope.row)"
-            v-hasPermi="['course:courseWatchComment:list']"
-          >查看评论</el-button>
-          <el-button
-            size="mini"
-            type="text"
-            icon="el-icon-delete"
-            @click="handleDelete(scope.row)"
-            v-hasPermi="['course:userCourseVideo:remove']"
-          >删除</el-button>
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
+            v-hasPermi="['course:userCourseVideo:edit']">修改</el-button>
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleComment(scope.row)"
+            v-hasPermi="['course:courseWatchComment:list']">查看评论</el-button>
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
+            v-hasPermi="['course:userCourseVideo:remove']">删除</el-button>
         </template>
       </el-table-column>
     </el-table>
 
-    <pagination
-      v-show="total>0"
-      :total="total"
-      :page.sync="queryParams.pageNum"
-      :limit.sync="queryParams.pageSize"
-      @pagination="getList"
-    />
-    <el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body >
+    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
+      @pagination="getList" />
+    <el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body>
       <el-form ref="form" :model="form" :rules="rules" label-width="110px" v-loading="uploadLoading">
         <el-form-item label="视频标题" prop="title">
-          <el-input v-model="form.title"  placeholder="请输入内容" />
+          <el-input v-model="form.title" placeholder="请输入内容" />
         </el-form-item>
         <el-form-item label="视频描述" prop="description">
-          <el-input v-model="form.description" type="textarea" :rows="2"  placeholder="请输入内容" />
+          <el-input v-model="form.description" type="textarea" :rows="2" placeholder="请输入内容" />
         </el-form-item>
-<!--        <el-form-item label="轮次" prop="round">-->
-<!--          <el-input v-model="form.round"  placeholder="请输入内容" />-->
-<!--        </el-form-item>-->
+        <!--        <el-form-item label="轮次" prop="round">-->
+        <!--          <el-input v-model="form.round"  placeholder="请输入内容" />-->
+        <!--        </el-form-item>-->
         <el-form-item label="课程排序" prop="courseSort">
-          <el-input-number v-model="form.courseSort" :min="1" ></el-input-number>
+          <el-input-number v-model="form.courseSort" :min="1"></el-input-number>
         </el-form-item>
         <!--        <el-form-item label="看课时间" prop="timeRange" v-if="isPrivate === 1">-->
         <!--          <el-time-picker-->
@@ -174,46 +119,28 @@
         <!--        </el-form-item>-->
 
         <el-form-item label="视频缩略图" prop="thumbnail">
-          <el-upload
-            v-model="form.thumbnail"
-            class="avatar-uploader"
-            :action="uploadUrl"
-            :show-file-list="false"
-            :on-success="handleAvatarSuccess"
-            :before-upload="beforeAvatarUpload">
+          <el-upload v-model="form.thumbnail" class="avatar-uploader" :action="uploadUrl" :show-file-list="false"
+            :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
             <img v-if="form.thumbnail" :src="form.thumbnail" class="avatar" width="300px">
             <i v-else class="el-icon-plus avatar-uploader-icon"></i>
           </el-upload>
         </el-form-item>
-        <video-upload
-          :type = "1"
-          :isPrivate = "isPrivate"
-          :fileKey.sync = "form.fileKey"
-          :fileSize.sync = "form.fileSize"
-          :videoUrl.sync="videoUrl"
-          :fileName.sync="form.fileName"
-          :line_1.sync="form.lineOne"
-          :line_2.sync="form.lineTwo"
-          :line_3.sync="form.lineThree"
-          :thumbnail.sync="form.thumbnail"
-          :uploadType.sync="form.uploadType"
-          :isTranscode.sync="form.isTranscode"
-          :transcodeFileKey.sync="form.transcodeFileKey"
-          @video-duration="handleVideoDuration"
-          @change="handleVideoChange"
-          @selectProjects="handleSelectProjects"
-          ref="videoUpload"
-          append-to-body
-        />
-
+        <video-upload :type="1" :isPrivate="isPrivate" :fileKey.sync="form.fileKey" :fileSize.sync="form.fileSize"
+          :videoUrl.sync="videoUrl" :fileName.sync="form.fileName" :line_1.sync="form.lineOne"
+          :line_2.sync="form.lineTwo" :line_3.sync="form.lineThree" :thumbnail.sync="form.thumbnail"
+          :uploadType.sync="form.uploadType" :isTranscode.sync="form.isTranscode"
+          :transcodeFileKey.sync="form.transcodeFileKey" @video-duration="handleVideoDuration"
+          @change="handleVideoChange" @selectProjects="handleSelectProjects" ref="videoUpload" append-to-body />
+        
         <el-form-item label="课题选择" prop="questionBankId" v-if="isPrivate === 1">
           <el-button size="small" type="primary" @click="chooseQuestionBank">选取课题</el-button>
-          <el-table border width="100%" style="margin-top:5px;"  :data="form.questionBankList">
+          <el-table border width="100%" style="margin-top:5px;" :data="form.questionBankList">
 
             <el-table-column label="问题" align="center" prop="title">
               <template slot-scope="scope">
                 <el-tooltip class="item" effect="dark" :content="scope.row.title" placement="top">
-                  <div style="display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; text-overflow: ellipsis;">
+                  <div
+                    style="display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; text-overflow: ellipsis;">
                     <span>{{ scope.row.title }}</span>
                   </div>
                 </el-tooltip>
@@ -221,50 +148,68 @@
             </el-table-column>
             <el-table-column label="类别" align="center" prop="type">
               <template slot-scope="scope">
-                <dict-tag :options="typeOptions" :value="scope.row.type"/>
+                <dict-tag :options="typeOptions" :value="scope.row.type" />
               </template>
             </el-table-column>
             <el-table-column label="答案" align="center" prop="answer" />
             <el-table-column label="操作" align="center" width="100px" fixed="right">
               <template slot-scope="scope">
-                <el-button
-                  size="mini"
-                  type="text"
-                  icon="el-icon-delete"
-                  @click="handleQuestionBankDelete(scope.row)"
-                >删除</el-button>
+                <el-button size="mini" type="text" icon="el-icon-delete"
+                  @click="handleQuestionBankDelete(scope.row)">删除</el-button>
               </template>
             </el-table-column>
           </el-table>
-        </el-form-item >
+        </el-form-item>
         <el-form-item label="红包金额" prop="redPacketMoney" v-if="isPrivate === 1">
-          <el-input-number v-model="form.redPacketMoney" :min="0.1" :max="200" :step="0.1" ></el-input-number>
+          <el-input-number v-model="form.redPacketMoney" :min="0.1" :max="200" :step="0.1"></el-input-number>
+        </el-form-item>
+        <el-form-item label="是否关联商品">
+          <el-radio v-model="form.isProduct" :label=0>否</el-radio>
+          <el-radio v-model="form.isProduct" :label=1>是</el-radio>
+        </el-form-item>
+        <el-form-item label="商品选择" v-if="form.isProduct === 1">
+          <el-button size="small" type="primary" @click="chooseCourseProduct">选取商品</el-button>
+          <el-table border width="100%" style="margin-top:5px;" :data="form.courseProducts">
+            <el-table-column label="商品名称" align="center" prop="productName" />
+            <el-table-column label="产品条码" align="center" prop="barCode" />
+            <el-table-column label="商品价格" align="center" prop="productPrice" />
+            <el-table-column label="库存" align="center" prop="stock" />
+            <el-table-column label="操作" align="center" width="100px" fixed="right">
+              <template slot-scope="scope">
+                <el-button size="mini" type="text" icon="el-icon-delete"
+                  @click="handleCourseProductDelete(scope.row)">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
         </el-form-item>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item v-if="form.isProduct === 1" label="商品售卖时间" prop="listingStartTime">
+              <el-input-number v-model="form.listingStartTime" :min="0" label="商品售卖时间"></el-input-number>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item v-if="form.isProduct === 1"  label="结束售卖时间" prop="listingStartTime">
+              <el-input-number v-model="form.listingEndTime" :min="0" label="结束售卖时间"></el-input-number>
+            </el-form-item>
+          </el-col>
+        </el-row>
       </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="submitForm">确 定</el-button>
         <el-button @click="cancel">取 消</el-button>
       </div>
     </el-dialog>
-    <el-dialog :title="title" :visible.sync="updateBatchData.open" width="1000px" append-to-body >
+    <el-dialog :title="title" :visible.sync="updateBatchData.open" width="1000px" append-to-body>
       <el-form ref="form" :model="updateBatchData.form" label-width="110px">
         <el-form-item label="看课时间" prop="timeRange">
-          <el-time-picker
-            is-range
-            v-model="updateBatchData.form.timeRange"
-            range-separator="至"
-            start-placeholder="开始时间"
-            value-format="HH:mm:ss"
-            end-placeholder="结束时间"
-            placeholder="选择时间范围">
+          <el-time-picker is-range v-model="updateBatchData.form.timeRange" range-separator="至" start-placeholder="开始时间"
+            value-format="HH:mm:ss" end-placeholder="结束时间" placeholder="选择时间范围">
           </el-time-picker>
         </el-form-item>
         <el-form-item label="领取红包时间" prop="lastJoinTime">
-          <el-time-picker
-            v-model="updateBatchData.form.lastJoinTime"
-            :selectableRange="updateBatchData.form.timeRange"
-            value-format="HH:mm:ss"
-            placeholder="选择时间范围">
+          <el-time-picker v-model="updateBatchData.form.lastJoinTime" :selectableRange="updateBatchData.form.timeRange"
+            value-format="HH:mm:ss" placeholder="选择时间范围">
           </el-time-picker>
           <p style="color: red;margin: 0;font-size: 12px">超过领取红包时间,只允许看课,不允许领取红包</p>
         </el-form-item>
@@ -274,39 +219,30 @@
         <el-button @click="updateBatchData.open = false">取 消</el-button>
       </div>
     </el-dialog>
-    <el-dialog :title="questionBank.title" :visible.sync="questionBank.open" width="1000px" append-to-body >
-      <question-bank ref="questionBank" @questionBankResult="questionBankResult" ></question-bank>
+    <el-dialog :title="questionBank.title" :visible.sync="questionBank.open" width="1000px" append-to-body>
+      <question-bank ref="questionBank" @questionBankResult="questionBankResult"></question-bank>
+    </el-dialog>
+    <el-dialog :title="courseProduct.title" :visible.sync="courseProduct.open" width="1000px" append-to-body>
+      <course-product ref="courseProduct" @courseProductResult="courseProductResult"></course-product>
     </el-dialog>
     <el-dialog title="视频库选择" :visible.sync="addBatchData.open" width="900px" append-to-body>
       <!-- 搜索条件 -->
       <el-form :inline="true" :model="addBatchData.queryParams" class="library-search">
         <el-form-item label="素材名称">
-          <el-input
-            v-model="addBatchData.queryParams.resourceName"
-            placeholder="请输入素材名称"
-            clearable
-            size="small"
-            @keyup.enter.native="resourceList"
-          />
+          <el-input v-model="addBatchData.queryParams.resourceName" placeholder="请输入素材名称" clearable size="small"
+            @keyup.enter.native="resourceList" />
         </el-form-item>
         <el-form-item label="类型">
-          <el-select v-model="addBatchData.queryParams.typeId" @change="changeCateType" placeholder="请选择素材类型" clearable size="small">
-            <el-option
-              v-for="item in addBatchData.typeOptions"
-              :key="item.dictValue"
-              :label="item.dictLabel"
-              :value="item.dictValue"
-            />
+          <el-select v-model="addBatchData.queryParams.typeId" @change="changeCateType" placeholder="请选择素材类型" clearable
+            size="small">
+            <el-option v-for="item in addBatchData.typeOptions" :key="item.dictValue" :label="item.dictLabel"
+              :value="item.dictValue" />
           </el-select>
         </el-form-item>
         <el-form-item label="子类型">
           <el-select v-model="addBatchData.queryParams.typeSubId" placeholder="请选择素材子类型" clearable size="small">
-            <el-option
-              v-for="item in addBatchData.typeSubOptions"
-              :key="item.dictValue"
-              :label="item.dictLabel"
-              :value="item.dictValue"
-            />
+            <el-option v-for="item in addBatchData.typeSubOptions" :key="item.dictValue" :label="item.dictLabel"
+              :value="item.dictValue" />
           </el-select>
         </el-form-item>
         <el-form-item>
@@ -315,18 +251,15 @@
       </el-form>
 
       <!-- 视频列表 -->
-      <el-table v-loading="addBatchData.loading" :data="addBatchData.list" @selection-change="handVideoleSelectionChange" height="400px">
+      <el-table v-loading="addBatchData.loading" :data="addBatchData.list"
+        @selection-change="handVideoleSelectionChange" height="400px">
         <el-table-column type="selection" width="55" align="center" />
         <el-table-column label="素材名称" align="center" prop="resourceName" />
         <el-table-column label="文件名称" align="center" prop="fileName" />
         <el-table-column label="排序" align="center" prop="sort" />
         <el-table-column label="缩略图" align="center">
           <template slot-scope="scope">
-            <el-popover
-              placement="right"
-              title=""
-              trigger="hover"
-            >
+            <el-popover placement="right" title="" trigger="hover">
               <img alt="" slot="reference" :src="scope.row.thumbnail" style="width: 80px; height: 50px" />
               <img alt="" :src="scope.row.thumbnail" style="max-width: 150px;" />
             </el-popover>
@@ -340,13 +273,9 @@
       </el-table>
 
       <!-- 分页 -->
-      <pagination
-        v-show="addBatchData.total>0"
-        :total="addBatchData.total"
-        :page.sync="addBatchData.queryParams.pageNum"
-        :limit.sync="addBatchData.queryParams.pageSize"
-        @pagination="resourceList"
-      />
+      <pagination v-show="addBatchData.total > 0" :total="addBatchData.total"
+        :page.sync="addBatchData.queryParams.pageNum" :limit.sync="addBatchData.queryParams.pageSize"
+        @pagination="resourceList" />
 
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="batchVideoSave">确 定</el-button>
@@ -355,7 +284,7 @@
     <el-dialog title="章节红包" :visible.sync="redData.open" width="900px" append-to-body>
       <el-table border v-loading="redData.loading" :data="redData.list" height="600px">
         <el-table-column label="小节名称" align="center" show-overflow-tooltip prop="title" />
-        <el-table-column label="视频文件名称" align="center" show-overflow-tooltip  prop="fileName" >
+        <el-table-column label="视频文件名称" align="center" show-overflow-tooltip prop="fileName">
         </el-table-column>
         <el-table-column label="视频时长" align="center" prop="duration">
           <template slot-scope="{ row }">
@@ -374,11 +303,9 @@
         <el-button type="primary" @click="batchRedSave">确 定</el-button>
       </div>
     </el-dialog>
-    <el-dialog :title="commentDialog.title" :visible.sync="commentDialog.open" width="1000px" append-to-body :close-on-click-modal="false">
-      <course-watch-comment
-        ref="courseWatchComment"
-        :courseId="commentDialog.courseId"
-        :videoId="commentDialog.videoId"
+    <el-dialog :title="commentDialog.title" :visible.sync="commentDialog.open" width="1000px" append-to-body
+      :close-on-click-modal="false">
+      <course-watch-comment ref="courseWatchComment" :courseId="commentDialog.courseId" :videoId="commentDialog.videoId"
         v-if="commentDialog.open">
       </course-watch-comment>
     </el-dialog>
@@ -399,6 +326,7 @@ import {
   updateUserCourseVideo
 } from "@/api/course/userCourseVideo";
 import QuestionBank from "@/views/course/courseQuestionBank/QuestionBank.vue";
+import CourseProduct from "@/views/course/fsCourseProduct/CourseProduct.vue";
 import VideoUpload from "@/components/VideoUpload/index.vue";
 import { listVideoResource } from '@/api/course/videoResource';
 import { getByIds } from '@/api/course/courseQuestionBank'
@@ -407,38 +335,43 @@ import { getCateListByPid, getCatePidList } from '@/api/course/userCourseCategor
 
 export default {
   name: "userCourseCatalog",
-  components: {VideoUpload,QuestionBank,CourseWatchComment},
+  components: { VideoUpload, QuestionBank, CourseWatchComment, CourseProduct,},
   data() {
     return {
       duration: null,
-      packageList:[],
+      packageList: [],
       //课题
-      package:{
-        title:'',
-        open:false,
+      package: {
+        title: '',
+        open: false,
       },
       //课题
-      questionBank:{
-        title:'',
-        open:false,
+      questionBank: {
+        title: '',
+        open: false,
+      },
+      //拍商品
+      courseProduct: {
+        title: '',
+        open: false,
       },
-      isPrivate:null,
+      isPrivate: null,
       videoUrl: "",
       uploadTypeOptions: [
         { dictLabel: "线路一", dictValue: 2 },
 
         { dictLabel: "线路二", dictValue: 3 },
       ],
-      uploadLoading:false,
-      courseId:null,
-      videoName:'',
+      uploadLoading: false,
+      courseId: null,
+      videoName: '',
       title: "",
       // 是否显示弹出层
       open: false,
-      uploadUrl:process.env.VUE_APP_BASE_API+"/common/uploadOSS",
+      uploadUrl: process.env.VUE_APP_BASE_API + "/common/uploadOSS",
       baseUrl: process.env.VUE_APP_BASE_API,
-      typeOptions:[],
-      files:[],
+      typeOptions: [],
+      files: [],
       fileList: [],
       // 上传成功后的地址
       videoURL: '',
@@ -446,33 +379,33 @@ export default {
       progress: 0,
       // 上传视频获取成功后拿到的fileID【备用】
       fileId: '',
-      courseName:null,
-      userCourseVideoList:[],
+      courseName: null,
+      userCourseVideoList: [],
       total: 0,
-      redData:{
+      redData: {
         queryParams: {
           pageNum: 1,
           pageSize: 99999,
-          courseId:null,
+          courseId: null,
         },
         list: [],
         open: false,
-        loading:true,
-        form:{
+        loading: true,
+        form: {
         }
       },
       queryParams: {
         pageNum: 1,
         pageSize: 10,
-        courseId:null,
-        title:null
+        courseId: null,
+        title: null
       },
       addBatchData: {
         open: false,
         loading: true,
         form: {},
         select: [],
-        total:0,
+        total: 0,
         queryParams: {
           pageNum: 1,
           pageSize: 10,
@@ -499,7 +432,7 @@ export default {
       form: {},
       updateBatchData: {
         open: false,
-        form:{}
+        form: {}
       },
       // 表单校验
       rules: {
@@ -528,8 +461,8 @@ export default {
   methods: {
     getPickerOptions() {
       const durationInMinutes = Math.floor(this.form.duration / 60); // 将秒转换为分钟
-      const endHour  = Math.floor(durationInMinutes / 60); // 起始小时
-      const endMinute  = durationInMinutes % 60; // 起始分钟
+      const endHour = Math.floor(durationInMinutes / 60); // 起始小时
+      const endMinute = durationInMinutes % 60; // 起始分钟
       return {
         start: "00:00", // 固定开始时间
         step: "00:01", // 时间间隔
@@ -538,35 +471,43 @@ export default {
           .padStart(2, "0")}`, // 动态结束时间
       };
     },
-    handlePackageDelete(row){
+    handlePackageDelete(row) {
       this.packageList.splice(this.packageList.findIndex(item => item.packageId === row.packageId), 1)
     },
-    choosePackage(){
-      this.package.open=true;
-      this.package.title='疗法选择';
+    choosePackage() {
+      this.package.open = true;
+      this.package.title = '疗法选择';
     },
     /**
      * 选择课题
      */
-    chooseQuestionBank(){
-      this.questionBank.open=true;
-      this.questionBank.title='课题选择';
+    chooseQuestionBank() {
+      this.questionBank.open = true;
+      this.questionBank.title = '课题选择';
+    },
+
+    /**
+     * 选择拍商品
+     */
+    chooseCourseProduct() {
+      this.courseProduct.open = true;
+      this.courseProduct.title = '拍商品选择';
     },
 
     //选择疗法
-    selectPackage(row){
+    selectPackage(row) {
       const drug = {};
-      for(var i=0;i<this.packageList.length;i++){
-        if(this.packageList[i].packageId==row.packageId){
+      for (var i = 0; i < this.packageList.length; i++) {
+        if (this.packageList[i].packageId == row.packageId) {
           this.$message.warning("疗法已存在!")
           return;
         }
       }
-      drug.packageId=row.packageId;
-      drug.packageName=row.packageName;
-      drug.secondName=row.secondName;
-      drug.totalPrice=row.totalPrice;
-      drug.imgUrl=row.imgUrl;
+      drug.packageId = row.packageId;
+      drug.packageName = row.packageName;
+      drug.secondName = row.secondName;
+      drug.totalPrice = row.totalPrice;
+      drug.imgUrl = row.imgUrl;
       this.packageList.push(drug);
       this.$message({
         message: '添加成功',
@@ -575,14 +516,31 @@ export default {
 
     },
 
+    courseProductResult(val){
+      this.form.courseProducts = this.form.courseProducts || [];
+      for (var i = 0; i < this.form.courseProducts.length; i++) {
+        if (this.form.courseProducts[i].id == val.id) {
+          return this.$message.error("当前商品已选择")
+        }
+      }
+
+      //先置空 只选择一件商品
+      this.form.courseProducts = [];
+      this.form.courseProducts.push(val);
+      this.$message({
+        message: '添加成功',
+        type: 'success'
+      });
+    },
+
     //选择结果
-    questionBankResult(val){
+    questionBankResult(val) {
 
       // 确保 questionBankList 是数组
       this.form.questionBankList = this.form.questionBankList || [];
 
-      for(var i=0;i<this.form.questionBankList.length;i++){
-        if(this.form.questionBankList[i].id==val.id){
+      for (var i = 0; i < this.form.questionBankList.length; i++) {
+        if (this.form.questionBankList[i].id == val.id) {
           return this.$message.error("当前课题已选择")
         }
       }
@@ -595,15 +553,20 @@ export default {
     },
 
     //删除课题
-    handleQuestionBankDelete(row){
+    handleQuestionBankDelete(row) {
       this.form.questionBankList.splice(this.form.questionBankList.findIndex(item => item.id === row.id), 1)
     },
-       handleVideoChange(){
-      if(this.form.uploadType==1){
+
+    //删除商品
+    handleCourseProductDelete(row) {
+      this.form.courseProducts.splice(this.form.courseProducts.findIndex(item => item.id === row.id), 1)
+    },
+    handleVideoChange() {
+      if (this.form.uploadType == 1) {
         this.videoUrl = this.form.lineOne;
-      }else if(this.form.uploadType==2){
+      } else if (this.form.uploadType == 2) {
         this.videoUrl = this.form.lineTwo;
-      }else if(this.form.uploadType==3){
+      } else if (this.form.uploadType == 3) {
         this.videoUrl = this.form.lineThree;
       }
       // console.log("选择的video=======>>>>>>>",this.videoUrl)
@@ -615,7 +578,7 @@ export default {
         return
       }
 
-      const params = {ids: projectIds}
+      const params = { ids: projectIds }
       getByIds(params).then(response => {
         if (response.code === 200) {
           response.data.forEach(item => {
@@ -646,11 +609,11 @@ export default {
     },
 
     handleAvatarSuccess(res, file) {
-      if(res.code==200){
-        this.form.thumbnail=res.url;
+      if (res.code == 200) {
+        this.form.thumbnail = res.url;
         this.$forceUpdate()
       }
-      else{
+      else {
         this.msgError(res.msg);
       }
     },
@@ -659,9 +622,9 @@ export default {
       if (!isLt1M) {
         this.$message.error('上传图片大小不能超过 1MB!');
       }
-      return   isLt1M;
+      return isLt1M;
     },
-    getDetails(courseId,courseName,isPrivate) {
+    getDetails(courseId, courseName, isPrivate) {
       this.isPrivate = isPrivate
       this.courseName = courseName
       this.courseId = courseId;
@@ -691,11 +654,11 @@ export default {
         thumbnail: null,
         duration: null,
         createTime: null,
-        uploadType:null,
-        lineOne:null,
-        lineTwo:null,
-        lineThree:null,
-        fileName:null,
+        uploadType: null,
+        lineOne: null,
+        lineTwo: null,
+        lineThree: null,
+        fileName: null,
         userId: null,
         cateId: null,
         courseId: null,
@@ -716,14 +679,18 @@ export default {
         tags: null,
         productId: null,
         productJson: null,
-        questionBankId:null,
-        questionBankList:[],
-        redPacketMoney:0,
-        isTranscode:0,
-        transcodeFileKey:null
+        questionBankId: null,
+        questionBankList: [],
+        redPacketMoney: 0,
+        isTranscode: 0,
+        transcodeFileKey: null,
+        isProduct: 0,
+        productId: null,
+        listingStartTime: null,
+        listingEndTime: null,
       };
       this.videoURL = '';
-      this.progress=0;
+      this.progress = 0;
       this.resetForm("form");
     },
     /** 搜索按钮操作 */
@@ -739,20 +706,20 @@ export default {
     // 多选框选中数据
     handleSelectionChange(selection) {
       this.ids = selection.map(item => item.videoId)
-      this.single = selection.length!==1
+      this.single = selection.length !== 1
       this.multiple = !selection.length
     },
     // 多选框选中数据
     handVideoleSelectionChange(selection) {
       this.addBatchData.select = selection.map(item => item.id);
     },
-    handleAdd(){
+    handleAdd() {
       this.reset();
       this.form.courseId = this.courseId;
       this.open = true;
       this.title = "添加课堂视频";
       this.videoUrl = '';
-      this.packageList=[];
+      this.packageList = [];
       getSort(this.courseId).then(response => {
         this.form.courseSort = Number(response.data);
       })
@@ -764,18 +731,18 @@ export default {
     /** 修改按钮操作 */
     handleUpdate(row) {
       this.reset();
-      this.packageList=[];
+      this.packageList = [];
       const videoId = row.videoId || this.ids
       getUserCourseVideo(videoId).then(response => {
         this.form = response.data;
-        if(response.data.videoUrl!=null && response.data.videoUrl!==''){
+        if (response.data.videoUrl != null && response.data.videoUrl !== '') {
           this.videoUrl = response.data.videoUrl;
         }
-        if (this.form.packageJson!=null){
+        if (this.form.packageJson != null) {
           this.packageList = JSON.parse(this.form.packageJson);
         }
 
-        if(response.data.viewStartTime != null && response.data.viewEndTime != null){
+        if (response.data.viewStartTime != null && response.data.viewEndTime != null) {
           this.form.timeRange = [response.data.viewStartTime, response.data.viewEndTime]
         }
         setTimeout(() => {
@@ -792,24 +759,31 @@ export default {
 
         if (valid) {
           this.form.videoUrl = this.videoUrl;
-          if(this.form.videoUrl==null || this.form.videoUrl===''){
+          if (this.form.videoUrl == null || this.form.videoUrl === '') {
             this.$message({
               message: '请上传视频!',
               type: 'warning'
             });
             return
           }
-          if(this.form.timeRange != null && this.form.timeRange.length === 2){
+          if (this.form.timeRange != null && this.form.timeRange.length === 2) {
             this.form.viewStartTime = this.form.timeRange[0];
             this.form.viewEndTime = this.form.timeRange[1];
           }
-          if(this.form.duration==null){
+          if (this.form.duration == null) {
             this.$message({
               message: '未识别到视频时长请稍等。。。',
               type: 'warning'
             });
             return
           }
+          if (this.form.isProduct != null && this.form.isProduct == 1 && this.form.courseProducts.length < 1) {
+             this.$message({
+              message: '请选择关联商品',
+              type: 'warning'
+            });
+            return
+          }
           // if(this.form.uploadType==null){
           //   this.$message({
           //     message: '请选择播放线路!',
@@ -817,12 +791,15 @@ export default {
           //   });
           //   return
           // }
-          if (this.form.questionBankList!==null){
+          if (this.form.questionBankList !== null) {
             this.form.questionBankId = this.form.questionBankList.map(item => item.id).join(',');
           }
-          if (this.packageList.length>0){
+          if (this.packageList.length > 0) {
             this.form.packageJson = JSON.stringify(this.packageList);
           }
+          if (this.form.courseProducts != null) {
+            this.form.productId = this.form.courseProducts[0].id
+          }
           if (this.form.videoId != null) {
             updateUserCourseVideo(this.form).then(response => {
               this.msgSuccess("修改成功");
@@ -839,14 +816,14 @@ export default {
         }
       });
     },
-    openUpdates(){
+    openUpdates() {
       this.updateBatchData.form = {};
       this.updateBatchData.open = true;
     },
     /** 提交按钮 */
     updateBatch() {
       this.updateBatchData.form.ids = this.ids;
-      if(this.updateBatchData.form.timeRange != null && this.updateBatchData.form.timeRange.length === 2){
+      if (this.updateBatchData.form.timeRange != null && this.updateBatchData.form.timeRange.length === 2) {
         this.updateBatchData.form.viewStartTime = this.updateBatchData.form.timeRange[0];
         this.updateBatchData.form.viewEndTime = this.updateBatchData.form.timeRange[1];
       }
@@ -863,14 +840,14 @@ export default {
         confirmButtonText: "确定",
         cancelButtonText: "取消",
         type: "warning"
-      }).then(function() {
+      }).then(function () {
         return delUserCourseVideo(videoIds);
       }).then(() => {
         this.getList();
         this.msgSuccess("删除成功");
-      }).catch(() => {});
+      }).catch(() => { });
     },
-    openAdds(){
+    openAdds() {
       this.addBatchData.open = true;
       this.getRootTypeList();
       this.addBatchData.form = {
@@ -893,7 +870,7 @@ export default {
         this.addBatchData.typeSubOptions = response.data
       })
     },
-    resourceList(){
+    resourceList() {
       this.addBatchData.loading = true;
       listVideoResource(this.addBatchData.queryParams).then(response => {
         this.addBatchData.loading = false;
@@ -901,8 +878,8 @@ export default {
         this.addBatchData.total = response.total;
       });
     },
-    batchVideoSave(){
-      if (this.addBatchData.select.length===0){
+    batchVideoSave() {
+      if (this.addBatchData.select.length === 0) {
         this.$message({
           message: '请选择视频!!',
           type: 'warning'
@@ -916,7 +893,7 @@ export default {
         this.getList();
       })
     },
-    updateRedPageckeOpen(){
+    updateRedPageckeOpen() {
       this.redData.open = true;
       this.redData.loading = true;
       this.redData.queryParams.courseId = this.courseId;
@@ -925,7 +902,7 @@ export default {
         this.redData.loading = false;
       });
     },
-    batchRedSave(){
+    batchRedSave() {
       batchUpdateRed(this.redData.list).then(response => {
         this.redData.open = false;
         this.getList();
@@ -949,6 +926,7 @@ export default {
   position: relative;
   overflow: hidden;
 }
+
 .avatar-uploader .el-upload:hover {
   border-color: #409EFF;
 }
@@ -961,5 +939,4 @@ export default {
   line-height: 150px;
   text-align: center;
 }
-
 </style>

+ 165 - 0
src/views/course/fsCourseProduct/CourseProduct.vue

@@ -0,0 +1,165 @@
+<template>
+    <div class="app-container">
+        <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+            <el-form-item label="商品名称" prop="productName">
+                <el-input v-model="queryParams.productName" placeholder="请输入商品名称" clearable size="small"
+                    @keyup.enter.native="handleQuery" />
+            </el-form-item>
+
+            <el-form-item label="产品条码" prop="barCode">
+                <el-input v-model="queryParams.barCode" placeholder="请输入产品条码" clearable size="small"
+                    @keyup.enter.native="handleQuery" />
+            </el-form-item>
+
+            <el-form-item>
+                <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+                <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+            </el-form-item>
+        </el-form>
+
+
+
+        <el-table border v-loading="loading" :data="fsCourseProductList">
+            <el-table-column label="商品名称" align="center" prop="productName" />
+            <el-table-column label="商品图片" align="center" prop="imgUrl" width="120">
+                <template slot-scope="scope">
+                    <el-popover placement="right" title="" trigger="hover">
+                        <img slot="reference" :src="scope.row.imgUrl" width="100">
+                        <img :src="scope.row.imgUrl" style="max-width: 150px;">
+                    </el-popover>
+                </template>
+            </el-table-column>
+            <el-table-column label="产品条码" align="center" prop="barCode" />
+            <el-table-column label="商品价格" align="center" prop="productPrice" />
+            <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+                <template slot-scope="scope">
+                    <el-button size="mini" type="text" icon="el-icon-edit"
+                        @click="chooseCourseProduct(scope.row)">选择此商品</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+
+        <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum"
+            :limit.sync="queryParams.pageSize" @pagination="getList" />
+
+
+    </div>
+</template>
+
+<script>
+import { listFsCourseProduct, } from "@/api/course/fsCourseProduct";
+import Material from '@/components/Material'
+import singleImg from '@/components/Material/single'
+export default {
+    name: "CourseProduct",
+    components: { Material, singleImg, },
+    watch: {
+        imageArr: function (val) {
+            this.form.imgUrl = val.join(',')
+        },
+        photoArr: function (val) {
+            this.form.images = val.join(',')
+        }
+    },
+    data() {
+        return {
+            photoArr: [],
+            imageArr: [],
+            // 遮罩层
+            loading: true,
+            // 导出遮罩层
+            exportLoading: false,
+            // 选中数组
+            ids: [],
+            // 非单个禁用
+            single: true,
+            // 非多个禁用
+            multiple: true,
+            // 显示搜索条件
+            showSearch: true,
+            // 总条数
+            total: 0,
+            // 拍单商品表格数据
+            fsCourseProductList: [],
+            // 弹出层标题
+            title: "",
+            // 是否显示弹出层
+            open: false,
+            // 查询参数
+            queryParams: {
+                pageNum: 1,
+                pageSize: 10,
+                imgUrl: null,
+                images: null,
+                barCode: null,
+                sort: null,
+                stock: null,
+                productContent: null,
+                productPrice: null,
+                productName: null,
+            },
+            // 表单参数
+            form: {},
+            // 表单校验
+
+        };
+    },
+    created() {
+        this.getList();
+    },
+    methods: {
+        chooseCourseProduct(val) {
+            this.$emit('courseProductResult', val)
+        },
+        /** 查询拍单商品列表 */
+        getList() {
+            this.loading = true;
+            listFsCourseProduct(this.queryParams).then(response => {
+                this.fsCourseProductList = response.rows;
+                this.total = response.total;
+                this.loading = false;
+            });
+        },
+        // 取消按钮
+        cancel() {
+            this.open = false;
+            this.reset();
+        },
+        // 表单重置
+        reset() {
+            this.form = {
+                id: null,
+                imgUrl: null,
+                images: null,
+                barCode: null,
+                sort: null,
+                stock: null,
+                productContent: null,
+                productPrice: null,
+                productName: null,
+                createTime: null,
+                updateTime: null
+            };
+            this.resetForm("form");
+            this.photoArr = [];
+            this.imageArr = [];
+        },
+        /** 搜索按钮操作 */
+        handleQuery() {
+            this.queryParams.pageNum = 1;
+            this.getList();
+        },
+        /** 重置按钮操作 */
+        resetQuery() {
+            this.resetForm("queryForm");
+            this.handleQuery();
+        },
+
+
+
+
+
+
+    }
+};
+</script>

+ 316 - 0
src/views/course/fsCourseProduct/index.vue

@@ -0,0 +1,316 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="商品名称" prop="productName">
+        <el-input v-model="queryParams.productName" placeholder="请输入商品名称" clearable size="small"
+          @keyup.enter.native="handleQuery" />
+      </el-form-item>
+
+      <el-form-item label="产品条码" prop="barCode">
+        <el-input v-model="queryParams.barCode" placeholder="请输入产品条码" clearable size="small"
+          @keyup.enter.native="handleQuery" />
+      </el-form-item>
+
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
+          v-hasPermi="['course:fsCourseProduct:add']">新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
+          v-hasPermi="['course:fsCourseProduct:edit']">修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
+          v-hasPermi="['course:fsCourseProduct:remove']">删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button type="warning" plain icon="el-icon-download" size="mini" :loading="exportLoading"
+          @click="handleExport" v-hasPermi="['course:fsCourseProduct:export']">导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="fsCourseProductList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="商品名称" align="center" prop="productName" />
+      <el-table-column label="商品图片" align="center" prop="imgUrl" width="120">
+        <template slot-scope="scope">
+          <el-popover placement="right" title="" trigger="hover">
+            <img slot="reference" :src="scope.row.imgUrl" width="100">
+            <img :src="scope.row.imgUrl" style="max-width: 150px;">
+          </el-popover>
+        </template>
+      </el-table-column>
+      <el-table-column label="产品条码" align="center" prop="barCode" />
+      <el-table-column label="商品价格" align="center" prop="productPrice" />
+      <el-table-column label="排序" align="center" prop="sort" />
+      <el-table-column label="库存" align="center" prop="stock" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
+            v-hasPermi="['course:fsCourseProduct:edit']">修改</el-button>
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
+            v-hasPermi="['course:fsCourseProduct:remove']">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
+      @pagination="getList" />
+
+    <!-- 添加或修改拍单商品对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="900px" append-to-body>
+
+      <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="商品名称" prop="productName">
+              <el-input v-model="form.productName" placeholder="请输入商品名称" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="商品价格" prop="productPrice">
+              <el-input v-model="form.productPrice" placeholder="请输入商品价格" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="排序" prop="sort">
+              <el-input-number v-model="form.sort" :min="0" label="排序"></el-input-number>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="库存" prop="stock">
+              <el-input-number v-model="form.stock" :min="0" label="库存"></el-input-number>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+
+        <el-form-item label="商品图片" prop="imgUrl">
+          <Material v-model="imageArr" type="image" :num="1" :width="150" :height="150" />
+        </el-form-item>
+        <el-form-item label="商品组图" prop="images">
+          <Material v-model="photoArr" type="image" :num="10" :width="150" :height="150" />
+        </el-form-item>
+
+        <el-form-item label="产品条码" prop="barCode">
+          <el-input v-model="form.barCode" placeholder="请输入产品条码" />
+        </el-form-item>
+
+        <el-form-item label="商品介绍">
+          <el-input v-model="form.productContent" type="textarea" placeholder="请输入商品介绍" />
+          <!-- <editor v-model="form.productContent" :min-height="192"/> -->
+        </el-form-item>
+
+
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listFsCourseProduct, getFsCourseProduct, delFsCourseProduct, addFsCourseProduct, updateFsCourseProduct, exportFsCourseProduct } from "@/api/course/fsCourseProduct";
+import Material from '@/components/Material'
+import singleImg from '@/components/Material/single'
+export default {
+  name: "FsCourseProduct",
+  components: { Material, singleImg, },
+  watch: {
+    imageArr: function (val) {
+      this.form.imgUrl = val.join(',')
+    },
+    photoArr: function (val) {
+      this.form.images = val.join(',')
+    }
+  },
+  data() {
+    return {
+      photoArr: [],
+      imageArr: [],
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 拍单商品表格数据
+      fsCourseProductList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        imgUrl: null,
+        images: null,
+        barCode: null,
+        sort: null,
+        stock: null,
+        productContent: null,
+        productPrice: null,
+        productName: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        productName: [
+          { required: true, message: "商品名称不能为空", trigger: "blur" }
+        ],
+        productPrice: [
+          { required: true, message: "商品价格不能为空", trigger: "blur" }
+        ]
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询拍单商品列表 */
+    getList() {
+      this.loading = true;
+      listFsCourseProduct(this.queryParams).then(response => {
+        this.fsCourseProductList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        imgUrl: null,
+        images: null,
+        barCode: null,
+        sort: null,
+        stock: null,
+        productContent: null,
+        productPrice: null,
+        productName: null,
+        createTime: null,
+        updateTime: null
+      };
+      this.resetForm("form");
+      this.photoArr = [];
+      this.imageArr = [];
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length !== 1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加拍单商品";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getFsCourseProduct(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改拍单商品";
+        if (this.form.imgUrl != null) {
+          this.imageArr = this.form.imgUrl.split(",");
+        }
+        if (this.form.images != null) {
+          this.photoArr = this.form.images.split(",");
+        }
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateFsCourseProduct(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addFsCourseProduct(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除拍单商品编号为"' + ids + '"的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function () {
+        return delFsCourseProduct(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(() => { });
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有拍单商品数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.exportLoading = true;
+        return exportFsCourseProduct(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+        this.exportLoading = false;
+      }).catch(() => { });
+    }
+  }
+};
+</script>

+ 523 - 0
src/views/course/fsCourseProductOrder/index.vue

@@ -0,0 +1,523 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="订单编号" prop="orderCode">
+        <el-input
+          v-model="queryParams.orderCode"
+          placeholder="请输入订单编号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      
+      <el-form-item label="用户名称" prop="userName">
+        <el-input
+          v-model="queryParams.userName"
+          placeholder="请输入用户名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="用户电话" prop="userPhone">
+        <el-input
+          v-model="queryParams.userPhone"
+          placeholder="请输入用户电话"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+     
+      
+      
+      <el-form-item label="支付状态" prop="isPay">
+        <!-- <el-input
+          v-model="queryParams.isPay"
+          placeholder="请输入支付状态 0 待支付 1已支付"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        /> -->
+        <el-select v-model="queryParams.isPay" placeholder="请选择" clearable size="small">
+          <el-option label="待支付" value="0" />
+          <el-option label="已支付" value="1" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="支付时间" prop="payDateRange">
+        <el-date-picker
+          v-model="payDateRange"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="yyyy-MM-dd HH:mm:ss"
+          style="width: 240px"
+        />
+      </el-form-item>
+      <el-form-item label="订单状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择" clearable size="small">
+          <el-option label="待支付" value="1" />
+          <el-option label="已支付" value="2" />
+          <el-option label="已完成" value="3" />
+          <el-option label="申请退款" value="-1" />
+          <el-option label="已退款" value="-2" />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="退款时间" prop="refundDateRange">
+       <el-date-picker
+          v-model="refundDateRange"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          value-format="yyyy-MM-dd HH:mm:ss"
+          style="width: 240px"
+        />
+      </el-form-item>
+      
+     
+      
+      
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <!-- <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['fsCourseProductOrder:fsCourseProductOrder:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['fsCourseProductOrder:fsCourseProductOrder:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['fsCourseProductOrder:fsCourseProductOrder:remove']"
+        >删除</el-button>
+      </el-col> -->
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['course:fsCourseProductOrder:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="fsCourseProductOrderList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="订单编号" width="180px" align="center" prop="orderCode" />
+      <el-table-column label="用户名称" align="center" prop="userName" />
+      <el-table-column label="用户电话" width="180px" align="center" prop="userPhone" >
+        <template slot-scope="scope">
+          <span>{{ scope.row.userPhone }}<el-button icon="el-icon-search" size="mini" @click="handlePhone(scope)" style="margin-left: 20px;" circle v-hasPermi="['course:fsCourseProductOrder:queryPhone']"></el-button></span>
+        </template>
+      </el-table-column>
+      <el-table-column label="商品名称" align="center" prop="productName"/>
+      <el-table-column label="课程" align="center" :show-overflow-tooltip="true" prop="courseName" />
+      <el-table-column label="视频" align="center" :show-overflow-tooltip="true" prop="title" />
+      <el-table-column label="公司名称" align="center"  prop="companyName" />
+      <el-table-column label="销售" align="center"  prop="companyUserName" />  
+      <el-table-column label="企微外部联系人" align="center"  prop="extName" />      
+      <el-table-column label="支付状态" align="center" prop="isPay">
+        <template slot-scope="scope">
+          <el-tag v-if="scope.row.isPay == 0">待支付</el-tag>
+          <el-tag v-if="scope.row.isPay == 1" type="success">已支付</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="支付时间" align="center" prop="payTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.payTime, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="订单状态" align="center" prop="status">
+        <template slot-scope="scope">
+          <span v-if="scope.row.status === 1">待支付</span>
+          <span v-if="scope.row.status === 2">已支付</span>
+          <span v-if="scope.row.status === 3">已完成</span>
+          <span v-if="scope.row.status === -1">申请退款</span>
+          <span v-if="scope.row.status === -2">退款成功</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="申请退款时间" align="center" prop="refundTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.refundTime, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="申请退款理由" :show-overflow-tooltip="true" align="center" prop="refundExplain" />
+      <el-table-column label="核销码" align="center" prop="verifyCode" />
+      
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            :disabled="scope.row.status == 1 || scope.row.status == 3 || scope.row.status == -2"
+            size="mini"
+            type="text"
+            @click="handleRefund(scope.row)"
+            v-hasPermi="['course:fsCourseProductOrder:refund']"
+          >退款</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改拍单商品订单对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="订单编号" prop="orderCode">
+          <el-input v-model="form.orderCode" placeholder="请输入订单编号" />
+        </el-form-item>
+        <el-form-item label="用户id" prop="userId">
+          <el-input v-model="form.userId" placeholder="请输入用户id" />
+        </el-form-item>
+        <el-form-item label="用户名称" prop="userName">
+          <el-input v-model="form.userName" placeholder="请输入用户名称" />
+        </el-form-item>
+        <el-form-item label="用户电话" prop="userPhone">
+          <el-input v-model="form.userPhone" placeholder="请输入用户电话" />
+        </el-form-item>
+        <el-form-item label="拍单商品id" prop="courseProductId">
+          <el-input v-model="form.courseProductId" placeholder="请输入拍单商品id" />
+        </el-form-item>
+        <el-form-item label="商品json" prop="productJson">
+          <el-input v-model="form.productJson" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+        <el-form-item label="课程id" prop="courseId">
+          <el-input v-model="form.courseId" placeholder="请输入课程id" />
+        </el-form-item>
+        <el-form-item label="视频小节id" prop="videoId">
+          <el-input v-model="form.videoId" placeholder="请输入视频小节id" />
+        </el-form-item>
+        <el-form-item label="支付状态 0 待支付 1已支付" prop="isPay">
+          <el-input v-model="form.isPay" placeholder="请输入支付状态 0 待支付 1已支付" />
+        </el-form-item>
+        <el-form-item label="支付时间" prop="payTime">
+          <el-date-picker clearable size="small"
+            v-model="form.payTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择支付时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="支付方式 微信" prop="payType">
+          <el-select v-model="form.payType" placeholder="请选择支付方式 微信">
+            <el-option label="请选择字典生成" value="" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="1 待支付 2已支付 3 已完成 -1 申请退款 -2 : 退款成功">
+          <el-radio-group v-model="form.status">
+            <el-radio label="1">请选择字典生成</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="申请退款时间" prop="refundTime">
+          <el-date-picker clearable size="small"
+            v-model="form.refundTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择申请退款时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="申请退款理由" prop="refundExplain">
+          <el-input v-model="form.refundExplain" placeholder="请输入申请退款理由" />
+        </el-form-item>
+        <el-form-item label="核销码" prop="verifyCode">
+          <el-input v-model="form.verifyCode" placeholder="请输入核销码" />
+        </el-form-item>
+        <el-form-item label="公司id" prop="companyId">
+          <el-input v-model="form.companyId" placeholder="请输入公司id" />
+        </el-form-item>
+        <el-form-item label="销售id" prop="companyUserId">
+          <el-input v-model="form.companyUserId" placeholder="请输入销售id" />
+        </el-form-item>
+        <el-form-item label="企微外部联系人id" prop="extId">
+          <el-input v-model="form.extId" placeholder="请输入企微外部联系人id" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listFsCourseProductOrder, getFsCourseProductOrder, delFsCourseProductOrder, addFsCourseProductOrder, updateFsCourseProductOrder, exportFsCourseProductOrder, refund, getOrderUserPhone } from "@/api/course/fsCourseProductOrder";
+
+export default {
+  name: "FsCourseProductOrder",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 拍单商品订单表格数据
+      fsCourseProductOrderList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      payDateRange: [],
+      refundDateRange: [],
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        orderCode: null,
+        userId: null,
+        userName: null,
+        userPhone: null,
+        courseProductId: null,
+        productJson: null,
+        courseId: null,
+        videoId: null,
+        isPay: null,
+        payStartTime: null,
+        payEndTime: null,
+        payType: null,
+        status: null,
+        refundStartTime: null,
+        refundEndTime: null,
+        refundExplain: null,
+        verifyCode: null,
+        companyId: null,
+        companyUserId: null,
+        extId: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询拍单商品订单列表 */
+    getList() {
+      this.loading = true;
+      if (this.payDateRange && this.payDateRange.length === 2) {
+        this.queryParams.payStartTime = this.payDateRange[0];
+        this.queryParams.payEndTime = this.payDateRange[1].substring(0,10)+" 23:59:59";
+      } else {
+        this.queryParams.payStartTime = null;
+        this.queryParams.payEndTime = null;
+      }
+      if (this.refundDateRange && this.refundDateRange.length === 2) {
+        this.queryParams.refundStartTime = this.refundDateRange[0];
+        this.queryParams.refundEndTime = this.refundDateRange[1].substring(0,10)+" 23:59:59";
+      } else {
+        this.queryParams.refundStartTime = null;
+        this.queryParams.refundEndTime = null;
+      }
+      listFsCourseProductOrder(this.queryParams).then(response => {
+        this.fsCourseProductOrderList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        courseOrderId: null,
+        orderCode: null,
+        userId: null,
+        userName: null,
+        userPhone: null,
+        courseProductId: null,
+        productJson: null,
+        courseId: null,
+        videoId: null,
+        isPay: null,
+        payTime: null,
+        payType: null,
+        status: 0,
+        createTime: null,
+        refundTime: null,
+        refundExplain: null,
+        verifyCode: null,
+        updateTime: null,
+        companyId: null,
+        companyUserId: null,
+        extId: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.payDateRange = [];
+      this.refundDateRange = [];
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.courseOrderId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加拍单商品订单";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const courseOrderId = row.courseOrderId || this.ids
+      getFsCourseProductOrder(courseOrderId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改拍单商品订单";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.courseOrderId != null) {
+            updateFsCourseProductOrder(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addFsCourseProductOrder(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const courseOrderIds = row.courseOrderId || this.ids;
+      this.$confirm('是否确认删除拍单商品订单编号为"' + courseOrderIds + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delFsCourseProductOrder(courseOrderIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      if (this.payDateRange && this.payDateRange.length === 2) {
+        this.queryParams.payStartTime = this.payDateRange[0];
+        this.queryParams.payEndTime = this.payDateRange[1];
+      } else {
+        this.queryParams.payStartTime = null;
+        this.queryParams.payEndTime = null;
+      }
+      if (this.refundDateRange && this.refundDateRange.length === 2) {
+        this.queryParams.refundStartTime = this.refundDateRange[0];
+        this.queryParams.refundEndTime = this.refundDateRange[1];
+      } else {
+        this.queryParams.refundStartTime = null;
+        this.queryParams.refundEndTime = null;
+      }
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有拍单商品订单数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          this.exportLoading = true;
+          return exportFsCourseProductOrder(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+          this.exportLoading = false;
+        }).catch(() => {});
+    },
+
+    /**申请退款 */
+    handleRefund(row) {
+      const data = {
+        courseOrderId : row.courseOrderId
+      };
+       this.$confirm('是否确认拍商品退款?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          return refund(data);
+        }).then(response => {
+          this.getList();
+          this.msgSuccess("退款成功");
+        }).catch(() => {});
+    },
+
+    /**查询电话 */
+    handlePhone(scope) {
+      getOrderUserPhone(scope.row.courseOrderId).then(res=>{
+        scope.row.userPhone = res.userPhone
+      }) 
+    },
+  }
+};
+</script>

+ 3 - 4
src/views/course/userCoursePeriod/batchRedPacket.vue

@@ -24,7 +24,7 @@
         align="center"
       />
       <el-table-column
-        label="金额(0.1-0.3元)"
+        label="金额"
         align="center"
         width="200"
       >
@@ -32,7 +32,6 @@
           <el-input-number
             v-model="scope.row.amount"
             :min="0.1"
-            :max="0.3"
             :precision="2"
             :step="0.01"
             size="small"
@@ -96,9 +95,9 @@ export default {
     // 保存
     handleSave() {
       // 验证金额范围
-      const invalidItems = this.tableData.filter(item => item.amount < 0.1 || item.amount > 0.3);
+      const invalidItems = this.tableData.filter(item => item.amount < 0.1);
       if (invalidItems.length > 0) {
-        this.$message.error('红包金额需要在0.1元至0.3元之间');
+        this.$message.error('红包金额需要大于等于0.1元');
         return;
       }
 

+ 27 - 11
src/views/course/userCoursePeriod/index.vue

@@ -165,6 +165,7 @@
           <el-table-column label="营期名称" align="center" prop="periodName" />
           <el-table-column label="公司名称" align="center" prop="companyName" />
           <el-table-column label="营期状态" align="center" prop="periodStatus" width="100" :formatter="periodStatusFormatter" />
+          <el-table-column label="营期线" align="center" prop="periodLine" width="180" />
           <el-table-column label="开营开始时间" align="center" prop="periodStartingTime" width="180" />
           <el-table-column label="开营结束时间" align="center" prop="periodEndTime" width="180" />
           <el-table-column label="创建时间" align="center" prop="createTime" width="180" />
@@ -249,12 +250,12 @@
         <el-form-item label="课程LOGO" prop="courseLogo">
           <image-upload v-model="form.courseLogo" :limit="1" />
         </el-form-item>
-        <el-form-item label="红包发放方式" prop="redPacketGrantMethod">
-          <el-radio-group v-model="form.redPacketGrantMethod">
-            <el-radio :label="1" >按课程</el-radio>
-            <el-radio :label="2" >按营期</el-radio>
-          </el-radio-group>
-        </el-form-item>
+<!--        <el-form-item label="红包发放方式" prop="redPacketGrantMethod">-->
+<!--          <el-radio-group v-model="form.redPacketGrantMethod">-->
+<!--            <el-radio :label="1" >按课程</el-radio>-->
+<!--            <el-radio :label="2" >按营期</el-radio>-->
+<!--          </el-radio-group>-->
+<!--        </el-form-item>-->
         <el-form-item label="营期类型" prop="periodType">
           <el-radio-group v-model="form.periodType">
             <el-radio :label="1" >多课程</el-radio>
@@ -291,6 +292,21 @@
           >
           </el-date-picker>
         </el-form-item>
+        <el-form-item prop="periodLine">
+          <span slot="label">
+            营期线
+            <el-tooltip content="营期首次播放课程的日期" placement="top">
+              <i class="el-icon-question" style="margin-left: 5px; color: #909399; cursor: help;"></i>
+            </el-tooltip>
+          </span>
+          <el-date-picker
+            v-model="form.periodLine"
+            type="date"
+            placeholder="请选择营期线"
+            value-format="yyyy-MM-dd"
+            :clearable="true">
+          </el-date-picker>
+        </el-form-item>
       </el-form>
       <div class="drawer-footer">
         <el-button type="primary" @click="submitForm">确 定</el-button>
@@ -704,9 +720,9 @@ export default {
         courseStyle: [
           { required: true, message: '课程风格不能为空', trigger: 'change' }
         ],
-        redPacketGrantMethod: [
-          { required: true, message: '红包发放方式不能为空', trigger: 'change' }
-        ],
+        // redPacketGrantMethod: [
+        //   { required: true, message: '红包发放方式不能为空', trigger: 'change' }
+        // ],
         periodType: [
           { required: true, message: '营期类型不能为空', trigger: 'change' }
         ],
@@ -1413,8 +1429,8 @@ export default {
       this.course.form = {
         periodId: this.course.queryParams.periodId,
         courseId: null,
-        timeRange: null,
-        joinTime: null,
+        timeRange: ['00:00:00', '23:59:59'],
+        joinTime: '23:59:59',
         videoIds: []
       };
       // 重置表单

+ 6 - 9
src/views/course/userCoursePeriod/redPacket.vue

@@ -27,12 +27,11 @@
         <el-table-column label="课程" prop="courseName" align="center" />
         <el-table-column label="小节" prop="videoName" align="center" />
         <el-table-column label="营期日期" prop="dayDate" align="center"/>
-        <el-table-column label="红包金额(0.0-0.3元)" width="200px" align="center">
+        <el-table-column label="红包金额" width="200px" align="center">
           <template slot-scope="scope">
             <el-input-number
               v-model="scope.row.amount"
-              :min="0.0"
-              :max="0.3"
+              :min="0.1"
               :precision="2"
               :step="0.01"
               size="small"
@@ -129,27 +128,25 @@ export default {
         periodId: this.periodId,
         companyId: this.currentCompany.companyId
       }).then(response => {
-        console.log("-----------",JSON.stringify(response.data))  
         this.redPacketList = (response.data || []).map(item => ({
           ...item,
-          // amount: item.amount || 0.1
-          amount:item.amount ?? 0.1
+          amount: item.amount || 0.1
         }));
       });
     },
     // 保存红包金额
     handleSave() {
       // 筛选出有金额的项目
-      const validAmountItems = this.redPacketList.filter(item => item.amount >= 0);
+      const validAmountItems = this.redPacketList.filter(item => item.amount > 0);
       if (validAmountItems.length === 0) {
         this.$message.warning('请至少设置一个红包金额');
         return;
       }
 
       // 验证金额范围
-      const invalidItems = validAmountItems.filter(item => item.amount < 0.0 || item.amount > 0.3);
+      const invalidItems = validAmountItems.filter(item => item.amount < 0.1);
       if (invalidItems.length > 0) {
-        this.$message.error('红包金额需要在0.0元至0.3元之间');
+        this.$message.error('红包金额需要大于等于0.1元');
         return;
       }
 

+ 390 - 0
src/views/course/userWatchCourseStatistics/index.vue

@@ -0,0 +1,390 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+
+      <el-form-item label="营期名称" prop="periodName">
+        <el-input
+          v-model="queryParams.periodName"
+          placeholder="请输入营期名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="营期线" prop="periodStartingTime">
+        <el-date-picker clearable size="small"
+                        v-model="queryParams.periodStartingTime"
+                        type="date"
+                        value-format="yyyy-MM-dd"
+                        placeholder="选择营期线">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="播出时间" prop="courseStartDateTime">
+        <el-date-picker clearable size="small"
+                        v-model="queryParams.courseStartDateTime"
+                        type="date"
+                        value-format="yyyy-MM-dd"
+                        placeholder="选择课程开始日期">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="课程名称" prop="courseName">
+        <el-input
+          v-model="queryParams.courseName"
+          placeholder="请输入课程名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
+      <el-form-item label="销售公司" prop="companyName">
+        <el-input
+          v-model="queryParams.companyName"
+          placeholder="请输入销售公司名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
+      <el-form-item label="所属销售" prop="companyUserName">
+        <el-input
+          v-model="queryParams.companyUserName"
+          placeholder="请输入销售名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['course:userWatchCourseStatistics:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="userWatchCourseStatisticsList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="营期名称" align="center" prop="periodName" />
+      <el-table-column label="营期线" align="center" prop="periodStartingTime" />
+      <el-table-column label="播出时间" align="center" prop="courseStartDateTime" />
+      <el-table-column label="课程名称" align="center" prop="courseName" />
+      <el-table-column label="视频小节" align="center" prop="videoTitle" />
+      <el-table-column label="销售公司" align="center" prop="companyName" />
+      <el-table-column label="所属销售" align="center" prop="companyUserName" />
+      <el-table-column label="新增会员" align="center" prop="newUserNum" />
+      <el-table-column label="会员数量" align="center" prop="userNum" />
+      <el-table-column label="观看人数" align="center" prop="watchNum" />
+      <el-table-column label="上线率" align="center" prop="onlineRatePercent" />
+      <el-table-column label="完播人数" align="center" prop="completeWatchNum" />
+      <el-table-column label="完播率" align="center" prop="completeWatchRatePercent" />
+      <el-table-column label="答题人数" align="center" prop="answerNum" />
+      <el-table-column label="正确人数" align="center" prop="answerRightNum" />
+      <el-table-column label="正确率" align="center" prop="answerRightRatePercent" />
+      <el-table-column label="红包领取个数" align="center" prop="redPacketNum" />
+      <el-table-column label="红包领取总额" align="center" prop="redPacketAmount" />
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改会员看课统计-按课程统计对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="营期id" prop="periodId">
+          <el-input v-model="form.periodId" placeholder="请输入营期id" />
+        </el-form-item>
+        <el-form-item label="营期名称" prop="periodName">
+          <el-input v-model="form.periodName" placeholder="请输入营期名称" />
+        </el-form-item>
+        <el-form-item label="课程id" prop="courseId">
+          <el-input v-model="form.courseId" placeholder="请输入课程id" />
+        </el-form-item>
+        <el-form-item label="课程名称" prop="courseName">
+          <el-input v-model="form.courseName" placeholder="请输入课程名称" />
+        </el-form-item>
+        <el-form-item label="视频id" prop="videoId">
+          <el-input v-model="form.videoId" placeholder="请输入视频id" />
+        </el-form-item>
+        <el-form-item label="视频标题" prop="videoTitle">
+          <el-input v-model="form.videoTitle" placeholder="请输入视频标题" />
+        </el-form-item>
+        <el-form-item label="销售公司id" prop="companyId">
+          <el-input v-model="form.companyId" placeholder="请输入销售公司id" />
+        </el-form-item>
+        <el-form-item label="销售公司名称" prop="companyName">
+          <el-input v-model="form.companyName" placeholder="请输入销售公司名称" />
+        </el-form-item>
+        <el-form-item label="销售id" prop="companyUserId">
+          <el-input v-model="form.companyUserId" placeholder="请输入销售id" />
+        </el-form-item>
+        <el-form-item label="课程开始日期" prop="courseStartDateTime">
+          <el-date-picker clearable size="small"
+            v-model="form.courseStartDateTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择课程开始日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="销售名称" prop="companyUserName">
+          <el-input v-model="form.companyUserName" placeholder="请输入销售名称" />
+        </el-form-item>
+        <el-form-item label="营期开始日期" prop="periodStartingTime">
+          <el-date-picker clearable size="small"
+            v-model="form.periodStartingTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择营期开始日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="新增会员数量" prop="newUserNum">
+          <el-input v-model="form.newUserNum" placeholder="请输入新增会员数量" />
+        </el-form-item>
+        <el-form-item label="会员数量" prop="userNum">
+          <el-input v-model="form.userNum" placeholder="请输入会员数量" />
+        </el-form-item>
+        <el-form-item label="观看人数" prop="watchNum">
+          <el-input v-model="form.watchNum" placeholder="请输入观看人数" />
+        </el-form-item>
+        <el-form-item label="完播人数" prop="completeWatchNum">
+          <el-input v-model="form.completeWatchNum" placeholder="请输入完播人数" />
+        </el-form-item>
+        <el-form-item label="完播率" prop="completeWatchRate">
+          <el-input v-model="form.completeWatchRate" placeholder="请输入完播率" />
+        </el-form-item>
+        <el-form-item label="答题人数" prop="answerNum">
+          <el-input v-model="form.answerNum" placeholder="请输入答题人数" />
+        </el-form-item>
+        <el-form-item label="答题正确人数" prop="answerRightNum">
+          <el-input v-model="form.answerRightNum" placeholder="请输入答题正确人数" />
+        </el-form-item>
+        <el-form-item label="答题正确率" prop="answerRightRate">
+          <el-input v-model="form.answerRightRate" placeholder="请输入答题正确率" />
+        </el-form-item>
+        <el-form-item label="红包领取个数" prop="redPacketNum">
+          <el-input v-model="form.redPacketNum" placeholder="请输入红包领取数量" />
+        </el-form-item>
+        <el-form-item label="红包领取总额" prop="redPacketAmount">
+          <el-input v-model="form.redPacketAmount" placeholder="请输入红包领取总额" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listUserWatchCourseStatistics, getUserWatchCourseStatistics, delUserWatchCourseStatistics, addUserWatchCourseStatistics, updateUserWatchCourseStatistics, exportUserWatchCourseStatistics } from "@/api/course/userWatchCourseStatistics";
+
+export default {
+  name: "UserWatchCourseStatistics",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 会员看课统计-按课程统计表格数据
+      userWatchCourseStatisticsList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        periodId: null,
+        periodName: null,
+        courseId: null,
+        courseName: null,
+        videoId: null,
+        videoTitle: null,
+        companyId: null,
+        companyName: null,
+        companyUserId: null,
+        courseStartDateTime: null,
+        companyUserName: null,
+        periodStartingTime: null,
+        newUserNum: null,
+        userNum: null,
+        watchNum: null,
+        completeWatchNum: null,
+        completeWatchRate: null,
+        answerNum: null,
+        answerRightNum: null,
+        answerRightRate: null,
+        redPacketNum: null,
+        redPacketAmount: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询会员看课统计-按课程统计列表 */
+    getList() {
+      this.loading = true;
+      listUserWatchCourseStatistics(this.queryParams).then(response => {
+        this.userWatchCourseStatisticsList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        periodId: null,
+        periodName: null,
+        courseId: null,
+        courseName: null,
+        videoId: null,
+        videoTitle: null,
+        companyId: null,
+        companyName: null,
+        companyUserId: null,
+        courseStartDateTime: null,
+        companyUserName: null,
+        periodStartingTime: null,
+        newUserNum: null,
+        userNum: null,
+        watchNum: null,
+        completeWatchNum: null,
+        completeWatchRate: null,
+        answerNum: null,
+        answerRightNum: null,
+        answerRightRate: null,
+        redPacketNum: null,
+        redPacketAmount: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加会员看课统计-按课程统计";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getUserWatchCourseStatistics(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改会员看课统计-按课程统计";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateUserWatchCourseStatistics(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addUserWatchCourseStatistics(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除会员看课统计-按课程统计编号为"' + ids + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delUserWatchCourseStatistics(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出当前数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          this.exportLoading = true;
+          return exportUserWatchCourseStatistics(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+          this.exportLoading = false;
+        }).catch(() => {});
+    }
+  }
+};
+</script>

+ 394 - 0
src/views/course/userWatchCourseTotalStatistics/index.vue

@@ -0,0 +1,394 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+
+      <el-form-item label="营期名称" prop="periodName">
+        <el-input
+          v-model="queryParams.periodName"
+          placeholder="请输入营期名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="营期线" prop="periodStartingTime">
+        <el-date-picker clearable size="small"
+                        v-model="queryParams.periodStartingTime"
+                        type="date"
+                        value-format="yyyy-MM-dd"
+                        placeholder="选择营期线">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="播出时间" prop="courseStartDateTime">
+        <el-date-picker clearable size="small"
+                        v-model="queryParams.courseStartDateTime"
+                        type="date"
+                        value-format="yyyy-MM-dd"
+                        placeholder="选择课程开始日期">
+        </el-date-picker>
+      </el-form-item>
+      <el-form-item label="课程名称" prop="courseName">
+        <el-input
+          v-model="queryParams.courseName"
+          placeholder="请输入课程名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="视频小节" prop="videoTitle">
+        <el-input
+          v-model="queryParams.videoTitle"
+          placeholder="请输入视频标题"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
+      <el-form-item label="销售公司" prop="companyName">
+        <el-input
+          v-model="queryParams.companyName"
+          placeholder="请输入销售公司名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
+<!--      <el-form-item label="所属销售" prop="companyUserName">-->
+<!--        <el-input-->
+<!--          v-model="queryParams.companyUserName"-->
+<!--          placeholder="请输入销售名称"-->
+<!--          clearable-->
+<!--          size="small"-->
+<!--          @keyup.enter.native="handleQuery"-->
+<!--        />-->
+<!--      </el-form-item>-->
+
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="userWatchCourseStatisticsList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="营期名称" align="center" prop="periodName" />
+      <el-table-column label="营期线" align="center" prop="periodStartingTime" />
+      <el-table-column label="播出时间" align="center" prop="courseStartDateTime" />
+      <el-table-column label="课程名称" align="center" prop="courseName" />
+      <el-table-column label="视频小节" align="center" prop="videoTitle" />
+      <el-table-column label="销售公司" align="center" prop="companyName" />
+<!--      <el-table-column label="所属销售" align="center" prop="companyUserName" />-->
+      <el-table-column label="新增会员" align="center" prop="newUserNum" />
+      <el-table-column label="会员数量" align="center" prop="userNum" />
+      <el-table-column label="观看人数" align="center" prop="watchNum" />
+      <el-table-column label="上线率" align="center" prop="onlineRatePercent" />
+      <el-table-column label="完播人数" align="center" prop="completeWatchNum" />
+      <el-table-column label="完播率" align="center" prop="completeWatchRatePercent" />
+      <el-table-column label="红包领取个数" align="center" prop="redPacketNum" />
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改会员看课统计-按课程统计对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="营期id" prop="periodId">
+          <el-input v-model="form.periodId" placeholder="请输入营期id" />
+        </el-form-item>
+        <el-form-item label="营期名称" prop="periodName">
+          <el-input v-model="form.periodName" placeholder="请输入营期名称" />
+        </el-form-item>
+        <el-form-item label="课程id" prop="courseId">
+          <el-input v-model="form.courseId" placeholder="请输入课程id" />
+        </el-form-item>
+        <el-form-item label="课程名称" prop="courseName">
+          <el-input v-model="form.courseName" placeholder="请输入课程名称" />
+        </el-form-item>
+        <el-form-item label="视频id" prop="videoId">
+          <el-input v-model="form.videoId" placeholder="请输入视频id" />
+        </el-form-item>
+        <el-form-item label="视频标题" prop="videoTitle">
+          <el-input v-model="form.videoTitle" placeholder="请输入视频标题" />
+        </el-form-item>
+        <el-form-item label="销售公司id" prop="companyId">
+          <el-input v-model="form.companyId" placeholder="请输入销售公司id" />
+        </el-form-item>
+        <el-form-item label="销售公司名称" prop="companyName">
+          <el-input v-model="form.companyName" placeholder="请输入销售公司名称" />
+        </el-form-item>
+        <el-form-item label="销售id" prop="companyUserId">
+          <el-input v-model="form.companyUserId" placeholder="请输入销售id" />
+        </el-form-item>
+        <el-form-item label="课程开始日期" prop="courseStartDateTime">
+          <el-date-picker clearable size="small"
+            v-model="form.courseStartDateTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择课程开始日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="销售名称" prop="companyUserName">
+          <el-input v-model="form.companyUserName" placeholder="请输入销售名称" />
+        </el-form-item>
+        <el-form-item label="营期开始日期" prop="periodStartingTime">
+          <el-date-picker clearable size="small"
+            v-model="form.periodStartingTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择营期开始日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="新增会员数量" prop="newUserNum">
+          <el-input v-model="form.newUserNum" placeholder="请输入新增会员数量" />
+        </el-form-item>
+        <el-form-item label="会员数量" prop="userNum">
+          <el-input v-model="form.userNum" placeholder="请输入会员数量" />
+        </el-form-item>
+        <el-form-item label="观看人数" prop="watchNum">
+          <el-input v-model="form.watchNum" placeholder="请输入观看人数" />
+        </el-form-item>
+        <el-form-item label="完播人数" prop="completeWatchNum">
+          <el-input v-model="form.completeWatchNum" placeholder="请输入完播人数" />
+        </el-form-item>
+        <el-form-item label="完播率" prop="completeWatchRate">
+          <el-input v-model="form.completeWatchRate" placeholder="请输入完播率" />
+        </el-form-item>
+        <el-form-item label="答题人数" prop="answerNum">
+          <el-input v-model="form.answerNum" placeholder="请输入答题人数" />
+        </el-form-item>
+        <el-form-item label="答题正确人数" prop="answerRightNum">
+          <el-input v-model="form.answerRightNum" placeholder="请输入答题正确人数" />
+        </el-form-item>
+        <el-form-item label="答题正确率" prop="answerRightRate">
+          <el-input v-model="form.answerRightRate" placeholder="请输入答题正确率" />
+        </el-form-item>
+        <el-form-item label="红包领取个数" prop="redPacketNum">
+          <el-input v-model="form.redPacketNum" placeholder="请输入红包领取数量" />
+        </el-form-item>
+        <el-form-item label="红包领取总额" prop="redPacketAmount">
+          <el-input v-model="form.redPacketAmount" placeholder="请输入红包领取总额" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listUserWatchCourseStatisticsTotal, getUserWatchCourseStatistics, delUserWatchCourseStatistics, addUserWatchCourseStatistics, updateUserWatchCourseStatistics, exportUserWatchCourseStatisticsTotal } from "@/api/course/userWatchCourseStatistics";
+
+export default {
+  name: "UserWatchCourseStatistics",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 会员看课统计-按课程统计表格数据
+      userWatchCourseStatisticsList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        periodId: null,
+        periodName: null,
+        courseId: null,
+        courseName: null,
+        videoId: null,
+        videoTitle: null,
+        companyId: null,
+        companyName: null,
+        companyUserId: null,
+        courseStartDateTime: null,
+        companyUserName: null,
+        periodStartingTime: null,
+        newUserNum: null,
+        userNum: null,
+        watchNum: null,
+        completeWatchNum: null,
+        completeWatchRate: null,
+        answerNum: null,
+        answerRightNum: null,
+        answerRightRate: null,
+        redPacketNum: null,
+        redPacketAmount: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询会员看课统计-按课程统计列表 */
+    getList() {
+      this.loading = true;
+      listUserWatchCourseStatisticsTotal(this.queryParams).then(response => {
+        this.userWatchCourseStatisticsList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        periodId: null,
+        periodName: null,
+        courseId: null,
+        courseName: null,
+        videoId: null,
+        videoTitle: null,
+        companyId: null,
+        companyName: null,
+        companyUserId: null,
+        courseStartDateTime: null,
+        companyUserName: null,
+        periodStartingTime: null,
+        newUserNum: null,
+        userNum: null,
+        watchNum: null,
+        completeWatchNum: null,
+        completeWatchRate: null,
+        answerNum: null,
+        answerRightNum: null,
+        answerRightRate: null,
+        redPacketNum: null,
+        redPacketAmount: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加会员看课统计-按课程统计";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getUserWatchCourseStatistics(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改会员看课统计-按课程统计";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateUserWatchCourseStatistics(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addUserWatchCourseStatistics(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除会员看课统计-按课程统计编号为"' + ids + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delUserWatchCourseStatistics(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出当前数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          this.exportLoading = true;
+          return exportUserWatchCourseStatisticsTotal(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+          this.exportLoading = false;
+        }).catch(() => {});
+    }
+  }
+};
+</script>

+ 286 - 0
src/views/course/userWatchStatistics/index.vue

@@ -0,0 +1,286 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+
+      <el-form-item label="营期名称" prop="periodName">
+        <el-input
+          v-model="queryParams.periodName"
+          placeholder="请输入营期名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="营期线" prop="periodStartingTime">
+        <el-date-picker clearable size="small"
+          v-model="queryParams.periodStartingTime"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择营期线">
+        </el-date-picker>
+      </el-form-item>
+
+      <el-form-item label="销售公司" prop="companyName">
+        <el-input
+          v-model="queryParams.companyName"
+          placeholder="请输入销售公司名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
+
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['course:userWatchStatistics:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="userWatchStatisticsList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="营期名称" align="center" prop="periodName" />
+      <el-table-column label="营期线" align="center" prop="periodStartingTime" width="180">
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.periodStartingTime, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="销售公司" align="center" prop="companyName" />
+      <el-table-column label="新增会员" align="center" prop="newUserNum" />
+      <el-table-column label="会员数量" align="center" prop="userNum" />
+      <el-table-column label="观看人数" align="center" prop="watchNum" />
+      <el-table-column label="上线率" align="center" prop="onlineRatePercent" />
+      <el-table-column label="完播人数" align="center" prop="completeWatchNum" />
+      <el-table-column label="完播率" align="center" prop="completeWatchRatePercent" />
+
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改会员看课统计-按营期统计对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="营期id" prop="periodId">
+          <el-input v-model="form.periodId" placeholder="请输入营期id" />
+        </el-form-item>
+        <el-form-item label="营期名称" prop="periodName">
+          <el-input v-model="form.periodName" placeholder="请输入营期名称" />
+        </el-form-item>
+        <el-form-item label="营期开始日期" prop="periodStartingTime">
+          <el-date-picker clearable size="small"
+            v-model="form.periodStartingTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择营期开始日期">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="新增会员数量" prop="newUserNum">
+          <el-input v-model="form.newUserNum" placeholder="请输入新增会员数量" />
+        </el-form-item>
+        <el-form-item label="会员数量" prop="userNum">
+          <el-input v-model="form.userNum" placeholder="请输入会员数量" />
+        </el-form-item>
+        <el-form-item label="观看人数" prop="watchNum">
+          <el-input v-model="form.watchNum" placeholder="请输入观看人数" />
+        </el-form-item>
+        <el-form-item label="完播人数" prop="completeWatchNum">
+          <el-input v-model="form.completeWatchNum" placeholder="请输入完播人数" />
+        </el-form-item>
+        <el-form-item label="完播率" prop="completeWatchRate">
+          <el-input v-model="form.completeWatchRate" placeholder="请输入完播率" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listUserWatchStatistics, getUserWatchStatistics, delUserWatchStatistics, addUserWatchStatistics, updateUserWatchStatistics, exportUserWatchStatistics } from "@/api/course/userWatchStatistics";
+
+export default {
+  name: "UserWatchStatistics",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 会员看课统计-按营期统计表格数据
+      userWatchStatisticsList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        periodId: null,
+        periodName: null,
+        periodStartingTime: null,
+        companyName: null,
+        newUserNum: null,
+        userNum: null,
+        watchNum: null,
+        completeWatchNum: null,
+        completeWatchRate: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询会员看课统计-按营期统计列表 */
+    getList() {
+      this.loading = true;
+      listUserWatchStatistics(this.queryParams).then(response => {
+        this.userWatchStatisticsList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        periodId: null,
+        periodName: null,
+        periodStartingTime: null,
+        newUserNum: null,
+        userNum: null,
+        watchNum: null,
+        completeWatchNum: null,
+        completeWatchRate: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加会员看课统计-按营期统计";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getUserWatchStatistics(id).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改会员看课统计-按营期统计";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.id != null) {
+            updateUserWatchStatistics(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addUserWatchStatistics(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除会员看课统计-按营期统计编号为"' + ids + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delUserWatchStatistics(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出当前数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          this.exportLoading = true;
+          return exportUserWatchStatistics(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+          this.exportLoading = false;
+        }).catch(() => {});
+    }
+  }
+};
+</script>

+ 42 - 2
src/views/his/package/index.vue

@@ -81,6 +81,16 @@
           />
         </el-select>
       </el-form-item>
+      <el-form-item label="节气" prop="solarTerm" >
+        <el-select v-model="queryParams.solarTerm" placeholder="请选择">
+          <el-option
+            v-for="dict in solarTermOptions"
+            :key="dict.value"
+            :label="dict.label"
+            :value="parseInt(dict.value)"
+          />
+        </el-select>
+      </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
         <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@@ -171,6 +181,11 @@
           <dict-tag :options="orOptions" :value="scope.row.isShow"/>
         </template>
       </el-table-column>
+      <el-table-column label="节气" align="center" prop="solarTerm" width="75px">
+        <template slot-scope="scope">
+          <el-tag v-if="scope.row.solarTerm">{{getSolarTermLabel(scope.row.solarTerm)}}</el-tag>
+        </template>
+      </el-table-column>
       <el-table-column label="创建时间" align="center" prop="createTime" width="180px"/>
       <el-table-column label="更改时间" align="center" prop="updateTime" width="180px"/>
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="180px">
@@ -503,6 +518,16 @@
             </el-option>
           </el-select>
         </el-form-item>
+        <el-form-item label="节气" prop="solarTerm">
+          <el-select v-model="form.solarTerm" placeholder="请选择节气" clearable size="small">
+            <el-option
+              v-for="dict in solarTermOptions"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            />
+          </el-select>
+        </el-form-item>
         <el-form-item label="随访模板" prop="followTempId">
           <el-select v-model="form.followTempId" placeholder="请选择模板" clearable size="small">
                   <el-option
@@ -595,6 +620,7 @@ import { getToken } from "@/utils/auth";
 import Material from '@/components/Material'
 import ImageUpload from '@/components/ImageUpload'
 import { Loading } from 'element-ui';
+import { getOptions } from '@/api/his/packageSolarTerm'
 export default {
   name: "Package",
   components: { packageDetails,Editor,productAttrValueSelect,Material },
@@ -691,6 +717,7 @@ export default {
       // 是否删除字典
       isDelOptions: [],
       packageSubTypeOptions:[],
+      solarTermOptions: [],
       photoArr:[],
       // 查询参数
       queryParams: {
@@ -700,7 +727,8 @@ export default {
         sort: null,
         productJson: null,
         status: null,
-        isDel: null
+        isDel: null,
+        solarTerm: null,
       },
 
       // 表单参数
@@ -779,11 +807,23 @@ export default {
       this.privateTypeOptions = response.data.privateType;
     });
     this.getTemp();
+    this.getSolarTermOptions()
     listStore().then(response => {
       this.storeOPtions = response.rows;
     });
   },
   methods: {
+    getSolarTermLabel(solarTerm) {
+      if (solarTerm) {
+        return this.solarTermOptions.find(item => item.value === solarTerm)?.label || '-'
+      }
+      return '-'
+    },
+    getSolarTermOptions() {
+      getOptions().then(response => {
+        this.solarTermOptions = response.data;
+      })
+    },
     handleUpdateMore(row){
       this.reset1();
       this.title = "批量修改套餐状态";
@@ -1259,7 +1299,7 @@ export default {
      color: #8c939d;
      width: 150px;
      height: 150px;
-     line-height: 150px;
+     line-height: 150px !important;
      text-align: center;
    }
 </style>

+ 336 - 0
src/views/his/packageSolarTerm/index.vue

@@ -0,0 +1,336 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
+      <el-form-item label="节气名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入套餐包名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="状态" prop="status">
+        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
+          <el-option
+            v-for="dict in statusOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['his:packageSolarTerm:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['his:packageSolarTerm:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['his:packageSolarTerm:remove']"
+        >删除</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table height="600" v-loading="loading" border :data="solarTermList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id"/>
+      <el-table-column label="节气名称" align="center" prop="name" />
+      <el-table-column label="开始时间" align="center" prop="startTime" width="180"/>
+      <el-table-column label="结束时间" align="center" prop="endTime" width="180"/>
+      <el-table-column label="节气简介" align="center" prop="desc" width="300">
+        <template slot-scope="scope">
+          <el-tooltip class="item" effect="dark" :content="scope.row.desc" placement="bottom-start">
+            <div style="overflow: hidden;white-space: nowrap;text-overflow: ellipsis;">
+              {{ scope.row.desc }}
+            </div>
+          </el-tooltip>
+        </template>
+      </el-table-column>
+      <el-table-column label="排序" align="center" prop="sort"/>
+      <el-table-column label="状态" align="center" prop="status">
+        <template slot-scope="scope">
+          <dict-tag :options="statusOptions" :value="scope.row.status"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" prop="createTime" width="180"/>
+      <el-table-column label="更改时间" align="center" prop="updateTime" width="180"/>
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-edit"
+            @click="handleUpdate(scope.row)"
+            v-hasPermi="['his:packageSolarTerm:edit']"
+          >修改</el-button>
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['his:packageSolarTerm:remove']"
+          >删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改套餐包对话框 -->
+    <el-dialog :title="addOrUpdateDialog.title" :visible.sync="addOrUpdateDialog.open" width="1000px" append-to-body>
+      <el-form ref="form" :model="addOrUpdateDialog.form" :rules="addOrUpdateDialog.rules" label-width="110px">
+        <el-form-item label="节气名称" prop="name">
+          <el-input v-model="addOrUpdateDialog.form.name" placeholder="请输入节气名称" />
+        </el-form-item>
+        <el-form-item label="开始时间" prop="startTime">
+          <el-date-picker
+            v-model="addOrUpdateDialog.form.startTime"
+            type="datetime"
+            value-format="yyyy-MM-dd HH:mm:ss"
+            placeholder="选择开始时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="结束时间" prop="endTime">
+          <el-date-picker
+            v-model="addOrUpdateDialog.form.endTime"
+            type="datetime"
+            value-format="yyyy-MM-dd HH:mm:ss"
+            placeholder="选择结束时间">
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="节气简介" prop="desc">
+          <el-input
+            type="textarea"
+            :rows="5"
+            v-model="addOrUpdateDialog.form.desc"
+            placeholder="请输入节气简介" />
+        </el-form-item>
+        <el-form-item label="排序" prop="sort">
+          <el-input-number :min="0" v-model="addOrUpdateDialog.form.sort" placeholder="请输入排序" />
+        </el-form-item>
+        <el-form-item label="状态" prop="status">
+          <el-select v-model="addOrUpdateDialog.form.status" placeholder="请选择状态">
+            <el-option
+              v-for="dict in statusOptions"
+              :key="dict.dictValue"
+              :label="dict.dictLabel"
+              :value="dict.dictValue"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+
+  </div>
+</template>
+
+<script>
+
+import {
+  addPackageSolarTerm,
+  delPackageSolarTerm,
+  getPackageSolarTerm,
+  listPackageSolarTerm,
+  updatePackageSolarTerm
+} from '@/api/his/packageSolarTerm'
+
+export default {
+  name: 'solarTerm',
+  data() {
+    return {
+      showSearch: true,
+      statusOptions: [],
+      multiple: true,
+      single: true,
+      solarTermIds: [],
+      loading: true,
+      queryParams: {
+        name: null,
+        status: null
+      },
+      solarTermList: [],
+      total: 0,
+      addOrUpdateDialog: {
+        open: false,
+        title: null,
+        form: {
+          id: null,
+          name: null,
+          startTime: null,
+          endTime: null,
+          desc: null,
+          sort: null,
+          status: "1",
+        },
+        rules: {
+          name: [
+            { required: true, message: '请输入节气名称', trigger: 'blur' }
+          ],
+          startTime: [
+            { required: true, message: '请输入开始时间', trigger: 'blur' }
+          ],
+          endTime: [
+            { required: true, message: '请输入结束时间', trigger: 'blur' }
+          ],
+          desc: []
+        }
+      }
+    }
+  },
+  created() {
+    this.getDicts("solar_Term_status").then(response => {
+      this.statusOptions = response.data;
+    });
+    this.getList();
+  },
+  methods: {
+    getList() {
+      this.loading = true;
+      listPackageSolarTerm(this.queryParams).then(response => {
+        const {code, rows, total, msg} = response
+        if (code === 200) {
+          this.solarTermList = rows
+          this.total = total
+          this.loading = false
+          return
+        }
+        this.msgError(msg)
+      });
+    },
+    handleAdd() {
+      this.reset()
+      this.addOrUpdateDialog.title = "添加节气";
+      this.addOrUpdateDialog.open = true;
+    },
+
+    handleUpdate(row) {
+      this.reset()
+      const id = row.id || this.solarTermIds
+      getPackageSolarTerm(id).then(response => {
+        this.addOrUpdateDialog.form = response.data;
+        this.addOrUpdateDialog.form.status = response.data.status?.toString();
+        this.addOrUpdateDialog.title = "修改节气";
+        this.addOrUpdateDialog.open = true;
+      })
+    },
+    handleDelete(row) {
+      const ids = row.id || this.solarTermIds;
+      this.$confirm('是否确认删除节气编号为"' + ids + '"的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+        return delPackageSolarTerm(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(() => {});
+    },
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.getList()
+    },
+    handleSelectionChange(selection) {
+      this.solarTermIds = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (!valid) {
+          return
+        }
+
+        if (this.addOrUpdateDialog.form.id != null) {
+          updatePackageSolarTerm(this.addOrUpdateDialog.form).then(response => {
+            const {code,msg} = response
+            if (code !== 200) {
+              this.msgError(msg)
+              return
+            }
+            this.msgSuccess("修改成功");
+            this.addOrUpdateDialog.open = false;
+            this.getList();
+          });
+          return
+        }
+
+        addPackageSolarTerm(this.addOrUpdateDialog.form).then(response => {
+          const {code,msg} = response
+          if (code !== 200) {
+            this.msgError(msg)
+            return
+          }
+          this.msgSuccess("新增成功");
+          this.addOrUpdateDialog.open = false;
+          this.getList();
+        });
+      });
+    },
+    cancel() {
+      this.addOrUpdateDialog.open = false;
+      this.reset();
+    },
+    reset() {
+      this.addOrUpdateDialog.form = {
+        name: null,
+        startTime: null,
+        endTime: null,
+        desc: null,
+        sort: null,
+        status: "1",
+      };
+      this.resetForm("form");
+    },
+  },
+}
+</script>
+
+<style scoped>
+
+</style>

+ 2 - 2
src/views/his/storeOrder/order1.vue

@@ -1243,7 +1243,7 @@ export default {
     // 设置erp账户
     showErpAccountSetDialog() {
       this.erpAccountDialog.open = true;
-      this.erpAccountDialog.loading = true;
+      // this.erpAccountDialog.loading = true;
       this.erpSettingType = 'set'
       // this.getErpAccountList();
       this.calculateOrderSummary();
@@ -1251,7 +1251,7 @@ export default {
     //显示ERP账户选择对话框
     showErpAccountDialog() {
       this.erpAccountDialog.open = true;
-      this.erpAccountDialog.loading = true;
+      // this.erpAccountDialog.loading = true;
       this.erpSettingType = 'push'
       // this.getErpAccountList();
       this.calculateOrderSummary();

+ 44 - 2
src/views/his/storeProduct/index.vue

@@ -344,6 +344,22 @@
            <el-form-item label="轮播图" prop="images">
              <Material v-model="photoArr" type="image" :num="10" :width="150" :height="150" />
            </el-form-item>
+            <el-form-item label="商品视频" prop="video">
+          <div>
+            <el-upload
+              ref="uploadVideo"
+              class="upload-demo"
+              :action="uploadUrl"
+              :on-success="handleSuccess"
+              :before-upload="beforeUpload"
+              :limit="1"
+              accept="video/*"
+            >
+              <el-button size="small" type="primary">点击上传视频</el-button>
+            </el-upload>
+            <video v-if="form.videoUrl" :src="form.videoUrl" controls style="max-width: 300px; max-height: 300px; margin-top: 10px"></video>
+          </div>
+        </el-form-item>
           <el-form-item label="规格" prop="specType">
              <el-radio-group v-model="form.specType" >
                <el-radio :label="0" class="radio">单规格</el-radio>
@@ -846,7 +862,8 @@ export default {
       isDrug: [
          { required: true, message: "不能为空", trigger: "blur" }
        ],
-      }
+      },
+      myloading:null
     };
   },
   created() {
@@ -873,6 +890,31 @@ export default {
     });
   },
   methods: {
+    //上传成功
+     handleSuccess(response, file) {
+      // 上传成功后的回调函数
+      this.myloading.close();
+      this.form.videoUrl = response.url;
+      this.$refs.uploadVideo.clearFiles();
+    },
+    beforeUpload(file) {
+      // 上传前的钩子函数,可以在这里对文件进行处理
+      // 返回 false 则取消上传
+
+      // 例如限制文件大小
+      const isLt2M = file.size / 1024 / 1024 < 200;
+      if (!isLt2M) {
+        this.$message.error('上传视频文件大小不能超过 200MB!');
+        return false;
+      }
+      this.myloading = this.$loading({
+        lock: true,
+        text: '上传中',
+        spinner: 'el-icon-loading',
+        background: 'rgba(0, 0, 0, 0.7)'
+      });
+
+    },
     handleUpdatePrice(){
       this.priceOpen=true;
     },
@@ -1061,6 +1103,7 @@ export default {
         doctorBrokerage:null,
         imgUrl: null,
         images: null,
+        videoUrl: null,
         productName: null,
         productIntroduce: null,
         keyword: null,
@@ -1261,7 +1304,6 @@ export default {
             return this.$message.warning('请点击生成规格!');
           }
 
-
           addOrEdit(this.form).then(response => {
             if (response.code === 200) {
               this.msgSuccess("操作成功");

+ 3 - 2
src/views/his/user/index.vue

@@ -319,7 +319,8 @@ export default {
         sTime:null,
         eTime:null,
         isBuy:null,
-        source:null
+        source:null,
+        companyName: null,
       },
       // 表单参数
       form: {},
@@ -563,7 +564,7 @@ export default {
     /** 导出按钮操作 */
     handleExport() {
       const queryParams = this.queryParams;
-      this.$confirm('是否确认导出所有用户数据项?', "警告", {
+      this.$confirm('是否确认导出当前用户数据项?', "警告", {
           confirmButtonText: "确定",
           cancelButtonText: "取消",
           type: "warning"

+ 400 - 0
src/views/his/userOnlineState/index.vue

@@ -0,0 +1,400 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="用户昵称" prop="nickname">
+        <el-input
+          v-model="queryParams.nickname"
+          placeholder="请输入用户昵称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="手机号码" prop="phone">
+        <el-input
+          v-model="queryParams.phone"
+          placeholder="请输入手机号码"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="所属公司" prop="companyName">
+        <el-input
+          v-model="queryParams.companyName"
+          placeholder="请输入所属公司"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="所属销售" prop="companyUserNickName">
+        <el-input
+          v-model="queryParams.companyUserName"
+          placeholder="请输入所属销售"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+<!--      <el-col :span="1.5">-->
+<!--        <el-button-->
+<!--          type="primary"-->
+<!--          plain-->
+<!--          icon="el-icon-plus"-->
+<!--          size="mini"-->
+<!--          @click="handleAdd"-->
+<!--          v-hasPermi="['store:userOnlineState:add']"-->
+<!--        >新增</el-button>-->
+<!--      </el-col>-->
+<!--      <el-col :span="1.5">-->
+<!--        <el-button-->
+<!--          type="success"-->
+<!--          plain-->
+<!--          icon="el-icon-edit"-->
+<!--          size="mini"-->
+<!--          :disabled="single"-->
+<!--          @click="handleUpdate"-->
+<!--          v-hasPermi="['store:userOnlineState:edit']"-->
+<!--        >修改</el-button>-->
+<!--      </el-col>-->
+<!--      <el-col :span="1.5">-->
+<!--        <el-button-->
+<!--          type="danger"-->
+<!--          plain-->
+<!--          icon="el-icon-delete"-->
+<!--          size="mini"-->
+<!--          :disabled="multiple"-->
+<!--          @click="handleDelete"-->
+<!--          v-hasPermi="['store:userOnlineState:remove']"-->
+<!--        >删除</el-button>-->
+<!--      </el-col>-->
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['store:userOnlineState:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="userOnlineStateList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="用户id" align="center" prop="userId" />
+      <el-table-column label="用户昵称" align="center" prop="nickname" />
+      <el-table-column label="用户头像" align="center" width="80">
+        <template slot-scope="scope">
+          <el-popover
+            placement="right"
+            title=""
+            trigger="hover"
+          >
+            <img slot="reference" :src="scope.row.avatar" width="50" >
+            <img :src="scope.row.avatar" style="max-width: 120px;">
+          </el-popover>
+        </template>
+      </el-table-column>
+      <el-table-column label="手机号码" align="center" prop="phone" />
+      <el-table-column label="注册时间" align="center" prop="createTime" />
+      <el-table-column label="用户状态" align="center" prop="status">
+        <template slot-scope="scope">
+          <el-tag prop="status"  v-if="scope.row.status === 1" type="success">正常</el-tag>
+          <el-tag prop="status"  v-if="scope.row.status === 0" type="warning">禁用</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="所属公司" align="center" prop="companyName" />
+      <el-table-column label="所属销售" align="center" prop="companyUserName" />
+      <el-table-column label="上线状态" align="center" prop="onlineStatus">
+      <template slot-scope="scope">
+        <el-tag prop="onlineStatus"  v-if="scope.row.onlineStatus === 1" type="success">已上线</el-tag>
+        <el-tag prop="onlineStatus"  v-if="scope.row.onlineStatus === 2" type="primary">未上线</el-tag>
+      </template>
+      </el-table-column>
+<!--      <el-table-column label="上线时间" align="center" prop="onlineTime" width="180">-->
+<!--        <template slot-scope="scope">-->
+<!--          <span>{{ parseTime(scope.row.onlineTime, '{y}-{m}-{d}') }}</span>-->
+<!--        </template>-->
+<!--      </el-table-column>-->
+<!--      <el-table-column label="看课数量" align="center" prop="watchCourseCount" />-->
+<!--      <el-table-column label="参与营期数量" align="center" prop="partCourseCount" />-->
+<!--      <el-table-column label="最后一次看课时间" align="center" prop="lastWatchDate" width="180">-->
+<!--        <template slot-scope="scope">-->
+<!--          <span>{{ parseTime(scope.row.lastWatchDate, '{y}-{m}-{d}') }}</span>-->
+<!--        </template>-->
+<!--      </el-table-column>-->
+<!--      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">-->
+<!--        <template slot-scope="scope">-->
+<!--          <el-button-->
+<!--            size="mini"-->
+<!--            type="text"-->
+<!--            icon="el-icon-edit"-->
+<!--            @click="handleUpdate(scope.row)"-->
+<!--            v-hasPermi="['store:userOnlineState:edit']"-->
+<!--          >修改</el-button>-->
+<!--          <el-button-->
+<!--            size="mini"-->
+<!--            type="text"-->
+<!--            icon="el-icon-delete"-->
+<!--            @click="handleDelete(scope.row)"-->
+<!--            v-hasPermi="['store:userOnlineState:remove']"-->
+<!--          >删除</el-button>-->
+<!--        </template>-->
+<!--      </el-table-column>-->
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+<!--    &lt;!&ndash; 添加或修改用户上线情况对话框 &ndash;&gt;-->
+<!--    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>-->
+<!--      <el-form ref="form" :model="form" :rules="rules" label-width="80px">-->
+<!--        <el-form-item label="用户昵称" prop="nickname">-->
+<!--          <el-input v-model="form.nickname" placeholder="请输入用户昵称" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="用户头像" prop="avatar">-->
+<!--          <el-input v-model="form.avatar" placeholder="请输入用户头像" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="微信小程序OPENID" prop="maOpenId">-->
+<!--          <el-input v-model="form.maOpenId" placeholder="请输入微信小程序OPENID" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="微信公众号OPENID" prop="mpOpenId">-->
+<!--          <el-input v-model="form.mpOpenId" placeholder="请输入微信公众号OPENID" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="关联ID" prop="unionId">-->
+<!--          <el-input v-model="form.unionId" placeholder="请输入关联ID" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="公司id" prop="companyId">-->
+<!--          <el-input v-model="form.companyId" placeholder="请输入公司id" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="销售id" prop="companyUserId">-->
+<!--          <el-input v-model="form.companyUserId" placeholder="请输入销售id" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="上线状态,1-已上线;2-未上线">-->
+<!--          <el-radio-group v-model="form.onlineStatus">-->
+<!--            <el-radio label="1">请选择字典生成</el-radio>-->
+<!--          </el-radio-group>-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="上线时间" prop="onlineTime">-->
+<!--          <el-date-picker clearable size="small"-->
+<!--            v-model="form.onlineTime"-->
+<!--            type="date"-->
+<!--            value-format="yyyy-MM-dd"-->
+<!--            placeholder="选择上线时间">-->
+<!--          </el-date-picker>-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="看课数量" prop="watchCourseCount">-->
+<!--          <el-input v-model="form.watchCourseCount" placeholder="请输入看课数量" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="参与营期数量" prop="partCourseCount">-->
+<!--          <el-input v-model="form.partCourseCount" placeholder="请输入参与营期数量" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="最后一次看课时间" prop="lastWatchDate">-->
+<!--          <el-date-picker clearable size="small"-->
+<!--            v-model="form.lastWatchDate"-->
+<!--            type="date"-->
+<!--            value-format="yyyy-MM-dd"-->
+<!--            placeholder="选择最后一次看课时间">-->
+<!--          </el-date-picker>-->
+<!--        </el-form-item>-->
+<!--      </el-form>-->
+<!--      <div slot="footer" class="dialog-footer">-->
+<!--        <el-button type="primary" @click="submitForm">确 定</el-button>-->
+<!--        <el-button @click="cancel">取 消</el-button>-->
+<!--      </div>-->
+<!--    </el-dialog>-->
+  </div>
+</template>
+
+<script>
+import { listUserOnlineState, getUserOnlineState, delUserOnlineState, addUserOnlineState, updateUserOnlineState, exportUserOnlineState } from "@/api/his/userOnlineState";
+
+export default {
+  name: "UserOnlineState",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 用户上线情况表格数据
+      userOnlineStateList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        nickname: null,
+        avatar: null,
+        phone: null,
+        maOpenId: null,
+        mpOpenId: null,
+        unionId: null,
+        companyId: null,
+        companyUserId: null,
+        onlineStatus: null,
+        onlineTime: null,
+        watchCourseCount: null,
+        partCourseCount: null,
+        lastWatchDate: null
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    /** 查询用户上线情况列表 */
+    getList() {
+      this.loading = true;
+      listUserOnlineState(this.queryParams).then(response => {
+        this.userOnlineStateList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        userId: null,
+        nickname: null,
+        avatar: null,
+        phone: null,
+        createTime: null,
+        maOpenId: null,
+        mpOpenId: null,
+        unionId: null,
+        companyId: null,
+        companyUserId: null,
+        onlineStatus: 0,
+        onlineTime: null,
+        watchCourseCount: null,
+        partCourseCount: null,
+        lastWatchDate: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.userId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加用户上线情况";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const userId = row.userId || this.ids
+      getUserOnlineState(userId).then(response => {
+        this.form = response.data;
+        this.open = true;
+        this.title = "修改用户上线情况";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.userId != null) {
+            updateUserOnlineState(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addUserOnlineState(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const userIds = row.userId || this.ids;
+      this.$confirm('是否确认删除用户上线情况编号为"' + userIds + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delUserOnlineState(userIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有用户上线情况数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(() => {
+          this.exportLoading = true;
+          return exportUserOnlineState(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+          this.exportLoading = false;
+        }).catch(() => {});
+    }
+  }
+};
+</script>

+ 63 - 38
src/views/statistics/section/inline.vue

@@ -120,6 +120,14 @@
           </span>
         </template>
       </el-table-column>
+
+      <el-table-column prop="trafficSum" label="流量数" align="center">
+        <template #default="scope">
+          {{ formatTraffic(scope.row.trafficSum) }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="regNum" label="注册数" align="center"/>
+
     </el-table>
 
     <pagination
@@ -214,6 +222,23 @@ export default {
     })
   },
   methods: {
+    formatTraffic(bytes) {
+      if (!bytes || bytes === 0) return '0 B';
+
+      const units = ['B', 'KB', 'MB', 'GB', 'TB'];
+      const k = 1024;
+
+      // 计算单位级别
+      const i = Math.floor(Math.log(bytes) / Math.log(k));
+
+      // 确保不超出单位数组范围
+      const unitIndex = Math.min(i, units.length - 1);
+
+      // 计算值并保留2位小数
+      const value = bytes / Math.pow(k, unitIndex);
+
+      return `${value.toFixed(2)} ${units[unitIndex]}`;
+    },
     getSummaries(param) {
       const { columns, data } = param;
       const sums = [];
@@ -224,48 +249,48 @@ export default {
           return;
         }
 
-        const values = data.map(item => Number(item[column.property]));
-
-        if (['periodPersonNum','periodNum', 'sendNum', 'notRegisteredNum', 'registeredNum',
-        'interruptNum', 'completedNum', 'qwRepeatNum', 'userRepeatNum','blackNum','deletedNum',
-        'orderNum','orderMoneyTotal','redPackageMoneyTotal','callNum','receivePassNum','receiveNotNum',
-      'callTimeTotal','remindPendingNum','remindProcessedNum'].includes(column.property)) {
-          if (!values.every(value => isNaN(value))) {
-            sums[index] = values.reduce((prev, curr) => {
-              const value = Number(curr);
-              if (!isNaN(value)) {
-                return prev + curr;
-              } else {
-                return prev;
-              }
-            }, 0);
-          } else {
-            sums[index] = 'N/A';
-          }
-          if(['orderMoneyTotal','redPackageMoneyTotal'].includes(column.property)){
+        // 定义所有需要求和的列
+        const sumColumns = [
+          'periodPersonNum', 'periodNum', 'sendNum', 'notRegisteredNum', 'registeredNum',
+          'interruptNum', 'completedNum', 'qwRepeatNum', 'userRepeatNum', 'blackNum', 'deletedNum',
+          'orderNum', 'orderMoneyTotal', 'redPackageMoneyTotal', 'callNum', 'receivePassNum',
+          'receiveNotNum', 'callTimeTotal', 'remindPendingNum', 'remindProcessedNum',
+          // 增加其他所有需要计算的数值列
+          'deleteNum', 'lineNum', 'orderTotalNum'
+        ];
+
+        const rateColumns = ['regRate', 'finishedRate'];
+
+        if (sumColumns.includes(column.property)) {
+          const values = data.map(item => Number(item[column.property]) || 0);
+          sums[index] = values.reduce((prev, curr) => prev + curr, 0);
+
+          if(['orderMoneyTotal', 'redPackageMoneyTotal'].includes(column.property)){
             sums[index] = sums[index].toFixed(2);
           }
         }
-        else if (column.property === 'regRate') {
-          const totalRegistered = data.reduce((sum, item) => sum + (Number(item.registeredNum) || 0), 0);
-          const totalSendNum = data.reduce((sum, item) => sum + (Number(item.sendNum) || 0), 0);
-
-          if (totalSendNum > 0) {
-            const rate = (totalRegistered / totalSendNum * 100).toFixed(2);
-            sums[index] = `${rate}%`;
-          } else {
-            sums[index] = '0.00%';
+        else if (rateColumns.includes(column.property)) {
+          if (column.property === 'regRate') {
+            const totalRegistered = data.reduce((sum, item) => sum + (Number(item.registeredNum) || 0), 0);
+            const totalSendNum = data.reduce((sum, item) => sum + (Number(item.sendNum) || 0), 0);
+
+            if (totalSendNum > 0) {
+              const rate = (totalRegistered / totalSendNum * 100).toFixed(2);
+              sums[index] = `${rate}%`;
+            } else {
+              sums[index] = '0.00%';
+            }
           }
-        }
-        else if (column.property === 'finishedRate') {
-          const totalCompleted = data.reduce((sum, item) => sum + (Number(item.completedNum) || 0), 0);
-          const totalSendNum = data.reduce((sum, item) => sum + (Number(item.sendNum) || 0), 0);
-
-          if (totalSendNum > 0) {
-            const rate = (totalCompleted / totalSendNum * 100).toFixed(2);
-            sums[index] = `${rate}%`;
-          } else {
-            sums[index] = '0.00%';
+          else if (column.property === 'finishedRate') {
+            const totalCompleted = data.reduce((sum, item) => sum + (Number(item.completedNum) || 0), 0);
+            const totalSendNum = data.reduce((sum, item) => sum + (Number(item.sendNum) || 0), 0);
+
+            if (totalSendNum > 0) {
+              const rate = (totalCompleted / totalSendNum * 100).toFixed(2);
+              sums[index] = `${rate}%`;
+            } else {
+              sums[index] = '0.00%';
+            }
           }
         }
         else {

+ 39 - 3
src/views/system/config/config.vue

@@ -155,8 +155,8 @@
           </el-form>
       </el-tab-pane>
 
-      <el-tab-pane label="协议配置" name="his.agreementConfig" :rules="rules3">
-          <el-form ref="form3" :model="form3"  label-width="150px">
+      <el-tab-pane label="协议配置" name="his.agreementConfig" >
+          <el-form ref="form3" :model="form3"  label-width="150px" :rules="rules4">
             <el-form-item label="医生注册协议" prop="doctorRegister">
               <editor v-model="form3.doctorRegister" :min-height="292"/>
             </el-form-item>
@@ -327,6 +327,15 @@
               <el-input-number  v-model="form7.followRate" :min="0" :max="1000"    ></el-input-number>
             </el-tooltip>
           </el-form-item>
+          <el-form-item  label="是否需要根据物流信息更新订单完成状态" prop="followRate">
+            <el-switch
+              v-model="form7.isUpdateOrder"
+              active-color="#13ce66"
+              inactive-color="#ff4949"
+              :active-value=1
+              :inactive-value=0>
+            </el-switch>
+          </el-form-item>
          <div   class="footer">
             <el-button type="primary" @click="submitForm7">提  交</el-button>
           </div>
@@ -1512,6 +1521,26 @@ export default {
       },
       rules3: {
       },
+      rules4: {
+        doctorRegister: [
+          { required: true, message: '请输入医生注册协议', trigger: 'blur' }
+        ],
+        doctorFiling: [
+          { required: true, message: '请输入医生多机构备案协议', trigger: 'blur' }
+        ],
+        userRegister: [
+          { required: true, message: '请输入用户协议', trigger: 'blur' }
+        ],
+        userPrivacy: [
+          { required: true, message: '请输入隐私协议', trigger: 'blur' }
+        ],
+        userHealth: [
+          { required: true, message: '请输入健康客服协议', trigger: 'blur' }
+        ],
+        vipService: [
+          { required: true, message: '请输入会员服务协议', trigger: 'blur' }
+        ]
+      },
       rulesDelay:[
                 {
                   validator: (rule, value, callback) => {
@@ -1731,7 +1760,14 @@ export default {
               });
           }
           if(key=="his.store"){
-              this.form7 =JSON.parse(response.data.configValue);
+              // this.form7 =JSON.parse(response.data.configValue);
+              const parsed = JSON.parse(response.data.configValue);
+              if (parsed.isUpdateOrder != null) {
+                parsed.isUpdateOrder = Number(parsed.isUpdateOrder);
+              } else {
+                parsed.isUpdateOrder = 1; // 默认值
+              }
+              this.form7 = parsed
           }
           if(key=="his.package"){
               this.form8 =JSON.parse(response.data.configValue);

+ 12 - 11
src/views/user/darkRoom/index.vue

@@ -44,16 +44,17 @@
           </el-popover>
         </template>
       </el-table-column>
+      <el-table-column label="手机号码" align="center" prop="phone" width="160px"/>
       <el-table-column label="注册时间" align="center" prop="createTime" width="160px"/>
-      <el-table-column label="看课数量" align="center" prop="watchCourseCount" />
-      <el-table-column label="缺课数量" align="center" prop="missCourseCount" />
-      <el-table-column label="缺课状态" align="center" prop="missCourseStatus">
-        <template slot-scope="scope">
-          <el-tag effect="dark" type="danger"  v-if="scope.row.missCourseStatus === 1">已缺课</el-tag>
-          <el-tag effect="dark" type="success" v-else>未缺课</el-tag>
-        </template>
-      </el-table-column>
-      <el-table-column label="参与营期数量" align="center" prop="partCourseCount" width="100px"/>
+<!--      <el-table-column label="看课数量" align="center" prop="watchCourseCount" />-->
+<!--      <el-table-column label="缺课数量" align="center" prop="missCourseCount" />-->
+<!--      <el-table-column label="缺课状态" align="center" prop="missCourseStatus">-->
+<!--        <template slot-scope="scope">-->
+<!--          <el-tag effect="dark" type="danger"  v-if="scope.row.missCourseStatus === 1">已缺课</el-tag>-->
+<!--          <el-tag effect="dark" type="success" v-else>未缺课</el-tag>-->
+<!--        </template>-->
+<!--      </el-table-column>-->
+<!--      <el-table-column label="参与营期数量" align="center" prop="partCourseCount" width="100px"/>-->
       <el-table-column label="最后一次看课时间" align="center" prop="lastWatchDate"  width="160px"/>
       <el-table-column label="用户状态" align="center" prop="courseCountStatus">
         <template slot-scope="scope">
@@ -62,8 +63,8 @@
           <el-tag effect="dark" type="danger"  v-else>未看</el-tag>
         </template>
       </el-table-column>
-      <el-table-column label="停课天数" align="center" prop="stopWatchDays" />
-      <el-table-column label="完播时间" align="center" prop="completeWatchDate" width="160px"/>
+<!--      <el-table-column label="停课天数" align="center" prop="stopWatchDays" />-->
+<!--      <el-table-column label="完播时间" align="center" prop="completeWatchDate" width="160px"/>-->
       <el-table-column label="标签名称" align="center" prop="tag" />
       <el-table-column label="所属销售名称" align="center" prop="companyUserNickName" width="120px"/>
       <el-table-column label="备注" align="center" prop="remark" />