Просмотр исходного кода

Merge remote-tracking branch 'origin/康年堂' into 康年堂

yh 4 дней назад
Родитель
Сommit
4723c69eaa

+ 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
 
+#直播解码路径
+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
+

+ 5 - 0
.env.prod-jnmy

@@ -27,6 +27,11 @@ VUE_APP_VIDEO_LINE_1 = https://jnmytcpv.ylrzcloud.com
 # 线路二地址
 VUE_APP_VIDEO_LINE_2 = https://jnmyobs.ylrztop.com
 
+#火山云视频地址域名
+VUE_APP_VIDE0_URL = https://cdjnmyvolcengine.ylrztop.com
+#火山云视频点播空间名
+VUE_APP_HSY_SPACE = cdjnmy-2114522511
+
 # 开发环境配置
 ENV = 'development'
 

+ 4 - 0
.env.prod-knt

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

+ 0 - 39
.env.prod-knt2

@@ -1,39 +0,0 @@
-# 页面标题
-VUE_APP_TITLE = 康年堂SCRM管理系统
-# 首页菜单标题
-VUE_APP_TITLE_INDEX = 康年堂
-# 公司名称
-VUE_APP_COMPANY_NAME = 陕西康年堂医药连锁有限公司
-# ICP备案号
-VUE_APP_ICP_RECORD = 陕ICP备2023011686号-5
-# ICP网站访问地址
-VUE_APP_ICP_URL =https://beian.miit.gov.cn
-# 网站LOG
-VUE_APP_LOG_URL =@/assets/logo/knt.jpg
-# 存储桶配置
-VUE_APP_OBS_ACCESS_KEY_ID = K2UTJGIN7UTZJR2XMXYG
-# 存储桶配置
-VUE_APP_OBS_SECRET_ACCESS_KEY = sbyeNJLbcYmH6copxeFP9pAoksM4NIT9Zw4x0SRX
-# 存储桶配置
-VUE_APP_OBS_SERVER = https://obs.cn-north-4.myhuaweicloud.com
-# 存储桶配置
-VUE_APP_OBS_BUCKET = jnmy-hw079058881
-# 存储桶配置
-VUE_APP_COS_BUCKET = jnmy-1323137866
-# 存储桶配置
-VUE_APP_COS_REGION = ap-chongqing
-# 线路一地址
-VUE_APP_VIDEO_LINE_1 = https://jnmytcpv.ylrzcloud.com
-# 线路二地址
-VUE_APP_VIDEO_LINE_2 = https://jnmyobs.ylrztop.com
-# 生产环境配置
-ENV = 'production'
-
-#FS管理系统/生产环境
-VUE_APP_BASE_API = '/prod-api'
-
-#默认 1、会员 2、企微
-VUE_APP_COURSE_DEFAULT = 1
-
-# 路由懒加载
-VUE_CLI_BABEL_TRANSPILE_MODULES = true

+ 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({

+ 8 - 0
src/api/hisStore/storeProductPackage.js

@@ -77,3 +77,11 @@ export function getProductsCompanyIds(data) {
     data: data
   })
 }
+
+//批量复制套餐包
+export function bulkCopy(packageId) {
+  return request({
+    url: '/store/store/storeProductPackage/bulkCopy/' + packageId,
+    method: 'get'
+  })
+}

+ 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'
+  })
+}

+ 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 = '';

+ 4 - 1
src/utils/cos.js

