Переглянути джерело

Merge remote-tracking branch 'origin/master'

xgb 1 день тому
батько
коміт
21232bd186

+ 2 - 1
.env.development

@@ -30,7 +30,8 @@ VUE_APP_VIDEO_LINE_2 = https://xfkobs.ylrztop.com
 VUE_APP_VIDEO_URL = https://myhkvolcengine.ylrztop.com
 #火山云视频点播空间名
 VUE_APP_HSY_SPACE = myhk-2114522511
-
+#直播解码路径
+LIVE_PATH = /live
 
 VUE_APP_LIVE_WS_URL = ws://127.0.0.1:7114/ws
 

+ 7 - 0
.env.prod-heyantang

@@ -26,7 +26,13 @@ VUE_APP_COS_REGION = ap-chongqing
 VUE_APP_VIDEO_LINE_1 = https://cdhyttcpv.ylrzcloud.com
 # 线路二地址
 VUE_APP_VIDEO_LINE_2 = https://cdhytobs.ylrztop.com
+#火山云视频地址域名
+VUE_APP_VIDEO_URL = https://cdhytvolcengine.ylrztop.com
+#火山云视频点播空间名
+VUE_APP_HSY_SPACE = cdhyt-2114522511
 
+#直播解码路径
+VUE_APP_LIVE_PATH = /live
 # 开发环境配置
 ENV = 'production'
 
@@ -41,3 +47,4 @@ VUE_CLI_BABEL_TRANSPILE_MODULES = true
 
 
 VUE_APP_LIVE_WS_URL = wss://liveapp.yytcdta.com/ws
+

+ 4 - 0
.env.prod-nmgyt

@@ -26,6 +26,10 @@ VUE_APP_COS_REGION = ap-chongqing
 VUE_APP_VIDEO_LINE_1 = https://nmgyttcpv.ylrzcloud.com
 # 线路二地址
 VUE_APP_VIDEO_LINE_2 = https://nmgytobs.ylrztop.com
+#火山云视频地址域名
+VUE_APP_VIDEO_URL = https://nmgmytvolcengine.ylrztop.com
+#火山云视频点播空间名
+VUE_APP_HSY_SPACE = nmgmyt-2114522511
 
 # 开发环境配置
 ENV = 'production'

+ 4 - 0
.env.prod-zkzh

@@ -26,6 +26,10 @@ VUE_APP_COS_REGION = ap-chongqing
 VUE_APP_VIDEO_LINE_1 = https://zkzhtcpv.ylrzcloud.com
 # 线路二地址
 VUE_APP_VIDEO_LINE_2 = https://zkzhobs.ylrztop.com
+#火山云视频地址域名
+VUE_APP_VIDEO_URL = https://sxzkvolcengine.ylrztop.com
+#火山云视频点播空间名
+VUE_APP_HSY_SPACE = sxzk-2114522511
 # 生产环境配置
 ENV = 'production'
 

+ 9 - 0
src/api/his/storePayment.js

@@ -9,6 +9,15 @@ export function listStorePayment(query) {
   })
 }
 
+// 查询支付明细列表
+export function listStorePaymentError(query) {
+  return request({
+    url: '/his/storePayment/error/list',
+    method: 'get',
+    params: query
+  })
+}
+
 // 查询支付明细详细
 export function getStorePayment(paymentId) {
   return request({

+ 9 - 1
src/api/live/live.js

@@ -157,4 +157,12 @@ export function getTagsListByCorpId(qwTagGroup) {
     method: 'get',
     params:qwTagGroup
   })
-}
+}
+
+// 清除直播间缓存
+export function clearLiveCache(liveId) {
+  return request({
+    url: '/live/live/clearCache/' + liveId,
+    method: 'post'
+  })
+}

+ 2 - 2
src/api/live/liveData.js

@@ -28,9 +28,9 @@ export function getLiveDataDetailBySql(liveId) {
   })
 }
 
-export function getLiveUserDetailListBySql(liveId) {
+export function getLiveUserDetailListBySql(liveId, pageNum, pageSize) {
   return request({
-    url: '/liveData/liveData/getLiveUserDetailListBySql?liveId=' + liveId,
+    url: '/liveData/liveData/getLiveUserDetailListBySql?liveId=' + liveId + '&pageNum=' + (pageNum || 1) + '&pageSize=' + (pageSize || 100),
     method: 'get'
   })
 }

+ 8 - 0
src/api/qw/friendWelcome.js

@@ -8,3 +8,11 @@ export function listFriendWelcome(query) {
     params: query
   })
 }
+
+// 查询好友欢迎语详细
+export function getFriendWelcome(id) {
+  return request({
+    url: '/qw/friendWelcome/' + id,
+    method: 'get'
+  })
+}

+ 1 - 1
src/components/LiveVideoUpload/index.vue

