Преглед изворни кода

Merge remote-tracking branch 'origin/master'

yfh пре 2 недеља
родитељ
комит
1df3f7bf2c

+ 14 - 0
src/api/statistics/statistics.js

@@ -228,6 +228,20 @@ export function watchCourseTopTen(param){
   })
 }
 
+/**
+ * 课程观看统计 按公司
+ * @param param
+ * @returns {AxiosPromise}
+ */
+export function getWatchCourseStatisticsData(param){
+  const safeParam = JSON.parse(JSON.stringify(param));
+  return request({
+    url: '/index/statistics/getWatchCourseStatisticsData',
+    method: 'post',
+    data: safeParam
+  })
+}
+
 
 /**
  * 答题红包金额TOP10

+ 2 - 1
src/components/TreeSelect/index.vue

@@ -73,7 +73,7 @@
                   :value="checkedKeysSet.has(item.key)"
                   :disabled="checkboxDisabled(item)"
                   @change="handleCheckboxChange(item, $event)"
-                  @click.stop
+                  @click.native.stop
                   class="node-checkbox"
                 ></el-checkbox>
 
@@ -569,6 +569,7 @@ export default {
       }
     },
     handleCheckboxChange(node, checked) {
+
       if (this.checkboxDisabled(node)) return;
 
       const newCheckedKeys = new Set(this.checkedKeysSet);

+ 10 - 0
src/views/course/courseAnswerlogs/index.vue

@@ -1,6 +1,16 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="120px">
+      <el-form-item label="销售公司" prop="companyId">
+        <el-select filterable v-model="queryParams.companyId" clearable placeholder="请选择公司名" size="small">
+          <el-option
+            v-for="item in companys"
+            :key="item.companyId"
+            :label="item.companyName"
+            :value="item.companyId"
+          />
+        </el-select>
+      </el-form-item>
       <el-form-item label="客户电话" prop="phone">
         <el-input
           v-model="queryParams.phone"

+ 12 - 2
src/views/course/courseFinishTempParent/index.vue

@@ -1,6 +1,16 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="销售公司" prop="companyId">
+        <el-select filterable v-model="queryParams.companyId" clearable placeholder="请选择公司名" size="small">
+          <el-option
+            v-for="item in companyList"
+            :key="item.companyId"
+            :label="item.companyName"
+            :value="item.companyId"
+          />
+        </el-select>
+      </el-form-item>
       <el-form-item label="名称" prop="name">
         <el-input
           v-model="queryParams.name"
@@ -434,6 +444,7 @@ export default {
         pageSize: 10,
         name: null,
         courseId: null,
+        companyId: null
       },
       // 表单参数
       form: {},
@@ -496,7 +507,7 @@ export default {
       this.form = {
         id: null,
         status: 1,
-        companyId: 1,
+        companyId: null,
         name: null,
         setting: [],
         chatSetting: [],
@@ -508,7 +519,6 @@ export default {
         companyUserIds: null,
         remark: null
       };
-      this.resetForm("form");
     },
     /** 搜索按钮操作 */
     handleQuery() {

+ 2 - 0
src/views/course/courseUserStatistics/qw/index.vue

@@ -38,6 +38,8 @@
             <el-table-column label="进线时间" align="center" prop="createTime"/>
             <!-- 进线数 -->
             <el-table-column label="进线数" align="center" prop="line" />
+            <!-- 注册数 -->
+            <el-table-column label="注册数" align="center" prop="regNum" />
 
             <!-- 先导课上线 -->
             <el-table-column label="先导课上线" align="center" prop="firstOnline">

+ 2 - 1
src/views/course/courseUserStatistics/qw/my.vue

@@ -37,7 +37,8 @@
             <el-table-column label="进线时间" align="center" prop="createTime"/>
             <!-- 进线数 -->
             <el-table-column label="进线数" align="center" prop="line" />
-
+            <!-- 注册数 -->
+            <el-table-column label="注册数" align="center" prop="regNum" />
             <!-- 先导课上线 -->
             <el-table-column label="先导课上线" align="center" prop="firstOnline">
                 <template slot-scope="scope">

+ 2 - 1
src/views/course/courseUserStatistics/qw/myStatistics.vue

@@ -27,7 +27,8 @@
             <el-table-column label="进线时间" align="center" prop="createTime"/>
             <!-- 进线数 -->
             <el-table-column label="进线数" align="center" prop="line" />
-
+            <!-- 注册数 -->
+            <el-table-column label="注册数" align="center" prop="regNum" />
             <!-- 先导课上线 -->
             <el-table-column label="先导上线" align="center" prop="firstOnline">
                 <template slot-scope="scope">

+ 2 - 1
src/views/course/courseUserStatistics/qw/statistics.vue

@@ -37,7 +37,8 @@
             <el-table-column label="进线时间" align="center" prop="createTime"/>
             <!-- 进线数 -->
             <el-table-column label="进线数" align="center" prop="line" />
-
+            <!-- 注册数 -->
+            <el-table-column label="注册数" align="center" prop="regNum" />
             <!-- 先导课上线 -->
             <el-table-column label="先导上线" align="center" prop="firstOnline">
                 <template slot-scope="scope">

+ 7 - 7
src/views/course/courseWatchComment/index.vue

@@ -91,13 +91,13 @@
       <el-table-column label="评论内容" align="center" prop="content" />
       <el-table-column label="所属课程" align="center" prop="courseName" />
       <el-table-column label="所属小节" align="center" prop="title" />
-      <el-table-column label="弹幕状态" align="center" prop="status">
-        <template slot-scope="scope">
-          <el-tag :type="getStatusTagType(scope.row.status)">
-            {{ formatBarrageStatus(scope.row.status) }}
-          </el-tag>
-        </template>
-      </el-table-column>
+<!--      <el-table-column label="弹幕状态" align="center" prop="status">-->
+<!--        <template slot-scope="scope">-->
+<!--          <el-tag :type="getStatusTagType(scope.row.status)">-->
+<!--            {{ formatBarrageStatus(scope.row.status) }}-->
+<!--          </el-tag>-->
+<!--        </template>-->
+<!--      </el-table-column>-->
       <el-table-column label="评论时间" align="center" prop="createTime" width="160px"/>
       <!--      <el-table-column label="是否是撤回的消息,1-是,0-否" align="center" prop="isRevoke" />-->
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width">

+ 20 - 2
src/views/course/courseWatchLog/index.vue

@@ -1,6 +1,16 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
+      <el-form-item label="销售公司" prop="companyId">
+        <el-select filterable v-model="queryParams.companyId" clearable placeholder="请选择公司名" size="small">
+          <el-option
+            v-for="item in companyList"
+            :key="item.companyId"
+            :label="item.companyName"
+            :value="item.companyId"
+          />
+        </el-select>
+      </el-form-item>
       <el-form-item label="课程" prop="courseId">
         <el-select filterable  v-model="queryParams.courseId" placeholder="请选择课程"  clearable size="small" @change="courseChange(queryParams.courseId)">
           <el-option
@@ -138,7 +148,7 @@
 
 <script>
 import { listCourseWatchLog, getCourseWatchLog, delCourseWatchLog, addCourseWatchLog, updateCourseWatchLog, exportCourseWatchLog } from "@/api/course/courseWatchLog";
-import {allList}from "@/api/company/company";
+import { allList, getCompanyList } from '@/api/company/company'
 import { courseList,videoList } from '@/api/course/courseRedPacketLog'
 import {getUserList} from "@/api/company/companyUser";
 import {getFsUserList} from "@/api/users/user";
@@ -153,6 +163,7 @@ export default {
       courseLists:[],
       videoList:[],
       logTypeOptions:[],
+      companyList: [],
       queryUserLoading: false,
       // 遮罩层
       loading: true,
@@ -212,7 +223,11 @@ export default {
     courseList().then(response => {
       this.courseLists = response.list;
     });
-    this.getList();
+
+    getCompanyList().then(response => {
+      this.companyList = response.data;
+    });
+
     this.getDicts("sys_course_watch_log_type").then(response => {
       this.logTypeOptions = response.data;
     });
@@ -222,6 +237,9 @@ export default {
       this.userSourceTypeOptions = response.data;
     })
 
+    this.getList();
+
+
   },
   computed: {
     sourceTypeModel: {

+ 1 - 0
src/views/course/userCourseComplaintRecord/index.vue

@@ -327,6 +327,7 @@ export default {
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm("queryForm");
+      this.dateRange = [];
       this.handleQuery();
     },
     // 多选框选中数据

+ 4 - 105
src/views/course/videoResource/index.vue

@@ -984,10 +984,12 @@ export default {
     },
     // 取消按钮
     cancel() {
-      this.$refs.videoUpload.clearFiles()
       this.open = false;
       this.reset();
+      this.resetForm("form");
+      this.batchUpdateVisible = false;
       this.changeCateType(this.queryParams.typeId)
+      this.$refs.videoUpload.clearFiles()
     },
     // 表单重置
     reset() {
@@ -1429,8 +1431,7 @@ export default {
         this.$message.warning("请至少选择一条数据");
         return;
       }
-      this.batchUpdateForm.typeId = null;
-      this.batchUpdateForm.typeSubId = null;
+      this.resetForm("form");
       this.batchUpdateForm.ids = this.ids; // 将选中的ID传递给批量修改表单
       this.batchUpdateVisible = true;
     },
@@ -2063,108 +2064,6 @@ export default {
       });
     },
 
-    /** 删除视频 */
-    handleDeleteVideo(row) {
-      if (row.uploadStatus === 'uploading') {
-        this.$confirm('该视频正在上传中,确认要取消上传并删除吗?', '取消上传', {
-          confirmButtonText: '确定取消',
-          cancelButtonText: '继续上传',
-          type: 'warning'
-        }).then(() => {
-          // Cancel the upload and remove from list
-          this.cancelVideoUpload(row);
-        }).catch(() => {
-          // User chose to continue uploading
-          this.$message.info('继续上传该视频');
-        });
-      } else {
-        // Original confirmation for non-uploading videos
-        this.$confirm('确认要从列表中删除该视频吗?', '提示', {
-          confirmButtonText: '确定',
-          cancelButtonText: '取消',
-          type: 'warning'
-        }).then(() => {
-          this.removeVideoFromList(row);
-        }).catch(() => {
-          // 取消删除
-        });
-      }
-    },
-
-    cancelVideoUpload(row) {
-      const cancellationTokens = this.uploadCancellationTokens.get(row.tempId);
-      if (cancellationTokens) {
-        // Cancel COS upload if exists
-        if (cancellationTokens.cos) {
-          try {
-            cancellationTokens.cos();
-            console.log('COS upload cancelled for video:', row.tempId);
-          } catch (error) {
-            console.error('Error cancelling COS upload:', error);
-          }
-        }
-
-        // Cancel OBS upload if exists
-        if (cancellationTokens.obs) {
-          try {
-            cancellationTokens.obs();
-            console.log('OBS upload cancelled for video:', row.tempId);
-          } catch (error) {
-            console.error('Error cancelling OBS upload:', error);
-          }
-        }
-
-        // Remove cancellation tokens
-        this.uploadCancellationTokens.delete(row.tempId);
-      }
-
-      const videoIndex = this.videoList.findIndex(item => item.tempId === row.tempId);
-      if (videoIndex !== -1) {
-        this.videoList[videoIndex].uploadStatus = 'cancelled';
-        this.videoList.splice(videoIndex, 1);
-      }
-
-      const queueIndex = this.uploadQueue.findIndex(item => item.tempId === row.tempId);
-      if (queueIndex !== -1) {
-        this.uploadQueue.splice(queueIndex, 1);
-        this.updateQueuePositions();
-      }
-
-      this.$message.success('已取消视频上传并从列表中移除');
-    },
-
-    removeVideoFromList(row) {
-      const videoIndex = this.videoList.findIndex(item => item.tempId === row.tempId);
-      if (videoIndex !== -1) {
-        this.videoList.splice(videoIndex, 1);
-      }
-
-      // Remove from upload queue if it's still queued
-      const queueIndex = this.uploadQueue.findIndex(item => item.tempId === row.tempId);
-      if (queueIndex !== -1) {
-        this.uploadQueue.splice(queueIndex, 1);
-        this.updateQueuePositions();
-        this.$message.success('已从上传队列中移除该视频');
-      } else {
-        this.$message.success('已从列表中移除该视频');
-      }
-    },
-
-    getUploadStatusText(status, queuePosition) {
-      switch (status) {
-        case 'success':
-          return '上传成功';
-        case 'failed':
-          return '上传失败';
-        case 'uploading':
-          return '上传中';
-        case 'queued':
-          return `队列中 (第${queuePosition}位)`;
-        default:
-          return '待上传';
-      }
-    },
-
     getQueueStatusColor(status) {
       switch (status) {
         case 'success':

+ 17 - 13
src/views/crm/components/assignCompany.vue

@@ -45,7 +45,7 @@
       </el-form>
       <div slot="footer" class="footer">
         <el-button type="primary" @click="submitAssignForm">确 定</el-button>
-        <el-button @click="assign.open=false">取 消</el-button>
+        <el-button @click="handleCancel">取 消</el-button>
       </div>
 
      <el-dialog :title="companySelect.title" :visible.sync="companySelect.open" width="1000px" append-to-body>
@@ -78,22 +78,24 @@
                 },
                 // 表单校验
                 assignRules: {
-                    
+
                 },
                 companys:[],
-                 
+
             };
         },
         created() {
-          
+
         },
         methods: {
-            init(customerIds){
-                this.customerIds =  customerIds;
-                this.assignCount=0;
-                this.noAssignCount=this.customerIds.length;
-                this.companys=[];
-            },
+          handleCancel() {
+            this.companys = [];
+            this.noAssignCount = 0;
+            this.assignCount = 0;
+            this.customerIds = [];
+            //关闭弹窗
+            // this.$emit('close');
+          },
             changeVal(row) {
                 this.$forceUpdate();//解决点击计数器失效问题
                 this.computeCount();
@@ -102,7 +104,7 @@
                          row.count=0;
                          this.computeCount();
                     });