@@ -48,7 +48,10 @@ 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
+    const basePath = process.LIVE_PATH || '/course';
+    const liveKey = `${basePath}/${uploadDay}/${upload_file_name}`;
+    const key = type === 3 ? liveKey : (type === 1 ? courseKey : videoKey);
+
     console.log("开始上传")
 
     return new Promise((resolve, reject) => {

+ 4 - 4
src/views/course/fsCourseProductOrder/index.vue

@@ -490,14 +490,14 @@ export default {
     handleDecodeExport() {
       if (this.payDateRange && this.payDateRange.length === 2) {
         this.queryParams.payStartTime = this.payDateRange[0];
-        this.queryParams.payEndTime = this.payDateRange[1];
+        this.queryParams.payEndTime = this.payDateRange[1].substring(0,10)+" 23:59:59";
       } else {
         this.queryParams.payStartTime = null;
         this.queryParams.payEndTime = null;
       }
       if (this.refundDateRange && this.refundDateRange.length === 2) {
         this.queryParams.refundStartTime = this.refundDateRange[0];
-        this.queryParams.refundEndTime = this.refundDateRange[1];
+        this.queryParams.refundEndTime = this.refundDateRange[1].substring(0,10)+" 23:59:59";
       } else {
         this.queryParams.refundStartTime = null;
         this.queryParams.refundEndTime = null;
@@ -519,14 +519,14 @@ export default {
     handleExport() {
       if (this.payDateRange && this.payDateRange.length === 2) {
         this.queryParams.payStartTime = this.payDateRange[0];
-        this.queryParams.payEndTime = this.payDateRange[1];
+        this.queryParams.payEndTime = this.payDateRange[1].substring(0,10)+" 23:59:59";
       } else {
         this.queryParams.payStartTime = null;
         this.queryParams.payEndTime = null;
       }
       if (this.refundDateRange && this.refundDateRange.length === 2) {
         this.queryParams.refundStartTime = this.refundDateRange[0];
-        this.queryParams.refundEndTime = this.refundDateRange[1];
+        this.queryParams.refundEndTime = this.refundDateRange[1].substring(0,10)+" 23:59:59";
       } else {
         this.queryParams.refundStartTime = null;
         this.queryParams.refundEndTime = null;

+ 19 - 0
src/views/his/company/index.vue

@@ -140,6 +140,13 @@
           </el-tag>
         </template>
       </el-table-column>
+      <!--  看课休息    -->
+      <el-table-column label="看课休息开关" align="center" prop="isOpenRestReminder">
+        <template slot-scope="scope">
+          <el-tag v-if="scope.row.isOpenRestReminder==1" type="success">开启</el-tag>
+          <el-tag v-if="scope.row.isOpenRestReminder==0" type="success">关闭</el-tag>
+        </template>
+      </el-table-column>
       <el-table-column label="备注" align="center" prop="remark"/>
       <el-table-column label="开始时间" align="center" prop="startTime" width="180"/>
       <el-table-column label="到期时间" align="center" prop="limitTime" width="180"/>
@@ -456,6 +463,17 @@
             />
           </el-select>
         </el-form-item>
+        <el-form-item label="看课休息开关" >
+          <el-radio-group v-model="form.isOpenRestReminder">
+            <el-radio :label="1" >开</el-radio>
+            <el-radio :label="0">关</el-radio>
+          </el-radio-group>
+          <span>(默认为空,走系统配置)</span>
+        </el-form-item>
+
+
+
+
         <el-form-item label="备注" prop="remark">
           <el-input v-model="form.remark" type="textarea" :rows="2" placeholder="请输入备注"/>
         </el-form-item>
@@ -1140,6 +1158,7 @@ export default {
         groupName: null,
         userId: null,
         remark: null,
+        isOpenRestReminder: null,
         linkName: null,
         limitUserCount: null,
         maxPadNum: -1,

+ 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>

+ 61 - 2
src/views/hisStore/storeCouponIssue/index.vue

@@ -65,6 +65,7 @@
       <el-table-column label="最低消费" align="center" prop="useMinPrice" />
       <el-table-column label="优惠券有效期限(天)" align="center" prop="couponTime" />
       <el-table-column label="总数量" align="center" prop="totalCount" />
+      <el-table-column label="领取数量" align="center" prop="receiveCount" />
       <el-table-column label="剩余领取数量" align="center" prop="remainCount" />
       <el-table-column label="类型" align="center" prop="couponType" >
           <template slot-scope="scope">
@@ -107,7 +108,28 @@
 
     <!-- 添加或修改优惠券领取对话框 -->
     <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
-      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+        <el-form-item label="优惠券开始时间" prop="startTime">
+          <el-date-picker clearable size="small" style="width: 200px"
+                          v-model="form.startTime"
+                          type="date"
+                          value-format="yyyy-MM-dd"
+                          placeholder="选择开始时间" disabled >
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="优惠券结束时间" prop="limitTime">
+          <el-date-picker clearable size="small" style="width: 200px"
+                          v-model="form.limitTime"
+                          type="date"
+                          value-format="yyyy-MM-dd"
+                          placeholder="选择结束时间"
+                          :picker-options="pickerOptions"
+          >
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="优惠券领取数量" prop="totalCount">
+          <el-input-number v-model="form.totalCount" :min=totalCount placeholder="请输入优惠券领取数量" />
+        </el-form-item>
          <el-form-item label="状态">
             <el-radio-group v-model="form.status">
               <el-radio :label="item.dictValue" v-for="item in statusOptions" >{{item.dictLabel}}</el-radio>
@@ -129,6 +151,19 @@ export default {
   name: "HisStoreCouponIssue",
   data() {
     return {
+      pickerOptions: {
+        disabledDate: (time) => {
+          // 如果没有选择开始时间,则不限制
+          if (!this.limitTime) {
+            return false;
+          }
+          // 设置可选时间为当前日期之后
+          const limitTime = new Date(this.limitTime);
+          return time.getTime() < limitTime.getTime();
+        }
+      },
+      limitTime:null,
+      totalCount:null,
       couponTypeOptions:[],
       statusOptions:[],
       dateRange:[],
@@ -198,9 +233,29 @@ export default {
     getList() {
       this.loading = true;
       listStoreCouponIssue(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
-        this.storeCouponIssueList = response.rows;
+        if (response.rows.length > 0) {
+          this.storeCouponIssueList = response.rows.map(item => {
+            // 计算领取数量
+            const receiveCount = item.remainCount;
+            // 计算剩余数量 = 总数量 - 领取数量
+            const remainCount = item.totalCount - receiveCount;
+
+            // 返回新的对象,包含计算后的值
+            return {
+              ...item,
+              receiveCount,
+              remainCount,
+            };
+          });
+        } else {
+          this.storeCouponIssueList = response.rows
+        }
+
         this.total = response.total;
         this.loading = false;
+      }).catch(error => {
+        this.loading = false;
+        console.error('获取优惠券列表失败:', error);
       });
     },
     // 取消按钮
@@ -248,6 +303,8 @@ export default {
     handleAdd() {
       this.reset();
       this.open = true;
+      this.limitTime = null;
+      this.totalCount = null;
       this.title = "添加优惠券领取";
     },
     /** 修改按钮操作 */
@@ -256,6 +313,8 @@ export default {
       const id = row.id || this.ids
       getStoreCouponIssue(id).then(response => {
         this.form = response.data;
+        this.limitTime = response.data.limitTime;
+        this.totalCount = response.data.totalCount;
         this.form.status = response.data.status.toString();
         this.open = true;
         this.title = "修改优惠券领取";

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

@@ -393,6 +393,7 @@ export default {
         deptId: null,
         bankTransactionId:null,
         companyUserNickName:null,
+        appId:null,
       },
       // 表单参数
       form: {},
@@ -542,7 +543,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);

+ 29 - 3
src/views/hisStore/storeProductPackage/index.vue

@@ -86,6 +86,18 @@
         >导出</el-button>
       </el-col>
 
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          :disabled="multiple"
+          @click="bulkCopy"
+          v-hasPermi="['store:storeProductPackage:add']"
+        >批量复制</el-button>
+      </el-col>
+
 	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
@@ -193,8 +205,8 @@
                 <el-radio :label="item.dictValue" v-for="item in statusOptions" >{{item.dictLabel}}</el-radio>
               </el-radio-group>
         </el-form-item>
-         <el-form-item label="公司" prop="companyId">
-           <el-select style="width: 220px" filterable v-model="form1.companyId" placeholder="请选择公司名" clearable size="small">
+         <el-form-item label="公司" prop="companyIds">
+           <el-select style="width: 220px" filterable v-model="form1.companyIds" multiple placeholder="请选择公司名" clearable size="small">
              <el-option
                v-for="item in companyOptions"
                :key="item.companyId"
@@ -351,7 +363,7 @@
 </template>
 
 <script>
-import { listStoreProductPackage, getStoreProductPackage, delStoreProductPackage, addStoreProductPackage, updateStoreProductPackage, exportStoreProductPackage,modifyStoreProductPackages,getProductsCompanyIds } from "@/api/hisStore/storeProductPackage";
+import { listStoreProductPackage, getStoreProductPackage, delStoreProductPackage, addStoreProductPackage, updateStoreProductPackage, exportStoreProductPackage,modifyStoreProductPackages,getProductsCompanyIds,bulkCopy } from "@/api/hisStore/storeProductPackage";
 import Editor from '@/components/Editor/wang';
 import productAttrValueSelect from "../components/productAttrValueSelect";
 import Material from '@/components/Material'
@@ -477,6 +489,20 @@ export default {
     this.getCompanyList();
   },
   methods: {
+    /** 批量复制 */
+    bulkCopy(row) {
+      const packageIds = row.packageId || this.ids;
+      this.$confirm('是否确认复制套餐包编号为"' + packageIds + '"的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+        return bulkCopy(packageIds);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("批量复制成功");
+      }).catch(() => {});
+    },
     handleCompanyChange(){
       if (!this.products || this.products.length === 0) {
         // this.$message.warning('请先选择商品');

+ 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;

+ 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");
     },