@@ -209,7 +209,7 @@ export default {
     async uploadVideoToTxPcdn() {
       try {
         const file = this.fileList[0].raw;
-        const data = await uploadObject(file, this.updateTxProgress, this.type);
+        const data = await uploadObject(file, this.updateTxProgress, 3);
         console.log("腾讯COS返回========>", data);
         console.log("isPrivate=======>", this.isPrivate)
         let line_1 = '';

+ 13 - 1
src/utils/cos.js

@@ -39,6 +39,7 @@ export const uploadObject = async (file, onProgress, type, callBackUp) => {
     })
 
     console.log("初始化成功")
+    console.log(process.env)
     const fileName = file.name || ""
     const upload_file_name = new Date().getTime() + "." + fileName.split(".")[fileName.split(".").length - 1]
     const date = new Date()
@@ -48,7 +49,18 @@ export const uploadObject = async (file, onProgress, type, callBackUp) => {
     const uploadDay = `${year}${month}${strDate}`
     const videoKey = `/userVideo/${uploadDay}/${upload_file_name}`
     const courseKey = `/course/${uploadDay}/${upload_file_name}`
-    const key = type === 1 ? courseKey : videoKey
+    let liveKey;
+    console.log("LIVE_PATH value:", process.env.VUE_APP_LIVE_PATH);  // 添加这行查看实际值
+    console.log("Type of LIVE_PATH:", typeof process.env.VUE_APP_LIVE_PATH);  // 查看类型
+// 检查是否是空字符串或只有空格
+    if (process.env.VUE_APP_LIVE_PATH && process.env.VUE_APP_LIVE_PATH.trim() !== '') {
+      liveKey = `${process.env.VUE_APP_LIVE_PATH.trim()}/${uploadDay}/${upload_file_name}`;
+    } else {
+      liveKey = `/course/${uploadDay}/${upload_file_name}`;
+    }
+    console.log("liveKey={}",liveKey);
+    const key = type === 3 ? liveKey : (type === 1 ? courseKey : videoKey);
+
     console.log("开始上传")
 
     return new Promise((resolve, reject) => {

+ 187 - 0
src/views/his/storePayment/errorIndex.vue

@@ -0,0 +1,187 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="90px">
+<!--      <el-form-item label="订单编号" prop="businessCode">-->
+<!--        <el-input-->
+<!--          v-model="queryParams.businessCode"-->
+<!--          placeholder="请输入订单号"-->
+<!--          clearable-->
+<!--          size="small"-->
+<!--          @keyup.enter.native="handleQuery"-->
+<!--        />-->
+<!--      </el-form-item>-->
+
+      <el-form-item label="外部订单" prop="tradeNo">
+        <el-input
+          v-model="queryParams.tradeNo"
+          placeholder="请输入外部订单号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+
+
+
+      <el-form-item label="业务类型" prop="businessType">
+        <el-select v-model="queryParams.businessType" placeholder="请选择业务类型" clearable size="small">
+          <el-option
+            v-for="dict in busineOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </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-table height="600" v-loading="loading" border :data="storePaymentList" @selection-change="handleSelectionChange">
+<!--      <el-table-column type="selection" width="55" align="center" />-->
+      <el-table-column label="订单编号" align="center" prop="orderNo" width="170px"/>
+      <el-table-column label="外部单号" align="center" prop="orderFlowNo" width="350px"/>
+      <el-table-column label="业务类型 " align="center" prop="businessType" width="100">
+        <template slot-scope="scope">
+          <dict-tag :options="busineOptions" :value="scope.row.businessType"/>
+        </template>
+      </el-table-column>
+<!--      <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="msg" />
+      <el-table-column label="创建时间" align="center" prop="createTime" width="155" />
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+  </div>
+</template>
+
+<script>
+import { listStorePaymentError } from "@/api/his/storePayment";
+export default {
+  name: "StoreErrorPayment",
+  data() {
+    return {
+      busineOptions:[],
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 支付明细表格数据
+      storePaymentList: [],
+      payModeOptions:[],
+      shareOptions:[],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 状态 0未处理 1已处理
+      statusOptions: [
+        {dictValue:'0',dictLabel:"未处理"},
+        {dictValue:'1',dictLabel:"已处理"}
+      ],
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        businessType: null,
+        status: '0',
+
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+      }
+    };
+  },
+  created() {
+    this.getList();
+
+    this.getDicts("sys_store_payment_business_type").then(response => {
+      this.busineOptions = response.data;
+    });
+  },
+  methods: {
+    /** 查询支付明细列表 */
+    getList() {
+      this.loading = true;
+      listStorePaymentError(this.queryParams).then(response => {
+        this.storePaymentList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        paymentId: null,
+        payCode: null,
+        payTypeCode: null,
+        payMoney: null,
+        payTime: null,
+        createTime: null,
+        tradeNo: null,
+        userId: null,
+        openId: null,
+        businessType: null,
+        businessId: null,
+        status: 0,
+        remark: null,
+        bankTransactionId: null,
+        bankSerialNo: null,
+        refundMoney: null,
+        refundTime: null,
+        storeId: 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.paymentId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    }
+  }
+};
+</script>

+ 2 - 1
src/views/hisStore/storePayment/index.vue

@@ -375,6 +375,7 @@ export default {
         deptId: null,
         bankTransactionId:null,
         companyUserNickName:null,
+        appId:null,
       },
       // 表单参数
       form: {},
@@ -517,7 +518,7 @@ export default {
     },
     /** 重置按钮操作 */
     resetQuery() {
-      his.dateRange=[];
+      this.dateRange=[];
       this.refundDateRange=[];
       this.createTimeRange=[];
       this.resetForm("queryForm");

+ 29 - 2
src/views/hisStore/storeProduct/index.vue

@@ -869,6 +869,16 @@
             />
           </el-select>
         </el-form-item>
+        <el-form-item label="所属小程序" prop="appIds">
+          <el-select style="width: 240px" v-model="appIds" placeholder="请选择所属小程序" clearable size="small" multiple>
+            <el-option
+              v-for="dict in appMallOptions"
+              :key="dict.appid"
+              :label="dict.name + '(' + dict.appid + ')'"
+              :value="dict.appid"
+            />
+          </el-select>
+        </el-form-item>
         <el-form-item label="退货地址" prop="returnAddress">
           <el-input v-model="form.returnAddress" type="textarea" :rows="1" placeholder="请输入退货地址" />
         </el-form-item>
@@ -944,6 +954,7 @@ import Material from '@/components/Material'
 import singleImg from '@/components/Material/single'
 import { getCompanyList } from "@/api/company/company";
 import { listStore } from '@/api/hisStore/store'
+import {list as getAppMallOptions} from "@/api/course/coursePlaySourceConfig";
 export default {
   name: "HisStoreProduct",
   components: {
@@ -1061,7 +1072,9 @@ export default {
       title: "",
       // 是否显示弹出层
       open: false,
-
+      // 小程序列表
+      appMallOptions:[],
+      appIds:[], // 选择的小程序
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -1214,6 +1227,9 @@ export default {
     getCompanyList().then(response => {
       this.companyOptions = response.data;
     });
+    // 查询小程序
+    this.getAppMallOptions();
+
     listStore(this.storeForm).then(response => {
       this.storeOptions = response.rows;
     });
@@ -1221,6 +1237,11 @@ export default {
     this.getList();
   },
   methods: {
+    getAppMallOptions() {
+      getAppMallOptions({pageNum:1,pageSize:100}).then(response => {
+        this.appMallOptions = response.rows;
+      })
+    },
     getStatusText(row) {
       console.log()
       if (row.isAudit == 0) {
@@ -1622,6 +1643,7 @@ export default {
         if (response.data.companyIds != null && response.data.companyIds != undefined && response.data.companyIds.length > 0) {
           this.form.companyIds = response.data.companyIds.split(',').map(Number);
         }
+        this.appIds = this.form.appIds ? this.form.appIds.split(',') : [];
         setTimeout(() => {
           that.generate();
         }, 200);
@@ -1682,7 +1704,12 @@ export default {
           if (this.form.companyIds != null && this.form.companyIds != undefined) {
             this.form.companyIds = this.form.companyIds.join(',');
           }
-          addOrEdit(this.form).then(response => {
+          // 小程序
+          const params = {
+            ...this.form,
+            appIds: this.appIds.join(',') // 数组转字符串
+          };
+          addOrEdit(params).then(response => {
             if (response.code === 200) {
               // 根据是否有productId判断是新增还是修改
               if (this.form.productId) {

+ 13 - 1
src/views/hisStore/storeProductAudit/index.vue

@@ -644,6 +644,16 @@
             />
           </el-select>
         </el-form-item>
+        <el-form-item label="所属小程序" prop="appIds">
+          <el-select style="width: 240px" v-model="appIds" placeholder="请选择所属小程序" clearable size="small" multiple>
+<!--            <el-option-->
+<!--              v-for="dict in appMallOptions"-->
+<!--              :key="dict.appid"-->
+<!--              :label="dict.name + '(' + dict.appid + ')'"-->
+<!--              :value="dict.appid"-->
+<!--            />-->
+          </el-select>
+        </el-form-item>
         <el-form-item label="国药准字" v-if="form.productType===2" prop="prescribeCode">
           <el-input v-model="form.prescribeCode" placeholder="请输入国药准字" />
         </el-form-item>
@@ -839,7 +849,7 @@ export default {
       title: "",
       // 是否显示弹出层
       open: false,
-
+      appIds:[],
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -1341,6 +1351,8 @@ export default {
         if (response.data.companyIds != null && response.data.companyIds != undefined && response.data.companyIds.length > 0) {
           this.form.companyIds = response.data.companyIds.split(',').map(Number);
         }
+
+        this.appIds = this.form.appIds ? this.form.appIds.split(',') : [];
         setTimeout(() => {
           that.generate();
         }, 200);

+ 33 - 0
src/views/live/live/index.vue

@@ -200,6 +200,12 @@
       @selection-change="handleSelectionChange"
     >
       <el-table-column type="selection" width="55"></el-table-column>
+      <el-table-column
+        label="直播ID"
+        align="center"
+        prop="liveId"
+        width="100"
+      />
       <el-table-column
         label="直播封面"
         align="center"
@@ -303,6 +309,14 @@
             v-hasPermi="['live:console:list']"
             >进入直播间</el-button
           >
+          <el-button
+            size="mini"
+            type="text"
+            icon="el-icon-delete"
+            @click="handleClearCache(scope.row)"
+            v-hasPermi="['live:live:edit']"
+            >清理缓存</el-button
+          >
           <el-dropdown trigger="hover">
             <el-button size="mini" type="text" icon="el-icon-more">
               更多
@@ -670,6 +684,7 @@ import {
   getCompanyDropList,
   getQwCorpList,
   getTagsListByCorpId,
+  clearLiveCache,
 } from "@/api/live/live";
 import Editor from "@/components/Editor/wang";
 import user from "@/store/modules/user";
@@ -1299,6 +1314,24 @@ export default {
         })
         .catch(() => {});
     },
+    /** 清理缓存按钮操作 */
+    handleClearCache(row) {
+      this.$confirm("是否确认清理该直播间的缓存?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          clearLiveCache(row.liveId).then((response) => {
+            if (response.code === 200) {
+              this.msgSuccess("缓存清理成功");
+            } else {
+              this.msgError(response.msg || "缓存清理失败");
+            }
+          });
+        })
+        .catch(() => {});
+    },
     /** 导出按钮操作 */
     handleExport() {
       const queryParams = this.queryParams;

+ 68 - 152
src/views/live/liveConsole/LivePlayer.vue

@@ -1,22 +1,9 @@
 <template>
   <div class="live-player">
-    <!-- 修改:所有录播和回放都使用同一个video元素,MP4和HLS都支持 -->
-    <video
-      v-if="videoParam.liveType == 2 || videoParam.liveType == 3"
-      ref="videoPlayer"
-      :loop="videoParam.liveType == 2"
-      autoplay
-      class="player"
-    >
-      <!-- 去掉type,让浏览器自动检测 -->
+    <video v-if="videoParam.liveType == 2" ref="videoPlayer" loop autoplay class="player">
+      <source :src="videoParam.videoUrl" type="application/x-mpegURL">
     </video>
-
-    <video
-      v-if="videoParam.liveType == 1"
-      ref="livePlayer"
-      autoplay
-      class="player"
-    >
+    <video v-if="videoParam.liveType == 1" ref="livePlayer" loop autoplay class="player">
     </video>
   </div>
 </template>
@@ -40,33 +27,23 @@ export default {
   },
   data() {
     return {
-      videoDuration: 0,
-      startTime: 0,
-      hls: null,
-      liveHls: null // 分开管理直播和录播的HLS实例
+      videoDuration: 0, // 视频总时长(秒)
+      startTime: 0, // 开播时间戳(毫秒)
+      hls: null, // HLS 实例
     };
   },
   mounted() {
-    this.initPlayer();
+
+    // 这里可以添加播放器初始化逻辑
   },
   methods: {
     videoPlay(url) {
-      const videoElement = this.$refs.videoPlayer;
-      if (!videoElement) {
-        console.error('找不到 video 元素');
-        return;
-      }
-
-      // 判断是否是MP4格式
-      const isMp4 = url.toLowerCase().endsWith('.mp4') ||
-        url.toLowerCase().includes('.mp4?');
-
-      // 判断是否是HLS格式(m3u8)
-      const isHls = url.toLowerCase().endsWith('.m3u8') ||
-        url.toLowerCase().includes('.m3u8?');
-
-      if (isHls && Hls.isSupported()) {
-        // HLS格式使用hls.js播放
+      if (Hls.isSupported()) {
+        const videoElement = this.$refs.videoPlayer
+        if (!videoElement) {
+          console.error('找不到 video 元素')
+          return
+        }
         this.hls = new Hls();
         this.hls.attachMedia(videoElement);
         this.hls.on(Hls.Events.MEDIA_ATTACHED, () => {
@@ -78,165 +55,104 @@ export default {
         this.hls.on(Hls.Events.ERROR, (event, data) => {
           console.error('HLS 错误:', data);
         });
-
-        // 录播的时间位置计算
+        // 1. 初始化开播时间
+        this.startTime = new Date(this.videoParam.startTime).getTime();
         if (this.videoParam.liveType === 2) {
+          // 2. 监听视频元数据加载完成(获取视频时长)
           videoElement.addEventListener('loadedmetadata', () => {
-            this.videoDuration = videoElement.duration;
-            this.updateVideoPosition(videoElement);
-          });
-        }
+            this.videoDuration = videoElement.duration; // 获取视频时长(秒)
 
-      } else if (isMp4 || !isHls) {
-        // MP4格式或非HLS格式直接使用video元素播放
-        videoElement.src = url;
-
-        // 录播的时间位置计算
-        if (this.videoParam.liveType === 2) {
-          videoElement.addEventListener('loadedmetadata', () => {
-            this.videoDuration = videoElement.duration;
+            // 初始化视频播放位置
             this.updateVideoPosition(videoElement);
+
           });
         }
-
-        // 触发播放
-        videoElement.load();
-        videoElement.play().catch(e => {
-          console.warn('自动播放失败:', e);
-        });
-
       } else {
-        // 不支持HLS的浏览器,尝试直接播放
-        console.warn('浏览器不支持HLS,尝试直接播放');
-        videoElement.src = url;
-        videoElement.load();
-        videoElement.play().catch(e => {
-          console.warn('播放失败:', e);
-        });
+        console.error('浏览器不支持 HLS')
       }
     },
-
-    updateVideoPosition(video) {
-      const currentTime = new Date().getTime();
-      this.startTime = new Date(this.videoParam.startTime).getTime();
-      const elapsedTime = currentTime - this.startTime;
-
+    updateVideoPosition(video){
+      const currentTime = new Date().getTime(); // 当前时间戳(毫秒)
+      const elapsedTime = currentTime - this.startTime; // 已流逝时间(毫秒)
       if (elapsedTime < 0) {
+        // 未开播:视频停在初始位置
         video.currentTime = 0;
         return;
       }
 
-      const elapsedSeconds = elapsedTime / 1000;
-      if (this.videoDuration > 0) {
-        video.currentTime = elapsedSeconds % this.videoDuration;
-      }
+      // 已开播:计算视频循环后的位置(流逝时间 % 视频时长)
+      const elapsedSeconds = elapsedTime / 1000; // 转换为秒
+      // 视频内的播放位置(秒)
+      // 设置视频播放位置
+      video.currentTime = elapsedSeconds % this.videoDuration;
     },
-
     livePlay(url) {
       if (Hls.isSupported()) {
-        const videoElement = this.$refs.livePlayer;
+        const videoElement = this.$refs.livePlayer
         if (!videoElement) {
-          console.error('找不到 video 元素');
-          return;
+          console.error('找不到 video 元素')
+          return
         }
-
-        this.liveHls = new Hls();
-        this.liveHls.attachMedia(videoElement);
-        this.liveHls.on(Hls.Events.MEDIA_ATTACHED, () => {
-          this.liveHls.loadSource(url);
-          this.liveHls.on(Hls.Events.STREAM_LOADED, (event, data) => {
+        this.hls = new Hls();
+        this.hls.attachMedia(videoElement);
+        this.hls.on(Hls.Events.MEDIA_ATTACHED, () => {
+          this.hls.loadSource(url);
+          this.hls.on(Hls.Events.STREAM_LOADED, (event, data) => {
             videoElement.play();
           });
         });
-        this.liveHls.on(Hls.Events.ERROR, (event, data) => {
+        this.hls.on(Hls.Events.ERROR, (event, data) => {
           console.error('HLS 错误:', data);
         });
-
       } else {
-        // 浏览器原生支持HLS(如Safari)
-        const videoElement = this.$refs.livePlayer;
-        if (videoElement.canPlayType('application/vnd.apple.mpegurl')) {
-          videoElement.src = url;
-          videoElement.play().catch(e => {
-            console.warn('自动播放失败:', e);
-          });
-        } else {
-          console.error('浏览器不支持 HLS');
-        }
+        console.error('浏览器不支持 HLS')
       }
     },
-
     initPlayer() {
-      // 清理之前的实例
-      if (this.hls) {
-        this.hls.destroy();
-        this.hls = null;
-      }
-      if (this.liveHls) {
-        this.liveHls.destroy();
-        this.liveHls = null;
-      }
 
       if (this.videoParam.liveType === 1) {
         // 直播
         const isUrl = this.videoParam.livingUrl === null || this.videoParam.livingUrl.trim() === '';
         if (isUrl) {
-          console.error('直播地址为空,无法初始化播放器');
-          return;
+          console.error('直播地址为空,无法初始化播放器')
+          return
         }
         this.$nextTick(() => {
           this.livePlay(this.videoParam.livingUrl);
-        });
+        })
         return;
       }
-
-      const viUrl = this.videoParam.videoUrl === null || this.videoParam.videoUrl.trim() === '';
+      const viUrl = this.videoParam.videoUrl === null || this.videoParam.videoUrl.trim() === ''
       if (viUrl) {
-        console.error('播放地址为空,无法初始化播放器');
-        return;
+        console.error('播放地址为空,无法初始化播放器')
+        return
       }
-
-      if (this.videoParam.liveType === 2 || this.videoParam.liveType === 3) {
-        // 录播或直播回放
-        this.$nextTick(() => {
-          this.videoPlay(this.videoParam.videoUrl);
-        });
-      } else {
-        console.error('直播类型错误,无法初始化播放器');
+      if(this.videoParam.liveType === 2){
+        // 录播
+        this.videoPlay(this.videoParam.videoUrl);
+      } else if(this.videoParam.liveType === 3){
+        // 直播回放
+        this.videoPlay(this.videoParam.videoUrl);
+      }else {
+        console.error('直播类型错误,无法初始化播放器')
       }
+      // 创建播放器实例
+      const videoPlayer = this.$refs.videoPlayer;
+      // 添加播放器事件监听器
+      videoPlayer.addEventListener('play', () => {
+        console.log('播放器已开始播放');
+      });
+      videoPlayer.addEventListener('pause', () => {
+        console.log('播放器已暂停');
+      });
+      videoPlayer.addEventListener('ended', () => {
+        console.log('播放器已结束');
+      });
     }
   },
-
-  watch: {
-    // 监听videoParam变化,重新初始化播放器
-    videoParam: {
-      handler() {
-        this.$nextTick(() => {
-          this.initPlayer();
-        });
-      },
-      deep: true
-    }
-  },
-
   beforeDestroy() {
-    // 销毁HLS实例
-    this.hls?.destroy();
-    this.liveHls?.destroy();
-
-    // 清理video元素
-    const videoElements = [
-      this.$refs.videoPlayer,
-      this.$refs.livePlayer
-    ];
-
-    videoElements.forEach(video => {
-      if (video) {
-        video.pause();
-        video.src = '';
-        video.load();
-      }
-    });
+    this.hls?.destroy()
+    // 销毁播放器实例
   }
 };
 </script>

+ 31 - 10
src/views/live/liveData/index.vue

@@ -363,25 +363,25 @@
             </el-col>
             <el-col :span="12">
               <div class="detail-item">
-                <span class="detail-label">>20分钟人数(直播):</span>
+                <span class="detail-label">>=20分钟人数(直播):</span>
                 <span class="detail-value">{{ detailData.liveOver20Minutes || 0 }}</span>
               </div>
             </el-col>
             <el-col :span="12">
               <div class="detail-item">
-                <span class="detail-label">>30分钟人数(直播):</span>
+                <span class="detail-label">>=30分钟人数(直播):</span>
                 <span class="detail-value">{{ detailData.liveOver30Minutes || 0 }}</span>
               </div>
             </el-col>
             <el-col :span="12">
               <div class="detail-item">
-                <span class="detail-label">到课完课率直播(>20分钟):</span>
+                <span class="detail-label">到课完课率直播(>=20分钟):</span>
                 <span class="detail-value">{{ formatPercent(detailData.liveCompletionRate20) }}</span>
               </div>
             </el-col>
             <el-col :span="12">
               <div class="detail-item">
-                <span class="detail-label">到课完课率直播(>30分钟):</span>
+                <span class="detail-label">到课完课率直播(>=30分钟):</span>
                 <span class="detail-value">{{ formatPercent(detailData.liveCompletionRate30) }}</span>
               </div>
             </el-col>
@@ -399,25 +399,25 @@
             </el-col>
             <el-col :span="12">
               <div class="detail-item">
-                <span class="detail-label">>20分钟人数(回放):</span>
+                <span class="detail-label">>=20分钟人数(回放):</span>
                 <span class="detail-value">{{ detailData.playbackOver20Minutes || 0 }}</span>
               </div>
             </el-col>
             <el-col :span="12">
               <div class="detail-item">
-                <span class="detail-label">>30分钟人数(回放):</span>
+                <span class="detail-label">>=30分钟人数(回放):</span>
                 <span class="detail-value">{{ detailData.playbackOver30Minutes || 0 }}</span>
               </div>
             </el-col>
             <el-col :span="12">
               <div class="detail-item">
-                <span class="detail-label">到课完课率回放(>20分钟):</span>
+                <span class="detail-label">到课完课率回放(>=20分钟):</span>
                 <span class="detail-value">{{ formatPercent(detailData.playbackCompletionRate20) }}</span>
               </div>
             </el-col>
             <el-col :span="12">
               <div class="detail-item">
-                <span class="detail-label">到课完课率回放(>30分钟):</span>
+                <span class="detail-label">到课完课率回放(>=30分钟):</span>
                 <span class="detail-value">{{ formatPercent(detailData.playbackCompletionRate30) }}</span>
               </div>
             </el-col>
@@ -555,6 +555,16 @@
           <el-table-column prop="companyName" label="分公司" min-width="150"></el-table-column>
           <el-table-column prop="salesName" label="销售" min-width="120"></el-table-column>
         </el-table>
+        <!-- 用户详情分页组件 -->
+        <pagination
+          v-show="userDetailTotal > 0"
+          :total="userDetailTotal"
+          :page.sync="userDetailQueryParams.pageNum"
+          :limit.sync="userDetailQueryParams.pageSize"
+          :page-sizes="[10, 100, 1000]"
+          @pagination="handleViewUserDetail"
+          style="margin-top: 20px;"
+        />
       </div>
     </el-drawer>
   </div>
@@ -633,7 +643,12 @@ export default {
       userDetailList: [],
       userDetailLoading: false,
       showUserDetail: false,
-      userDetailExportLoading: false
+      userDetailExportLoading: false,
+      userDetailTotal: 0,
+      userDetailQueryParams: {
+        pageNum: 1,
+        pageSize: 10
+      }
     };
   },
   created() {
@@ -882,9 +897,10 @@ export default {
       if (!this.currentLiveId) return;
       this.showUserDetail = true;
       this.userDetailLoading = true;
-      getLiveUserDetailListBySql(this.currentLiveId).then(response => {
+      getLiveUserDetailListBySql(this.currentLiveId, this.userDetailQueryParams.pageNum, this.userDetailQueryParams.pageSize).then(response => {
         if (response.code === 200) {
           this.userDetailList = response.data || [];
+          this.userDetailTotal = response.total || 0;
         }
         this.userDetailLoading = false;
       }).catch(() => {
@@ -898,6 +914,11 @@ export default {
       this.detailData = {};
       this.userDetailList = [];
       this.currentLiveId = null;
+      this.userDetailTotal = 0;
+      this.userDetailQueryParams = {
+        pageNum: 1,
+        pageSize: 100
+      };
     },
     /** 格式化百分比 */
     formatPercent(value) {

+ 39 - 39
src/views/live/order/index.vue

@@ -161,37 +161,37 @@
 <!--        </el-select>-->
 <!--      </el-form-item>-->
 
-      <el-form-item label="结算状态" prop="deliveryPayStatus">
-        <el-select v-model="queryParams.deliveryPayStatus" placeholder="请选择物流结算状态" clearable size="small">
-          <el-option
-            v-for="item in deliveryPayStatusOptions"
-            :key="item.dictValue"
-            :label="item.dictLabel"
-            :value="item.dictValue"
-          />
-        </el-select>
-      </el-form-item>
+<!--      <el-form-item label="结算状态" prop="deliveryPayStatus">-->
+<!--        <el-select v-model="queryParams.deliveryPayStatus" placeholder="请选择物流结算状态" clearable size="small">-->
+<!--          <el-option-->
+<!--            v-for="item in deliveryPayStatusOptions"-->
+<!--            :key="item.dictValue"-->
+<!--            :label="item.dictLabel"-->
+<!--            :value="item.dictValue"-->
+<!--          />-->
+<!--        </el-select>-->
+<!--      </el-form-item>-->
 
-      <el-form-item label="小程序" prop="appId">
-        <el-select v-model="queryParams.appId" placeholder="请选择所属小程序" clearable size="small">
-          <el-option
-            v-for="dict in appMallOptions"
-            :key="dict.appid"
-            :label="dict.name + '(' + dict.appid + ')'"
-            :value="dict.appid"
-          />
-        </el-select>
-      </el-form-item>
+<!--      <el-form-item label="小程序" prop="appId">-->
+<!--        <el-select v-model="queryParams.appId" placeholder="请选择所属小程序" clearable size="small">-->
+<!--          <el-option-->
+<!--            v-for="dict in appMallOptions"-->
+<!--            :key="dict.appid"-->
+<!--            :label="dict.name + '(' + dict.appid + ')'"-->
+<!--            :value="dict.appid"-->
+<!--          />-->
+<!--        </el-select>-->
+<!--      </el-form-item>-->
 
-      <el-form-item label="商品规格" prop="productSpec">
-        <el-input
-          v-model="queryParams.productSpec"
-          placeholder="请输入商品规格"
-          clearable
-          size="small"
-          @keyup.enter.native="handleQuery"
-        />
-      </el-form-item>
+<!--      <el-form-item label="商品规格" prop="productSpec">-->
+<!--        <el-input-->
+<!--          v-model="queryParams.productSpec"-->
+<!--          placeholder="请输入商品规格"-->
+<!--          clearable-->
+<!--          size="small"-->
+<!--          @keyup.enter.native="handleQuery"-->
+<!--        />-->
+<!--      </el-form-item>-->
 
 <!--      <el-form-item label="商品数量" prop="totalNum">-->
 <!--        <el-input-->
@@ -253,16 +253,16 @@
 <!--        />-->
 <!--      </el-form-item>-->
 
-      <el-form-item label="档期归属" prop="scheduleId">
-        <el-select filterable style="width: 215px" v-model="queryParams.scheduleId" placeholder="请选择档期" clearable size="small">
-          <el-option
-            v-for="item in scheduleOptions"
-            :key="item.id"
-            :label="item.name"
-            :value="item.id"
-          />
-        </el-select>
-      </el-form-item>
+<!--      <el-form-item label="档期归属" prop="scheduleId">-->
+<!--        <el-select filterable style="width: 215px" v-model="queryParams.scheduleId" placeholder="请选择档期" clearable size="small">-->
+<!--          <el-option-->
+<!--            v-for="item in scheduleOptions"-->
+<!--            :key="item.id"-->
+<!--            :label="item.name"-->
+<!--            :value="item.id"-->
+<!--          />-->
+<!--        </el-select>-->
+<!--      </el-form-item>-->
 
       <el-form-item label="代服账户" prop="erpAccount" v-if="SFDFopen">
         <el-select v-model="queryParams.erpAccount" style="width: 215px" placeholder="ERP账户" clearable size="small">

+ 19 - 1
src/views/qw/externalContact/index.vue

@@ -21,6 +21,16 @@
           />
         </el-select>
       </el-form-item>
+      <el-form-item label="企微主体" prop="corpId">
+        <el-select v-model="queryParams.corpId" placeholder="企微主体" size="small" clearable>
+          <el-option
+            v-for="corp in corpList"
+            :key="corp.corpId"
+            :label="corp.corpName"
+            :value="corp.corpId"
+          />
+        </el-select>
+      </el-form-item>
       <el-form-item label="企微微信" prop="companyUserName">
         <el-select v-model="queryParams.qwUserId" placeholder="企微微信"  size="small" clearable>
           <el-option
@@ -445,6 +455,7 @@ import {getAllUserlist} from "@/api/company/companyUser";
 import {getQwUserInfo} from "@/api/qw/qwUser";
 import { allListTagGroup} from "@/api/qw/tagGroup";
 import {searchTags,} from "@/api/qw/tag";
+import { allCorp } from "@/api/qw/qwCompany";
 import PaginationMore from '@/components/PaginationMore/index.vue'
 import externalContactInfo from "../externalContact/info";
 
@@ -570,6 +581,8 @@ export default {
         {dictLabel:"未绑定",dictValue:'noBindMini'},
       ],
       qwCompanyList:[],
+      // 企微主体列表
+      corpList: [],
       // 表单参数
       form: {},
       // 表单校验
@@ -613,6 +626,11 @@ export default {
       this.transferStatusOptions = response.data;
     });
 
+    // 企微主体列表
+    allCorp().then(response => {
+      this.corpList = response.data || [];
+    });
+
     //获取企业
     getCompanyList().then(response => {
       this.qwCompanyList = response.data;
@@ -755,7 +773,7 @@ export default {
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm("queryForm");
-      this.queryParams.corpId= this.qwCompanyList[0].dictValue;
+      this.queryParams.corpId = null;
       this.selectTags=[];
       this.queryParams.qwUserId = null;
       this.queryParams.sTime=null;

+ 248 - 11
src/views/qw/friendWelcome/index.vue

@@ -2,7 +2,7 @@
   <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 v-model="queryParams.companyId" clearable placeholder="销售公司" @change="changeCorpOrCompany()" size="small">
+        <el-select v-model="queryParams.companyId" placeholder="销售公司" @change="changeCorpOrCompany()" size="small">
           <el-option
             v-for="dict in companyList"
             :key="dict.dictValue"
@@ -12,7 +12,7 @@
         </el-select>
       </el-form-item>
       <el-form-item label="企微主体" prop="corpId">
-        <el-select v-model="queryParams.corpId" clearable placeholder="企微主体" @change="changeCorpOrCompany()" size="small">
+        <el-select v-model="queryParams.corpId" placeholder="企微主体" @change="changeCorpOrCompany()" size="small">
           <el-option
             v-for="dict in myQwCompanyList"
             :key="dict.dictValue"
@@ -101,6 +101,15 @@
       </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" width="120px">
+        <template slot-scope="scope">
+          <el-button
+            size="mini"
+            type="text"
+            @click="handleDetail(scope.row)"
+          >详情</el-button>
+        </template>
+      </el-table-column>
     </el-table>
 
     <pagination
@@ -110,11 +119,175 @@
       :limit.sync="queryParams.pageSize"
       @pagination="getList"
     />
+
+    <!-- 添加或修改好友欢迎语对话框 -->
+    <el-dialog :title="friendWelcomeDialog.title" :visible.sync="friendWelcomeDialog.visible" v-loading="friendWelcomeDialog.loading" width="1200px" append-to-body>
+      <div style="width: 1130px" class="app-container">
+        <div>
+          <span style="font-size: 15px">基础信息</span>
+          <el-divider></el-divider>
+        </div>
+        <el-form ref="form" :model="friendWelcomeDialog.friendWelcomeInfo" :disabled="true" label-width="120px">
+          <el-form-item label="使用成员:" style="margin-top: 2%">
+            <div>
+              <el-tag
+                style="margin-left: 5px"
+                size="medium"
+                :key="list.id"
+                v-for="list in userSelectList"
+                closable
+                :disable-transitions="false">
+                {{list.qwUserName}}({{list.nickName}})
+              </el-tag>
+            </div>
+          </el-form-item>
+          <!-- 新增整体标题 -->
+          <el-form-item label="标题:" prop="welcomeTitle">
+            <el-input v-model="friendWelcomeDialog.friendWelcomeInfo.welcomeTitle" placeholder="请输入欢迎语标题"/>
+            <el-alert style="margin-top: 8px;height: 30px"
+                      title="此标题仅用于欢迎语的用途区分"
+                      type="info"
+                      :closable="false"
+                      show-icon>
+            </el-alert>
+          </el-form-item>
+          <el-form-item label="是否发送欢迎语">
+            <el-switch
+              v-model="friendWelcomeDialog.friendWelcomeInfo.isSendMsg"
+              active-color="#13ce66"
+              inactive-color="#ff4949"
+              active-value="1"
+              inactive-value="2">
+            </el-switch>
+            <span v-if="friendWelcomeDialog.friendWelcomeInfo.isSendMsg == '1'" style="margin-left: 10px;color: #13ce66">允许</span>
+            <span v-if="friendWelcomeDialog.friendWelcomeInfo.isSendMsg == '2'" style="margin-left: 10px;color: #ff4949">不允许</span>
+
+          </el-form-item>
+          <div>
+            <span style="font-size: 15px">发送欢迎语</span>
+            <el-divider></el-divider>
+          </div>
+          <el-form-item label="默认欢迎语:" prop="welcomeText">
+            <el-input v-model="friendWelcomeDialog.friendWelcomeInfo.welcomeText" type="textarea"  :rows="12" maxlength="1300" show-word-limit placeholder="请输入消息内容"/>
+            <!-- 附件和链接列表 -->
+            <el-row>
+              <el-col>
+                <div v-for="(item, index) in friendWelcomeDialog.friendWelcomeInfo.attachments" :key="index" style="background-color: #f5f7fa;padding: 5px;border: 1px solid  #d9d9d9;">
+                  <div slot="header" style="display: flex;justify-content: space-between;align-items: center; ">
+                    <div style="flex: 1;">
+                      <span v-if="item.msgtype === 'image'">【图片】: {{ item.image.pic_url }}</span>
+                      <span v-if="item.msgtype === 'video'">【视频】: {{ item.video.url }}</span>
+                      <span v-if="item.msgtype === 'link'">【链接】: {{ item.link.title }}-{{item.link.desc}}</span>
+                      <span v-if="item.msgtype === 'miniprogram'">【小程序】: {{ item.miniprogram.title }}</span>
+                    </div>
+                  </div>
+                </div>
+              </el-col>
+            </el-row>
+          </el-form-item>
+
+          <el-form-item label="分时段欢迎语">
+            <el-switch
+              v-model="friendWelcomeDialog.friendWelcomeInfo.isDayparting"
+              active-color="#13ce66"
+              inactive-color="#ff4949"
+              active-value="1"
+              inactive-value="2">
+            </el-switch>
+            <span v-if="friendWelcomeDialog.friendWelcomeInfo.isDayparting == '1'" style="margin-left: 10px;color: #13ce66">已启用</span>
+            <span v-if="friendWelcomeDialog.friendWelcomeInfo.isDayparting == '2'" style="margin-left: 10px;color: #ff4949">已禁用</span>
+          </el-form-item>
+
+          <el-form-item v-if="friendWelcomeDialog.friendWelcomeInfo.isDayparting == '1'" >
+            <div style="background-color:#ecf8fe;width: 100%;border: 1px solid #dcdfe6">
+              <span style="margin-left:20px;font-size: 15px;display: block" >注意:1、员工上下班不同时间段可设置不同欢迎语;</span>
+              <span style="margin-left:65px;font-size: 15px;display: block" >2、分时段之外的时间将发送已允许的默认欢迎语。</span>
+              <span style="margin-left:65px;font-size: 15px;display: block" >3、不设置分时段欢迎语则使用已允许的默认欢迎语</span>
+              <span style="margin-left:65px;font-size: 15px;display: block" >4、若员工没有设置过欢迎语则不会发送</span>
+            </div>
+          </el-form-item>
+          <el-form-item v-if="friendWelcomeDialog.friendWelcomeInfo.isDayparting == '2'">
+            <div style="background-color:#ecf8fe;width: 100%;border: 1px solid #dcdfe6">
+              <span style="margin-left:20px;font-size: 15px;display: block" >注意:1、新建欢迎语最多可发送1条文字消息和9个附件;</span>
+              <span style="margin-left:65px;font-size: 15px;display: block" >2、文字消息和附件不能同时为空,当两者均填写时用户会收到多条消息;</span>
+              <span style="margin-left:65px;font-size: 15px;display: block" >3、欢迎语将在客户加为好友后20秒内下发,因网络延迟可能造成发送不成功</span>
+            </div>
+          </el-form-item>
+          <div  v-if="friendWelcomeDialog.friendWelcomeInfo.isDayparting == '1'"  v-for="(item, index) in friendWelcomeDialog.friendWelcomeInfo.daypartingItemlist"    :key="index" >
+            <el-form-item :label="`时段 ${index + 1}:`">
+              <el-row>
+                <el-col style="width: 965px">
+                  <div style="background-color: #fbfbfb;padding: 10px;  border: 1px solid #e6e6e6; margin-bottom: 20px;">
+                    <el-form ref="friendWelcomeItemForm" :disabled="true" :model="item">
+                      <div style="display: flex; gap: 10px;">
+                        <el-form-item label="发起时间:" prop="week" style="flex: 8;">
+                          <el-select v-model="item.week" remote multiple placeholder="请选择" filterable style="width: 580px">
+                            <el-option
+                              v-for="dict in weekOptions"
+                              :key="dict.value"
+                              :label="dict.label"
+                              :value="dict.value">
+                            </el-option>
+                          </el-select>
+                        </el-form-item>
+                        <el-form-item prop="startTime" style="flex: 1;">
+                          <el-time-select style="width: 120px;"
+                                          placeholder="起始时间"
+                                          v-model="item.startTime"
+                                          :picker-options="{
+                                            start: '00:00',
+                                            step: '00:15',
+                                            end: '24:00'
+                                          }">
+                          </el-time-select>
+                        </el-form-item>
+                        <el-form-item prop="endTime" style="flex: 1;">
+                          <el-time-select style="width: 120px;"
+                                          placeholder="结束时间"
+                                          v-model="item.endTime"
+                                          :picker-options="{
+                                            start: '00:00',
+                                            step: '00:15',
+                                            end: '24:00',
+                                            minTime: item.startTime
+                                          }">
+                          </el-time-select>
+                        </el-form-item>
+                      </div>
+
+                      <el-form-item style="margin-top: 20px" prop="welcomeText">
+                        <el-input v-model="item.welcomeText" type="textarea" :rows="12" maxlength="1300" show-word-limit placeholder="请输入消息内容"/>
+                        <!-- 附件和链接列表 -->
+                        <el-row>
+                          <el-col>
+                            <div v-for="(attachment, attachIndex) in item.attachments" :key="attachIndex" style="background-color: #f5f7fa;padding: 5px;border: 1px solid  #d9d9d9;">
+                              <div slot="header" style="  display: flex;justify-content: space-between;align-items: center; ">
+                                <div style="flex: 1;">
+                                  <span v-if="attachment.msgtype === 'image'">【图片】: {{ attachment.image.pic_url }}</span>
+                                  <span v-if="attachment.msgtype === 'video'">【视频】: {{ attachment.video.url }}</span>
+                                  <span v-if="attachment.msgtype === 'link'">【链接】: {{ attachment.link.title }}-{{attachment.link.desc}}</span>
+                                  <span v-if="attachment.msgtype === 'miniprogram'">【小程序】: {{ attachment.miniprogram.title }}</span>
+                                </div>
+                              </div>
+                            </div>
+                          </el-col>
+                        </el-row>
+                      </el-form-item>
+                    </el-form>
+                  </div>
+                </el-col>
+              </el-row>
+            </el-form-item>
+          </div>
+
+        </el-form>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-import { listFriendWelcome } from '@/api/qw/friendWelcome'
+import { getFriendWelcome, listFriendWelcome } from '@/api/qw/friendWelcome'
 import { allList } from '@/api/company/company'
 import { getMyQwCompanyList, getQwAllUserList } from '@/api/qw/user'
 
@@ -145,18 +318,40 @@ export default {
         updateTime: null,
         isSendMsg: null,
       },
+      userSelectList: [],
+      friendWelcomeDialog: {
+        visible: false,
+        loading: false,
+        title: "详情",
+        friendWelcomeInfo: {},
+      },
+      weekOptions: [
+        { value: 1, label: '星期一' },
+        { value: 2, label: '星期二' },
+        { value: 3, label: '星期三' },
+        { value: 4, label: '星期四' },
+        { value: 5, label: '星期五' },
+        { value: 6, label: '星期六' },
+        { value: 7, label: '星期天' }
+      ],
     }
   },
-  created() {
+  async created() {
     this.getDicts("sys_qw_allow_select").then(response => {
       this.allowSelectOptions = response.data;
     });
-    allList().then(response => {
-      this.companyList = response.rows;
-    });
-    getMyQwCompanyList().then(response => {
-      this.myQwCompanyList = response.data;
-    });
+    const [allRes, myRes] = await Promise.all([
+      allList(),
+      getMyQwCompanyList()
+    ]);
+
+    this.companyList = allRes.rows;
+    this.myQwCompanyList = myRes.data;
+
+    this.queryParams.companyId = this.companyList[0].dictValue
+    this.queryParams.corpId = this.myQwCompanyList[0].dictValue
+
+    this.changeCorpOrCompany()
     this.getList();
   },
   methods: {
@@ -167,6 +362,10 @@ export default {
     resetQuery() {
       this.resetForm("queryForm");
       this.companyUserList = []
+
+      this.queryParams.companyId = this.companyList[0].dictValue
+      this.queryParams.corpId = this.myQwCompanyList[0].dictValue
+      this.changeCorpOrCompany()
       this.handleQuery();
     },
     getList() {
@@ -187,7 +386,45 @@ export default {
           this.companyUserList = response.data;
         });
       }
-    }
+    },
+    handleDetail(row) {
+      getFriendWelcome(row.id).then(response => {
+        let data = response.row
+
+        const params = {
+          companyId: data.companyId,
+          corpId: data.corpId
+        }
+        getQwAllUserList(params).then(res => {
+          this.userSelectList = res.data.filter(item => {
+            return data.qwUserIds.includes(item.id)
+          })
+        })
+
+        // 转换 attachments
+        if (typeof data.attachments === 'string') {
+          data.attachments = JSON.parse(data.attachments);
+        }
+
+        // 转换 daypartingItemlist
+        if (typeof data.daypartingItemlist === 'string') {
+          data.daypartingItemlist = JSON.parse(data.daypartingItemlist);
+        }
+
+        // 转换 daypartingItemlist 中的每个项目的 attachments 和 week
+        if (Array.isArray(data.daypartingItemlist)) {
+          data.daypartingItemlist = data.daypartingItemlist.map(item => {
+            return {
+              ...item,
+              attachments: typeof item.attachments === 'string' ? JSON.parse(item.attachments) : item.attachments,
+              week: typeof item.week === 'string' ? JSON.parse(item.week) : item.week
+            };
+          });
+        }
+        this.friendWelcomeDialog.friendWelcomeInfo = data
+        this.friendWelcomeDialog.visible = true
+      })
+    },
   },
 }
 </script>

+ 13 - 1
src/views/qw/qwCompany/index.vue

@@ -200,6 +200,15 @@
         <el-form-item label="聊天工具栏实际运用地址" prop="chatToolbarOauth">
           <el-input v-model="form.chatToolbarOauth" placeholder="请输入聊天工具栏实际运用地址" />
         </el-form-item>
+        <el-form-item label="app分享小程序原始id" prop="yjfyyAppId">
+          <el-input v-model="form.yjfyyAppId" placeholder="app分享小程序原始id" />
+        </el-form-item>
+        <el-form-item label="app分享小程序应用id" prop="yjfyyAgentId">
+          <el-input v-model="form.yjfyyAgentId" placeholder="app分享小程序应用id" />
+        </el-form-item>
+        <el-form-item label="app分享小程序schma" prop="yjfyySchema">
+          <el-input v-model="form.yjfyySchema" placeholder="app分享小程序schema" />
+        </el-form-item>
         <el-form-item label="关联公司" prop="companyIds">
 
           <el-select filterable  v-model="form.companyIds" remote multiple placeholder="请选择公司名"  clearable style="width: 50%;">
@@ -359,7 +368,10 @@ export default {
         status: 0,
         createTime: null,
         updateTime: null,
-        createBy: null
+        createBy: null,
+        yjfyyAppId: null,
+        yjfyyAgentId: null,
+        yjfyySchema: null,
       };
       this.resetForm("form");
     },