-                   
+
                 }
             },
             handleRemoveCompany(index){
@@ -199,7 +201,9 @@
                 });
             },
             closeAction(){
-                //this.$refs.companySelects.companys=[];
+              if (this.$refs.companySelects) {
+                this.$refs.companySelects.clearSelection();
+              }
             }
         }
     };
@@ -210,7 +214,7 @@
     height: 100%;
     background-color: #fff;
     padding: 20px;
-        
+
 }
 .footer{
     display: flex;

+ 17 - 21
src/views/crm/customer/index.vue

@@ -63,7 +63,7 @@
           v-model="dateRange"
           type="daterange"
           value-format="yyyy-MM-dd"
-          start-placeholder="开始日期" end-placeholder="结束日期"
+          start-placeholder="开始日期" end-placeholder="结束日期" @change="handleScheduleTimeChange"
            >
         </el-date-picker>
       </el-form-item>
@@ -405,7 +405,9 @@ export default {
         companyId: null,
         isLine: null,
         source: null,
-        tags: null
+        tags: null,
+        beginTime: null,
+        endTime: null,
       },
       // 表单参数
       form: {},
@@ -449,6 +451,15 @@ export default {
     this.getList();
   },
   methods: {
+    handleScheduleTimeChange(val) {
+      if (val) {
+        this.queryParams.beginTime = val[0];
+        this.queryParams.endTime = val[1];
+      } else {
+        this.queryParams.beginTime = null;
+        this.queryParams.endTime = null;
+      }
+    },
     handleEditSource(){
       this.source.open=true;
       var that=this;
@@ -498,25 +509,6 @@ export default {
           this.citys=res.data;
         })
     },
-    handleClose(tag) {
-        this.tags.splice(this.tags.indexOf(tag), 1);
-        this.form.tags=this.tags.toString();
-    },
-    showInput() {
-      this.inputVisible = true;
-      this.$nextTick(_ => {
-        this.$refs.saveTagInput.$refs.input.focus();
-      });
-    },
-    handleInputConfirm() {
-      let inputValue = this.inputValue;
-      if (inputValue) {
-        this.tags.push(inputValue);
-      }
-      this.inputVisible = false;
-      this.inputValue = '';
-      this.form.tags=this.tags.toString();
-    },
     handleShow(row){
       var that=this;
       that.show.open=true;
@@ -602,7 +594,11 @@ export default {
     },
     /** 重置按钮操作 */
     resetQuery() {
+      this.queryParams.beginTime = null;
+      this.queryParams.endTime = null;
+      this.dateRange = null;
       this.resetForm("queryForm");
+      //this.$forceUpdate(); // 强制更新视图
       this.handleQuery();
     },
     // 多选框选中数据

+ 16 - 2
src/views/crm/customer/line.vue

@@ -43,7 +43,7 @@
           v-model="dateRange"
           type="daterange"
           value-format="yyyy-MM-dd"
-          start-placeholder="开始日期" end-placeholder="结束日期"
+          start-placeholder="开始日期" end-placeholder="结束日期"  @change="handleScheduleTimeChange"
            >
         </el-date-picker>
       </el-form-item>
@@ -426,7 +426,9 @@ export default {
         companyId: null,
         isLine: null,
         source: null,
-        tags: null
+        tags: null,
+        beginTime: null,
+        endTime: null,
       },
       // 表单参数
       form: {
@@ -465,6 +467,15 @@ export default {
     this.getList();
   },
   methods: {
+    handleScheduleTimeChange(val) {
+      if (val) {
+        this.queryParams.beginTime = val[0];
+        this.queryParams.endTime = val[1];
+      } else {
+        this.queryParams.beginTime = null;
+        this.queryParams.endTime = null;
+      }
+    },
     handleAssignList(){
       this.assignList.open=true;
       var that=this;
@@ -583,6 +594,9 @@ export default {
     },
     /** 重置按钮操作 */
     resetQuery() {
+      this.queryParams.beginTime = null;
+      this.queryParams.endTime = null;
+      this.dateRange = null;
       this.resetForm("queryForm");
       this.handleQuery();
     },

+ 1 - 0
src/views/crm/externalContact/index.vue

@@ -1515,6 +1515,7 @@ export default {
 
       searchTags(this.queryTagParams).then(response => {
         this.tagGroupList = response.rows;
+        this.total = response.total;
       });
 
     },

+ 1 - 0
src/views/fastGpt/fastGptExtUserTag/index.vue

@@ -279,6 +279,7 @@ export default {
 
       searchTags(this.queryTagParams).then(response => {
         this.tagGroupList = response.rows;
+        this.total = response.total;
       });
 
 

+ 30 - 2
src/views/his/doctor/type2.vue

@@ -396,7 +396,7 @@
                 </el-col>
           </el-row>
           <el-row>
-                <el-col :span="24">
+                <el-col :span="12">
                     <el-form-item label="身份证反面" prop="idCardBackUrl">
                        <el-upload
                                   v-model="form.idCardBackUrl"
@@ -410,6 +410,20 @@
                       </el-upload>
                     </el-form-item>
                 </el-col>
+                <el-col :span="12">
+                  <el-form-item label="医生签名" prop="signUrl">
+                    <el-upload id="sign"
+                               v-model="form.signUrl"
+                               class="avatar-uploader"
+                               :action="bauploadUrl"
+                               :show-file-list="false"
+                               :on-success="signhandleAvatarSuccess"
+                               :before-upload="beforeAvatarUpload">
+                      <img v-if="form.signUrl" :src="form.signUrl" class="avatar" width="150px">
+                      <i v-else class="el-icon-plus avatar-uploader-icon"></i>
+                    </el-upload>
+                  </el-form-item>
+                </el-col>
           </el-row>
 
       <el-row>
@@ -536,6 +550,7 @@ export default {
       certificateBack:process.env.VUE_APP_BASE_API+"/common/uploadOSS",
       practise:process.env.VUE_APP_BASE_API+"/common/uploadOSS",
       practiseBack:process.env.VUE_APP_BASE_API+"/common/uploadOSS",
+      bauploadUrl:process.env.VUE_APP_BASE_API+"/common/uploadOSS",
       orOptions: [],
       isauditOptions: [],
       positionOptions: [],
@@ -778,7 +793,15 @@ export default {
                   this.msgError(res.msg);
                 }
      },
-
+    signhandleAvatarSuccess(res, file) {
+      if(res.code==200){
+        this.form.signUrl=res.url;
+        this.$forceUpdate();
+      }
+      else{
+        this.msgError(res.msg);
+      }
+    },
     handleAvatarSuccess(res, file) {
             if(res.code==200){
               this.form.certificateImages=res.url;
@@ -1124,4 +1147,9 @@ export default {
        line-height: 150px;
        text-align: center;
     }
+  #sign .avatar{
+    min-width: 120px;
+    min-height: 80px;
+    display: block;
+  }
 </style>

+ 66 - 60
src/views/his/statistics/appOrderCountStats.vue

@@ -3,22 +3,32 @@
     <div class="app-content">
       <div class="title">App商城订单统计</div>
       <el-form class="search-form" :inline="true">
-        <el-form-item>
-          <treeselect
-            :clearable="false"
-            v-model="companyId"
-            :options="deptOptions"
-            :show-count="true"
-            placeholder="请选择归属部门"
-          />
+        <el-form-item label="公司名称" prop="companyId">
+          <el-select
+            style="width: 220px"
+            filterable
+            v-model="queryParams.companyId"
+            placeholder="请选择公司名"
+            clearable
+            size="small"
+          >
+            <el-option
+              v-for="item in companys"
+              :key="item.companyId"
+              :label="item.companyName"
+              :value="item.companyId"
+            />
+          </el-select>
         </el-form-item>
-        <el-form-item>
+
+        <el-form-item label="员工" prop="companyUserId">
           <el-select
             filterable
-            v-model="companyUserId"
+            v-model="queryParams.companyUserId"
             placeholder="请选择员工"
             clearable
             size="small"
+            :disabled="!queryParams.companyId"
           >
             <el-option
               v-for="item in users"
@@ -28,6 +38,7 @@
             />
           </el-select>
         </el-form-item>
+
         <el-form-item label="下单日期">
           <el-date-picker
             clearable
@@ -40,6 +51,7 @@
             end-placeholder="结束日期"
           />
         </el-form-item>
+
         <el-form-item>
           <el-button type="primary" icon="el-icon-search" @click="search">搜索</el-button>
         </el-form-item>
@@ -70,61 +82,64 @@
 
 <script>
 import { getAppOrderCount } from "@/api/company/statistics";
-import { getUserListByDeptId } from "@/api/company/companyUser";
-import { treeselect } from "@/api/company/companyDept";
-import Treeselect from "@riophae/vue-treeselect";
-import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import { getUserList } from "@/api/company/companyUser"; // 使用 getUserList(companyId)
+import { getCompanyList } from "@/api/company/company";
 
 export default {
   name: "AppOrderCountStats",
-  components: { Treeselect },
-  watch: {
-    companyId: {
-      handler(newVal) {
-        if (newVal != null) {
-          this.companyUserId = null;
-          this.getUserListByDeptId();
-        } else {
-          this.users = [];
-          this.companyUserId = null;
-        }
-      }
-    }
-  },
   data() {
     return {
-      companyId: null,
-      companyUserId: null,
-      users: [],
-      deptOptions: [],
-      dateRange: [],
-      tableData: []
+      // 仅保留必要查询参数
+      queryParams: {
+        companyId: null,
+        companyUserId: null
+      },
+      companys: [],   // 公司列表
+      users: [],      // 员工列表
+      dateRange: [],  // 日期范围
+      tableData: []   // 表格数据
     };
   },
+  watch: {
+    // 公司变化时,重新加载员工
+    'queryParams.companyId'(newVal) {
+      if (newVal) {
+        this.queryParams.companyUserId = null;
+        this.loadUsers();
+      } else {
+        this.users = [];
+        this.queryParams.companyUserId = null;
+      }
+    }
+  },
   created() {
-    this.loadDeptTree();
+    // 初始化公司下拉列表
+    getCompanyList().then(response => {
+      this.companys = response.data || [];
+    });
   },
   methods: {
-    loadDeptTree() {
-      treeselect().then(response => {
-        this.deptOptions = response.data;
-        if (response.data && response.data.length > 0) {
-          this.companyId = response.data[0].id;
-        }
-      });
-    },
+    // 根据 companyId 加载员工
+    loadUsers() {
+      const companyId = this.queryParams.companyId;
+      if (!companyId) return;
 
-    getUserListByDeptId() {
-      if (!this.companyId) return;
-      getUserListByDeptId({ deptId: this.companyId }).then(response => {
-        this.users = response.data || [];
+      getUserList(companyId).then(res => {
+        if (res.code === 200) {
+          this.users = Array.isArray(res.data) ? res.data : [];
+        } else {
+          this.users = [];
+        }
+      }).catch(() => {
+        this.users = [];
       });
     },
 
+    // 搜索统计
     search() {
       const params = {
-        companyId: this.companyId,
-        companyUserId: this.companyUserId,
+        companyId: this.queryParams.companyId,
+        companyUserId: this.queryParams.companyUserId,
         startTime: this.dateRange?.[0] || undefined,
         endTime: this.dateRange?.[1] ? this.dateRange[1] + " 23:59:59" : undefined
       };
@@ -132,6 +147,8 @@ export default {
       getAppOrderCount(params).then(response => {
         const vo = response.data;
         this.tableData = vo ? [vo] : [];
+      }).catch(() => {
+        this.tableData = [];
       });
     }
   }
@@ -165,15 +182,4 @@ export default {
     }
   }
 }
-
-.vue-treeselect {
-  width: 217px;
-  height: 36px;
-}
-</style>
-
-<style>
-.vue-treeselect__control {
-  display: block;
-}
 </style>

+ 52 - 59
src/views/his/statistics/hisOrderCountStats.vue

@@ -3,22 +3,32 @@
     <div class="app-content">
       <div class="title">互联网医院订单统计</div>
       <el-form class="search-form" :inline="true">
-        <el-form-item>
-          <treeselect
-            :clearable="false"
-            v-model="companyId"
-            :options="deptOptions"
-            :show-count="true"
-            placeholder="请选择归属部门"
-          />
+        <el-form-item label="公司名称" prop="companyId">
+          <el-select
+            style="width: 220px"
+            filterable
+            v-model="queryParams.companyId"
+            placeholder="请选择公司名"
+            clearable
+            size="small"
+          >
+            <el-option
+              v-for="item in companys"
+              :key="item.companyId"
+              :label="item.companyName"
+              :value="item.companyId"
+            />
+          </el-select>
         </el-form-item>
-        <el-form-item>
+
+        <el-form-item label="员工" prop="companyUserId">
           <el-select
             filterable
-            v-model="companyUserId"
+            v-model="queryParams.companyUserId"
             placeholder="请选择员工"
             clearable
             size="small"
+            :disabled="!queryParams.companyId"
           >
             <el-option
               v-for="item in users"
@@ -28,6 +38,7 @@
             />
           </el-select>
         </el-form-item>
+
         <el-form-item label="下单日期">
           <el-date-picker
             clearable
@@ -40,6 +51,7 @@
             end-placeholder="结束日期"
           />
         </el-form-item>
+
         <el-form-item>
           <el-button type="primary" icon="el-icon-search" @click="search">搜索</el-button>
         </el-form-item>
@@ -71,58 +83,50 @@
 <script>
 import { getHisOrderCountStats } from "@/api/company/statistics";
 import { getUserListByDeptId } from "@/api/company/companyUser";
-import { treeselect } from "@/api/company/companyDept";
-import Treeselect from "@riophae/vue-treeselect";
-import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+import { getCompanyList } from "@/api/company/company";
 
 export default {
   name: "HisOrderCountStats",
-  components: { Treeselect },
+  data() {
+    return {
+      // 查询参数统一管理
+      queryParams: {
+        companyId: null,
+        companyUserId: null
+        // 其他参数如 pageNum 等在此场景非必需,可省略
+      },
+      companys: [],        // 公司列表
+      users: [],           // 员工列表
+      dateRange: [],       // 日期范围
+      tableData: []        // 表格数据
+    };
+  },
   watch: {
-    // 监听 companyId 变化,自动重载员工列表
-    companyId: {
+    // 监听公司变化,自动加载员工
+    'queryParams.companyId': {
       handler(newVal) {
         if (newVal != null) {
-          this.companyUserId = null; // 清空已选员工
-          this.getUserListByDeptId();
+          this.queryParams.companyUserId = null; // 清空员工选择
+          this.loadUsers();
         } else {
           this.users = [];
-          this.companyUserId = null;
+          this.queryParams.companyUserId = null;
         }
       },
       immediate: false
     }
   },
-  data() {
-    return {
-      companyId: null,        // 销售公司(部门)ID
-      companyUserId: null,    // 销售人员(员工)ID
-      users: [],              // 员工列表
-      deptOptions: [],        // 部门树形数据
-      dateRange: [],          // 日期范围
-      tableData: []           // 表格数据
-    };
-  },
   created() {
-    this.loadDeptTree();
+    // 初始化公司列表
+    getCompanyList().then(response => {
+      this.companys = response.data || [];
+    });
   },
   methods: {
-    // 加载部门树
-    loadDeptTree() {
-      treeselect().then(response => {
-        this.deptOptions = response.data;
-        if (response.data && response.data.length > 0) {
-          // 默认选中第一个部门
-          this.companyId = response.data[0].id;
-          // 触发 watch 自动加载员工(无需手动调用)
-        }
-      });
-    },
-
-    // 根据 companyId 获取员工列表
-    getUserListByDeptId() {
-      if (!this.companyId) return;
-      getUserListByDeptId({ deptId: this.companyId }).then(response => {
+    // 根据 companyId 加载员工
+    loadUsers() {
+      if (!this.queryParams.companyId) return;
+      getUserListByDeptId({ deptId: this.queryParams.companyId }).then(response => {
         this.users = response.data || [];
       });
     },
@@ -130,8 +134,8 @@ export default {
     // 搜索统计
     search() {
       const params = {
-        companyId: this.companyId,
-        companyUserId: this.companyUserId,
+        companyId: this.queryParams.companyId,
+        companyUserId: this.queryParams.companyUserId,
         startTime: this.dateRange?.[0] || undefined,
         endTime: this.dateRange?.[1] ? this.dateRange[1] + " 23:59:59" : undefined
       };
@@ -172,15 +176,4 @@ export default {
     }
   }
 }
-
-.vue-treeselect {
-  width: 217px;
-  height: 36px;
-}
-</style>
-
-<style>
-.vue-treeselect__control {
-  display: block;
-}
 </style>

+ 4 - 0
src/views/hisStore/store/storeLog.vue

@@ -52,6 +52,7 @@
           placeholder="请输入关键字搜索"
           :remote-method="fetchMain"
           :loading="loadingMain"
+          @change="handleMainChange"
           size="small"
           style="width: 180px"
         >
@@ -258,6 +259,9 @@ export default {
     });
   },
   methods: {
+    handleMainChange(value) {
+      this.queryParams.mainId = value;
+    },
     async fetchMain(query) {
       if (!query) {
         return;

+ 106 - 11
src/views/index.vue

@@ -408,21 +408,41 @@
           </el-card>
         </el-col>
 
+
         <el-col :span="12">
           <el-card shadow="never">
             <div slot="header" class="chart-header">
-              <span>经销商会员观看TOP10</span>
+              <span>经销商看客统计</span>
               <div class="legend">
-                <el-radio-group v-model="viewerType" size="small" @change="handleDealerChartData">
-                  <el-radio-button label="0">按观看人数</el-radio-button>
-                  <el-radio-button label="1">按完播人数</el-radio-button>
-                </el-radio-group>
+                <div class="legend-item">
+                  <span class="dot viewer-dot"></span>
+                  <span>观看人数</span>
+                </div>
+                <div class="legend-item">
+                  <span class="dot complete-dot"></span>
+                  <span>完播人数</span>
+                </div>
               </div>
-              <!--              <el-button size="small" plain class="view-more">经销商统计 <i class="el-icon-arrow-right"></i></el-button>-->
             </div>
-            <div ref="dealerChart" class="chart-container"></div>
+            <div ref="dealerChartNew" class="chart-container"></div>
           </el-card>
         </el-col>
+
+<!--        <el-col :span="12">-->
+<!--          <el-card shadow="never">-->
+<!--            <div slot="header" class="chart-header">-->
+<!--              <span>经销商会员观看TOP10</span>-->
+<!--              <div class="legend">-->
+<!--                <el-radio-group v-model="viewerType" size="small" @change="handleDealerChartData">-->
+<!--                  <el-radio-button label="0">按观看人数</el-radio-button>-->
+<!--                  <el-radio-button label="1">按完播人数</el-radio-button>-->
+<!--                </el-radio-group>-->
+<!--              </div>-->
+<!--              &lt;!&ndash;              <el-button size="small" plain class="view-more">经销商统计 <i class="el-icon-arrow-right"></i></el-button>&ndash;&gt;-->
+<!--            </div>-->
+<!--            <div ref="dealerChart" class="chart-container"></div>-->
+<!--          </el-card>-->
+<!--        </el-col>-->
       </el-row>
     </transition>
     <transition name="fade">
@@ -553,7 +573,7 @@ import {
   authorizationInfo,
   dealerAggregated, deaMemberTopTen, rechargeComsumption, rewardMoneyTopTen, rewardMoneyTrend,
   smsBalance, thisMonthOrderCount, thisMonthRecvCount, trafficLog,
-  watchCourseTopTen, watchEndPlayTrend
+  watchCourseTopTen, watchEndPlayTrend,getWatchCourseStatisticsData
 } from "@/api/statistics/statistics";
 import dayjs from 'dayjs';
 import { listDept } from '@/api/system/dept'
@@ -600,6 +620,45 @@ const viewCharOption = {
   ]
 }
 
+const dealerOptionNew = {
+  tooltip: {
+    trigger: 'axis',
+    axisPointer: {
+      type: 'shadow'
+    }
+  },
+  grid: {
+    left: '3%',
+    right: '4%',
+    bottom: '3%',
+    containLabel: true
+  },
+  xAxis: {
+    type: 'category',
+  },
+  yAxis: {
+    type: 'value'
+  },
+  series: [
+    {
+      name: '观看人数',
+      type: 'bar',
+      data: [],
+      itemStyle: {
+        color: '#409EFF'
+      }
+    },
+    {
+      name: '完播人数',
+      type: 'bar',
+      data: [],
+      itemStyle: {
+        color: '#67C23A'
+      }
+    }
+  ]
+}
+
 const thisMonthOrderCountOption = {
   tooltip: {
     trigger: 'axis',
@@ -913,6 +972,7 @@ export default {
       smsRemainCount: 0,
       viewerType: '0',
       viewerChart: null,
+      dealerChartNew: null,
       userTypeText: process.env.VUE_APP_COURSE_DEFAULT==1?"会员":"企微",
       userType: process.env.VUE_APP_COURSE_DEFAULT,
       dealerChart: null,
@@ -985,18 +1045,21 @@ export default {
   },
   mounted() {
     this.$nextTick(() => {
-      this.initViewerChart()
-      this.initDealerChart()
+      this.initViewerChart();
+      this.initDealerChartNew();
+      this.initDealerChart();
       this.initCourseWatchChart();
       this.initAnswerRedPackViewerChart();
       this.initAnswerRedPackMoneyViewerChart();
       this.initThisMonthOrderChart();
-      this.initThisMonthRecvChart()
+      this.initThisMonthRecvChart();
+
 
       // 监听窗口大小变化,重新渲染图表
       window.addEventListener('resize', () => {
         this.viewerChart && this.viewerChart.resize()
         this.dealerChart && this.dealerChart.resize()
+        this.dealerChartNew && this.dealerChartNew.resize()
       })
     })
   },
@@ -1277,6 +1340,7 @@ export default {
 
       this.handleCourseWatchChart()
       this.handleViewChartData()
+      this.handleDealerChartDataNew()
 
       // 经销商会员观看TOP10
       this.handleDealerChartData()
@@ -1338,6 +1402,7 @@ export default {
       if (this.selectedDiv === 0) {
         this.handleViewChartData()
         this.handleDealerChartData()
+        this.handleDealerChartDataNew()
       } else if (this.selectedDiv === 1) {
         this.handleCourseWatchChart()
       } else if (this.selectedDiv === 2) {
@@ -1415,6 +1480,7 @@ export default {
       if (this.selectedDiv === 0) {
         this.handleViewChartData()
         this.handleDealerChartData()
+        this.handleDealerChartDataNew()
       } else if (this.selectedDiv === 1) {
         this.handleCourseWatchChart()
       } else if (this.selectedDiv === 2) {
@@ -1538,12 +1604,36 @@ export default {
         }
       })
 
+    },
+    handleDealerChartDataNew() {
+      let param = this.getParam();
+
+      getWatchCourseStatisticsData({ ...param }).then(res => {
+        if (res.code === 200) {
+          console.log(res.data);
+          // 根据实际数据结构调整
+          let data = res.data;
+          let watchUserCountList = data.map(e => e.watchCount);     // 观看次数
+          let completedUserCountList = data.map(e => e.finishCount); // 完播次数
+          let xAxis = data.map(e => e.companyName);                 // X轴使用公司名称
+
+          // 更新图表配置
+          dealerOptionNew.series[0].data = watchUserCountList;
+          dealerOptionNew.series[1].data = completedUserCountList;
+          dealerOptionNew.xAxis.data = xAxis;
+
+          this.dealerChartNew.setOption(dealerOptionNew);
+
+        }
+      })
+
     },
     initThisMonthOrderChart() {
       this.thisMonthOrderChart = echarts.init(this.$refs.viewerOrderChart)
       this.thisMonthOrderChart.setOption(thisMonthOrderCountOption)
     },
     initThisMonthRecvChart() {
+
       this.thisMonthRecvChart = echarts.init(this.$refs.viewerReceiveChart)
       this.thisMonthRecvChart.setOption(thisMonthOrderCountOption)
     },
@@ -1551,6 +1641,10 @@ export default {
       this.viewerChart = echarts.init(this.$refs.viewerChart)
       this.viewerChart.setOption(viewCharOption)
     },
+    initDealerChartNew() {
+      this.dealerChartNew = echarts.init(this.$refs.dealerChartNew)
+      this.dealerChartNew.setOption(dealerOptionNew)
+    },
     initDealerChart() {
       this.dealerChart = echarts.init(this.$refs.dealerChart)
 
@@ -1582,6 +1676,7 @@ export default {
     // window.removeEventListener('resize', this.resizeHandler)
     this.viewerChart && this.viewerChart.dispose()
     this.dealerChart && this.dealerChart.dispose()
+    this.dealerChartNew && this.dealerChartNew.dispose()
   }
 }
 </script>

+ 18 - 1
src/views/qw/sop/sop.vue

@@ -1,6 +1,16 @@
 <template>
   <div class="app-container">
     <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="销售公司" prop="companyId">
+        <el-select filterable v-model="queryParams.companyId" clearable placeholder="请选择公司名" size="small">
+          <el-option
+            v-for="item in companys"
+            :key="item.companyId"
+            :label="item.companyName"
+            :value="item.companyId"
+          />
+        </el-select>
+      </el-form-item>
       <el-form-item label="规则编号" prop="id">
         <el-input
           v-model="queryParams.id"
@@ -150,6 +160,7 @@
 import { listSop, exportSop, } from "@/api/qw/sop";
 
 import sopLogsDetails from '@/views/qw/sopLogs/sopLogsList.vue'
+import { getCompanyList } from '@/api/company/company'
 export default {
   name: "Sop",
     components: { sopLogsDetails},
@@ -168,6 +179,7 @@ export default {
       myQwCompanyList:[],
       //销售员工列表
       companyUserLists:[],
+      companys: [],
       courseList:[],
       // videoList:[],
       tags:null,
@@ -227,7 +239,8 @@ export default {
         setting: null,
         createBy: null,
         corpId: null,
-        createTime: null
+        createTime: null,
+        companyId: null
       },
       sopLogsDialog:{
         title:'',
@@ -272,6 +285,10 @@ export default {
     this.getDicts("sys_qw_sop_type").then(response => {
       this.sysQwSopType = response.data;
     });
+
+    getCompanyList().then(response => {
+      this.companys = response.data;
+    });
     this.getList();
 
   },

+ 7 - 0
src/views/system/config/config.vue

@@ -1410,6 +1410,13 @@
               active-color="#13ce66"
               inactive-color="#ff4949">
             </el-switch>
+          </el-form-item>
+           <el-form-item label="侧边栏是否仅展示当天课程" prop="showQwCode">
+            <el-switch
+              v-model="form18.sidebarOnlyShowTodayCourse"
+              active-color="#13ce66"
+              inactive-color="#ff4949">
+            </el-switch>
           </el-form-item>
           <div class="line"></div>
           <div style="float:right;margin-right:20px">