Browse Source

Merge branch 'master' into 宣传活动

Long 1 week ago
parent
commit
923e30596f

+ 40 - 0
.env.prod-hat

@@ -0,0 +1,40 @@
+# 页面标题
+VUE_APP_TITLE =互联网医院管理系统
+# 首页菜单标题
+VUE_APP_TITLE_INDEX =恒安图管理系统
+# 公司名称
+VUE_APP_COMPANY_NAME =重庆云联融智科技有限公司
+# ICP备案号
+VUE_APP_ICP_RECORD =渝ICP备2024031984号-1
+# ICP网站访问地址
+VUE_APP_ICP_URL =https://beian.miit.gov.cn
+# 网站LOG
+VUE_APP_LOG_URL =@/assets/logo/hat.png
+# 存储桶配置
+VUE_APP_OBS_ACCESS_KEY_ID = K2UTJGIN7UTZJR2XMXYG
+# 存储桶配置
+VUE_APP_OBS_SECRET_ACCESS_KEY = sbyeNJLbcYmH6copxeFP9pAoksM4NIT9Zw4x0SRX
+# 存储桶配置
+VUE_APP_OBS_SERVER = https://obs.cn-north-4.myhuaweicloud.com
+# 存储桶配置
+VUE_APP_OBS_BUCKET = hat-hw079058881
+# 存储桶配置
+VUE_APP_COS_BUCKET = hat-1323137866
+# 存储桶配置
+VUE_APP_COS_REGION = ap-chongqing
+# 线路一地址
+VUE_APP_VIDEO_LINE_1 = https://hattcpv.ylrzcloud.com
+# 线路二地址
+VUE_APP_VIDEO_LINE_2 = https://hatobs.ylrztop.com
+
+# 开发环境配置
+ENV = 'development'
+
+# FS管理系统/开发环境
+VUE_APP_BASE_API = '/prod-api'
+
+#默认 1、会员 2、企微
+VUE_APP_COURSE_DEFAULT = 2
+
+# 路由懒加载
+VUE_CLI_BABEL_TRANSPILE_MODULES = true

+ 39 - 0
.env.prod-knt

@@ -0,0 +1,39 @@
+# 页面标题
+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

+ 2 - 0
package.json

@@ -18,6 +18,7 @@
     "build:prod-sxjz": "vue-cli-service build --mode prod-sxjz",
     "build:prod-xfk": "vue-cli-service build --mode prod-xfk",
     "build:prod-jnmy": "vue-cli-service build --mode prod-jnmy",
+    "build:prod-knt": "vue-cli-service build --mode prod-knt",
     "build:prod-hdt": "vue-cli-service build --mode prod-hdt",
     "build:prod-yzt": "vue-cli-service build --mode prod-yzt",
     "build:prod-fcky": "vue-cli-service build --mode prod-fcky",
@@ -40,6 +41,7 @@
     "build:prod-syysy": "vue-cli-service build --mode prod-syysy",
     "build:prod-hyt": "vue-cli-service build --mode prod-hyt",
     "build:prod-hst": "vue-cli-service build --mode prod-hst",
+    "build:prod-hat": "vue-cli-service build --mode prod-hat",
     "preview": "node build/index.js --preview",
     "lint": "eslint --ext .js,.vue src"
   },

+ 16 - 0
src/api/company/statistics.js

@@ -39,6 +39,14 @@ export function packageOrder(query) {
     params: query
   })
 }
+
+export function afterSalesOrder(query) {
+  return request({
+    url: '/company/statistics/afterSalesOrder',
+    method: 'get',
+    params: query
+  })
+}
 export function inquiryOrder(query) {
   return request({
     url: '/company/statistics/inquiryOrder',
@@ -62,6 +70,14 @@ export function exportPackageOrder(query) {
     params: query
   })
 }
+
+export function exportAfterSalesOrder(query) {
+  return request({
+    url: '/company/statistics/exportAfterSalesOrder',
+    method: 'get',
+    params: query
+  })
+}
 export function exportInquiryOrder(query) {
   return request({
     url: '/company/statistics/exportInquiryOrder',

+ 61 - 0
src/api/his/answer.js

@@ -0,0 +1,61 @@
+import request from '@/utils/request'
+
+// 查询问答列表
+export function listAnswer(query) {
+  return request({
+    url: '/his/answer/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询问答详细
+export function getAnswer(id) {
+  return request({
+    url: '/his/answer/' + id,
+    method: 'get'
+  })
+}
+
+// 新增问答
+export function addAnswer(data) {
+  return request({
+    url: '/his/answer',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改问答
+export function updateAnswer(data) {
+  return request({
+    url: '/his/answer',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除问答
+export function delAnswer(id) {
+  return request({
+    url: '/his/answer/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出问答
+export function exportAnswer(query) {
+  return request({
+    url: '/his/answer/export',
+    method: 'get',
+    params: query
+  })
+}
+
+// 问答列表选项
+export function questionOptions() {
+  return request({
+    url: '/his/answer/allList',
+    method: 'get',
+  })
+}

BIN
src/assets/logo/hat.png


BIN
src/assets/logo/knt.jpg


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

@@ -36,7 +36,7 @@ export default {
     pageSizes: {
       type: Array,
       default() {
-        return [10, 20, 30, 50]
+        return [10, 20, 30, 50,100,200,300]
       }
     },
     // 移动端页码按钮的数量端默认值5

+ 2 - 2
src/store/modules/user.js

@@ -10,7 +10,7 @@ const user = {
     roles: [],
     permissions: [],
     isAdmin: false,
-    medicalMallConfig: {medicalMall: false,statics: false,audit:false,resource:false,stores:false}
+    medicalMallConfig: {medicalMall: false,statics: false,audit:false,resource:false,stores:true}
   },
 
   mutations: {
@@ -74,7 +74,7 @@ const user = {
           commit('SET_AVATAR', avatar)
           commit('SET_USER', user)
           commit('SET_ISADMIN', res.isAdmin)
-          console.log(res.medicalMallConfig)
+          console.log("res.medicalMallConfig",res.medicalMallConfig)
           commit('SET_MEDICALMALL', res.medicalMallConfig)
           resolve(res)
         }).catch(error => {

+ 7 - 0
src/views/components/course/userCourseCatalogDetails.vue

@@ -167,6 +167,12 @@
           <el-radio v-model="form.isProduct" :label=0>否</el-radio>
           <el-radio v-model="form.isProduct" :label=1>是</el-radio>
         </el-form-item>
+        <el-form-item label="是否先导课" prop="isFirst">
+          <el-radio-group v-model="form.isFirst">
+            <el-radio :label="1">是</el-radio>
+            <el-radio :label="0">否</el-radio>
+          </el-radio-group>
+        </el-form-item>
         <el-form-item label="商品选择" v-if="form.isProduct === 1">
           <el-button size="small" type="primary" @click="chooseCourseProduct">选取商品</el-button>
           <el-table border width="100%" style="margin-top:5px;" :data="form.courseProducts">
@@ -687,6 +693,7 @@ export default {
         isTranscode: 0,
         transcodeFileKey: null,
         isProduct: 0,
+        isFirst: 0,
         listingStartTime: null,
         listingEndTime: null,
       };

+ 6 - 1
src/views/components/his/storeAfterSalesDetails.vue

@@ -114,7 +114,12 @@
           </el-table-column>
           <el-table-column label="小计"  align="center">
             <template slot-scope="scope">
-              ¥{{JSON.parse(scope.row.jsonInfo).num*JSON.parse(scope.row.jsonInfo).price}}
+              ¥{{
+                  (
+                    Number(JSON.parse(scope.row.jsonInfo).num) *
+                    Number(JSON.parse(scope.row.jsonInfo).price)
+                  ).toFixed(2)
+                }}
             </template>
           </el-table-column>
         </el-table>

+ 198 - 17
src/views/components/his/storeOrderDetails.vue

@@ -60,7 +60,7 @@
                  </div>
 
                <div class="operate-button-container" v-if="item.status>1">
-                   <el-button size="mini" @click="refund()" v-hasPermi="['his:storeOrder:afterSales']">申请退款</el-button>
+                   <el-button size="mini" @click="chooseRefund()" v-hasPermi="['his:storeOrder:afterSales']">申请退款</el-button>
                </div>
                <div class="operate-button-container" v-if="item.prescribeId!=null&&item.prescribeId!=''" >
                   <el-button size="mini" @click="getPrescribeOrder()" >处方单</el-button>
@@ -125,7 +125,7 @@
      <el-tooltip class="item" effect="dark" :content="showList ? '显示全部' : '隐藏'" placement="top" style="float: right;">
        <el-button size="mini" circle icon="el-icon-search" @click="showListD()" />
      </el-tooltip>
-  <el-table border v-if="showProd!=null" :data="showProd" size="small" style="width: 100%;margin-top: 20px" >
+     <el-table border v-if="showProd!=null" :data="showProd" size="small" style="width: 100%;margin-top: 20px" >
          <el-table-column label="商品图片" width="150" align="center">
            <template slot-scope="scope">
              <img :src="JSON.parse(scope.row.jsonInfo).image" style="height: 80px">
@@ -346,6 +346,21 @@
                         />
                       </el-select>
                    </el-form-item>
+                   <el-form-item label="实付金额" prop="payMoney">
+                    <el-input-number
+                      v-model="payMoney"
+                      :precision="2"
+                      :step="0.1"
+                      disabled   
+                    />
+                  </el-form-item>
+                  <el-form-item label="物流代收金额">
+                    <el-input-number v-model="payRemain" :precision="2" :step="0.1" :disabled="isUpdatePayRemain==0"/>
+                  </el-form-item>
+
+                  <el-form-item label="应付金额">
+                    <el-input-number v-model="payPrice" :precision="2" :step="0.1" disabled/>
+                  </el-form-item>
                    <el-form-item label="物流状态" prop="deliveryStatus" >
                    <el-select v-model="editForm.deliveryStatus" placeholder="请选择物流状态" clearable size="small" filterable>
                         <el-option
@@ -423,6 +438,70 @@
                 <prescribeDetails  ref="prescribeDetails" />
               </el-drawer>
 
+              <el-dialog
+                :title="refundDialog.title"
+                :visible.sync="refundDialog.open"
+                width="50%"
+                append-to-body
+                >
+                <el-table border v-if="refundShowProd!=null" :data="refundShowProd" ref="refundTable" size="small"  @selection-change="handleSelectionChange">
+                  <el-table-column type="selection" width="55" align="center" />
+                  
+                  <el-table-column label="商品编码" width="110" align="center">
+                    <template slot-scope="scope">
+                      <p>{{ JSON.parse(scope.row.jsonInfo).barCode }}</p>
+                    </template>
+                  </el-table-column>
+
+                  <el-table-column label="商品名称" align="center">
+                    <template slot-scope="scope">
+                      <p>{{ JSON.parse(scope.row.jsonInfo).productName }}</p>
+                    </template>
+                  </el-table-column>
+
+                  <el-table-column label="原单价" width="100" align="center">
+                    <template slot-scope="scope">
+                      <p>¥{{JSON.parse(scope.row.jsonInfo).price.toFixed(2)}}</p>
+                    </template>
+                  </el-table-column>
+
+                  <el-table-column label="退款单价" width="200" align="center">
+                    <template slot-scope="scope">
+                      <el-input-number 
+                        v-model="scope.row.money" 
+                        :precision="2" 
+                        :step="0.1" 
+                        :min="0"
+                        size="mini"
+                      />
+                    </template>
+                  </el-table-column>
+
+                  <el-table-column label="退款数量" width="200" align="center">
+                    <template slot-scope="scope">
+                      <el-input-number 
+                        v-model="scope.row.num" 
+                        :min="0" 
+                        :max="scope.row.originNum"   
+                        size="mini"
+                      />
+                    </template>
+                  </el-table-column>
+
+                </el-table>
+               
+                <div style="margin-top:10px;">
+                  合计退款金额:
+                  <span style="color:red; font-weight:bold;">
+                    ¥{{ refundForm.refundAmount ? refundForm.refundAmount.toFixed(2) : '0.00' }}
+                  </span>
+                </div>
+                <div slot="footer" class="dialog-footer">
+                  <el-button type="primary" @click="submitRefundForm">确 定</el-button>
+                </div>
+
+              </el-dialog>
+
 
 
 
@@ -443,6 +522,19 @@ import {getCitys} from "@/api/store/city";
     components: { inquiryOrderDetails,packageOrderDetails,prescribeDetails ,msgDetails},
     data() {
       return {
+        isUpdateRefund:0, //是否支持修改退款金额 默认0不支持
+        isUpdatePayRemain:0, //是否支持修改物流代收金额 默认0不支持
+        refundShowProd:[],//原退款明细
+        refundForm:{
+          refundAmount:0
+        },
+        selectedRows:[],
+        refundDialog:{
+          title:"申请退款",
+          open:false,
+        },
+        payRemain: 0,   // 物流代收金额,可改
+        payMoney: 0,    // 实收金额,固定
         expressDialog:{
           title:"物流信息",
           open:false,
@@ -451,7 +543,7 @@ import {getCitys} from "@/api/store/city";
           title:"修改物流单号",
           open:false,
         },
-		sourceOptions:[],
+		    sourceOptions:[],
         prescribeDialog:{
           title:"处方单",
           open:false,
@@ -531,6 +623,8 @@ import {getCitys} from "@/api/store/city";
           deliveryType:null,
           userPhone:null,
           remark:"",
+          payRemain:null,
+          payPrice:null
         },
         editDyRules:{
           deliverySn: [
@@ -613,7 +707,24 @@ import {getCitys} from "@/api/store/city";
             });
 
     },
+    computed: {
+       // 应收金额 = 实收金额 + 代收金额
+      payPrice() {
+        const v = (this.payMoney * 100 + this.payRemain * 100) / 100;
+        return Number(v.toFixed(2));
+      }
+    },
     methods: {
+      updateRefund(row) {
+        // 默认退款金额 = 数量 × 单价
+        row.refundAmount = (row.num * row.money).toFixed(2);
+      },
+      handleSelectionChange(val) {
+        this.refundForm.refundAmount = val
+          .reduce((sum, row) => sum + row.num * row.money, 0)
+          ;
+        this.selectedRows = val;
+      },
       getCitys() {
         return getCitys().then(res => {
           this.citys = res.data || [];
@@ -764,6 +875,8 @@ import {getCitys} from "@/api/store/city";
         const payload = {
           ...this.editForm,
           userAddress: this.buildFullAddress(),
+          payRemain :this.payRemain,
+          payPrice: this.payPrice,
         };
 
         updateStoreOrder(payload).then(response => {
@@ -793,7 +906,9 @@ import {getCitys} from "@/api/store/city";
       this.editForm.status = this.item.status != null ? this.item.status.toString() : "";
       this.editForm.deliveryType = this.item.deliveryType;
       this.editForm.deliveryStatus = this.item.deliveryStatus;
-
+      this.payMoney= this.item.payMoney;
+      this.payRemain = this.item.payRemain;
+      this.payPrice= this.item.payPrice;
       // 等城市数据加载后再解析地址
       const currentAddress = (this.item.userAddress || "").toString().trim();
       this.getCitys().then(() => {
@@ -926,7 +1041,71 @@ import {getCitys} from "@/api/store/city";
       moneyCancel(){
         this.money=null;
         this.moneyVisible=false;
-    },
+      },
+      chooseRefund(){
+        if(this.isUpdateRefund == 1){
+          this.refundShowProd = this.showProd.map(item => {
+            const info = JSON.parse(item.jsonInfo);
+            return {
+              ...item,
+              originNum: item.num, // 原始购买数量
+              num: item.num,       // 可编辑的退款数量
+              price: info.price,
+              money: 0.00,
+              // refundAmount: (item.num * info.price).toFixed(2),
+              refundAmount: 0,
+              jsonInfo: item.jsonInfo
+            }
+          })
+          this.refundForm.refundAmount = 0
+          this.refundDialog.open = true
+          // this.$nextTick(() => {
+          //   // 默认全选表格
+          //   this.$refs.refundTable.toggleAllSelection();
+          // });
+          this.$alert('请先设置退款单价和退款数量,再选择商品', '提示');
+        } else {
+          this.refund(); //正常退款
+        }
+        
+      },
+      submitRefundForm(){
+        if(this.refundForm.refundAmount<=0){
+          return this.$message("退款金额不能为0");
+        }
+        if(this.refundForm.refundAmount>this.item.payMoney){
+          return this.$message("退款金额不能大于实付金额" + this.item.payMoney + "元");
+        }
+        if(this.selectedRows.length==0){
+          return this.$message("请选择退款商品");
+        }
+        const refundList = this.selectedRows.map(row => ({
+          itemId: row.itemId,
+          num: row.num,
+          money:row.money
+        }))
+        const param = {
+          orderId:this.item.orderId,
+          refundList:refundList,
+          refundAmount:this.refundForm.refundAmount
+        }
+        console.log("申请退款数据", param);
+        this.$confirm('是否确认申请退款?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return afterSales(param);
+        }).then(() => {
+          this.msgSuccess("操作成功");
+          getOrder(this.item.orderId).then(response => {
+              this.item = response.data;
+              this.getlogList(this.item.orderId);
+              this.$parent.$parent.getList();
+              this.refundDialog.open = false
+          });
+        }).catch(function() {});
+      },
       refund(){
         var that=this;
         this.$confirm('是否确认申请退款?', "警告", {
@@ -1056,18 +1235,20 @@ import {getCitys} from "@/api/store/city";
         this.storeName=storeName;
         this.item=null;
         this.tuiMoneyLogs=null;
-          getOrder(orderId).then(response => {
-              this.item = response.data;
-              this.tuiMoneyLogs = response.tuiMoneyLogs;
-              this.getlistOrderitem(orderId);
-              this.getlogList(orderId);
-              this.getPayment(orderId);
-              this.msgForm.userId=response.data.userId;
-              this.msgForm.followDoctorId=response.data.followDoctorId;
-              if(this.item.orderType==2){
-                this.getCount(this.item.prescribeId);
-              }
-          });
+        getOrder(orderId).then(response => {
+            this.item = response.data;
+            this.tuiMoneyLogs = response.tuiMoneyLogs;
+            this.getlistOrderitem(orderId);
+            this.getlogList(orderId);
+            this.getPayment(orderId);
+            this.msgForm.userId=response.data.userId;
+            this.msgForm.followDoctorId=response.data.followDoctorId;
+            if(this.item.orderType==2){
+              this.getCount(this.item.prescribeId);
+            }
+            this.isUpdateRefund = response.isUpdateRefund;
+            this.isUpdatePayRemain = response.isUpdatePayRemain
+        });
       },
       getCount(id){
         getPrescribe(id).then(response => {

+ 14 - 2
src/views/components/his/userDetails.vue

@@ -133,6 +133,15 @@
  </div>
     <userInquiryOrderDetails  ref="InquiryDetails" />
    </div>
+
+    <!-- 积分记录 -->
+    <div class="contentx" v-if="item!=null" >
+      <div class="desct">
+            用户积分记录
+      </div>
+          <userIntegralDetails  ref="userIntegralDetail" />
+    </div>
+
  </div>
 </template>
 
@@ -146,10 +155,11 @@ import userStorerDetails from "../his/userStorerDetails.vue";
 import userPatietDetails from "../his/userPatietDetails.vue";
 import userInquiryOrderDetails from "../his/userInquiryOrderDetails.vue";
 import userAddDetails from "../his/userAddDetails.vue";
+    import userIntegralDetails from "../his/userIntegralDetails.vue";
   export default {
     name: "storedet",
     props:["data"],
-     components: { userStorerDetails ,userInquiryOrderDetails,userPatietDetails,userAddDetails},
+     components: { userStorerDetails ,userInquiryOrderDetails,userPatietDetails,userAddDetails,userIntegralDetails},
     data() {
       return {
         patientInfo: process.env.VUE_APP_PATIENT_INFO,
@@ -232,7 +242,9 @@ import userAddDetails from "../his/userAddDetails.vue";
               setTimeout(() => {
                    this.$refs.userAddDetail.getAddList(orderId);
               }, 1);
-
+              setTimeout(() => {
+                  this.$refs.userIntegralDetail.getIntegralLogs(orderId);
+              }, 1);
           });
           this.patient=null;
           getPatientByUserId(orderId).then(response => {

+ 111 - 0
src/views/components/his/userIntegralDetails.vue

@@ -0,0 +1,111 @@
+<!-- UserIntegralLogs.vue -->
+<template>
+  <div class="integral-logs-container">
+    <el-table 
+      v-loading="loading" 
+      border 
+      :data="userIntegralLogsList" 
+      @selection-change="handleSelectionChange"
+    >
+      <el-table-column label="用户id" align="center" prop="userId" />
+      <el-table-column label="用户昵称" align="center" prop="nickName" />
+      <el-table-column label="用户电话" align="center" prop="phone" />
+      <el-table-column label="类别" align="center" prop="logType">
+        <template slot-scope="scope">
+          <dict-tag :options="intefralLogTypeOptions" :value="scope.row.logType"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="积分" align="center" prop="integral" />
+      <el-table-column label="积分余额" align="center" prop="balance" />
+      <el-table-column label="订单关联id" align="center" prop="businessId" />
+      <el-table-column label="时间" align="center" prop="createTime" />
+    </el-table>
+    
+    <!-- 分页组件 -->
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </div>
+</template>
+
+<script>
+import { listUserIntegralLogs} from "@/api/his/userIntegralLogs";
+
+export default {
+  name: 'UserIntegralLogs',
+  props: {
+    fsUserId: {
+      type: [String, Number],
+      required: false
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      userIntegralLogsList: [],
+      total: 0,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        userId: this.fsUserId
+      },
+      intefralLogTypeOptions: [],
+      selections: []
+    }
+  },
+  watch: {
+    fsUserId: {
+      handler(newVal) {
+        this.queryParams.userId = newVal;
+        this.getList();
+      },
+      immediate: true
+    }
+  },
+
+  created() {
+    this.getList();
+    this.getDictOptions();
+  },
+  methods: {
+    // 获取积分日志列表
+    getList() {
+
+      if (!this.queryParams.userId) return;
+      
+      this.loading = true;
+      listUserIntegralLogs(this.queryParams).then(response => {
+        this.userIntegralLogsList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    getIntegralLogs(fsUserId){
+        this.queryParams.userId=fsUserId;
+        this.getList();
+    },
+    // 获取字典选项
+    getDictOptions() {
+      // 获取积分日志类型字典
+        this.getDicts("sys_integral_log_type").then(response => {
+            this.intefralLogTypeOptions = response.data;
+        });
+    },
+    
+    // 处理选择变化
+    handleSelectionChange(selection) {
+      this.selections = selection;
+    }
+  }
+}
+</script>
+
+<style scoped>
+.integral-logs-container {
+  padding: 20px;
+}
+</style>

+ 3 - 3
src/views/course/courseWatchLog/watchLogStatistics.vue

@@ -61,7 +61,7 @@
 import { listCourseWatchLog, getCourseWatchLog, delCourseWatchLog, addCourseWatchLog, updateCourseWatchLog, exportCourseWatchLog,watchLogStatistics,watchLogStatisticsExport } from "@/api/course/courseWatchLog";
 import {allList}from "@/api/company/company";
 import { courseList,videoList } from '@/api/course/courseRedPacketLog'
-import {getUserList} from "@/api/company/companyUser";
+// import {getUserList} from "@/api/company/companyUser";
 export default {
   name: "CourseWatchLog",
   data() {
@@ -131,11 +131,11 @@ export default {
     this.getDicts("sys_course_watch_log_type").then(response => {
       this.logTypeOptions = response.data;
     });
-    getUserList().then(res=>{
+/*    getUserList().then(res=>{
       if(res.code === 200) {
         this.companyUserList = res.data
       }
-    })
+    })*/
   },
   methods: {
     courseChange(row){

+ 525 - 0
src/views/his/answer/index.vue

@@ -0,0 +1,525 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
+          v-hasPermi="['his:answer:add']">新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
+          v-hasPermi="['his:answer:edit']">修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
+          v-hasPermi="['his:answer:remove']">删除</el-button>
+      </el-col>
+      <!-- <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['his:answer:export']"
+        >导出</el-button>
+      </el-col> -->
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="answerList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="id" align="center" prop="id" />
+      <el-table-column label="问答名称" align="center" prop="questionName" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
+            v-hasPermi="['his:answer:edit']">修改</el-button>
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
+            v-hasPermi="['his:answer:remove']">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
+      @pagination="getList" />
+
+    <!-- 添加或修改问答对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="1000px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="110px">
+        <el-form-item label="问答名称" prop="questionName">
+          <el-input v-model="form.questionName" placeholder="请输入内容" />
+        </el-form-item>
+        <div v-if="form.answers && form.answers.length == 0" class="empty-state">
+          <div class="empty-state-icon">
+            <i class="el-icon-document"></i>
+          </div>
+          <p>暂无问题,请点击下方按钮添加</p>
+        </div>
+
+        <div v-for="(answer, index) in form.answers" :key="index" class="answer-section">
+          <div class="answer-section-header">
+            <span class="answer-section-title">
+              <span class="answer-section-number">{{ index + 1 }}</span>
+              问题 {{ index + 1 }}
+            </span>
+            <div>
+              <el-button 
+                v-if="index !== 0" 
+                type="danger" 
+                size="mini" 
+                icon="el-icon-delete"
+                @click="delItem(answer, index)">
+                删除问题
+              </el-button>
+            </div>
+          </div>
+          
+          <el-row :gutter="15">
+            <el-col :span="16">
+              <el-form-item label="问题标题" :prop="`answers[${index}].title`" :rules="rules.title">
+                <el-input v-model="answer.title" placeholder="请输入问题标题"></el-input>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          
+          <el-form-item label="选项配置">
+            <div v-for="(option, optionIndex) in answer.options" :key="optionIndex" class="option-item">
+              <div class="option-input">
+                <el-input 
+                  v-model="answer.options[optionIndex]" 
+                  :placeholder="`选项 ${optionIndex + 1}`">
+                </el-input>
+              </div>
+              <div class="option-actions">
+                <el-button 
+                  v-if="optionIndex + 1 === answer.options.length"
+                  type="primary" 
+                  size="mini" 
+                  icon="el-icon-plus"
+                  circle
+                  @click="addOption(index, optionIndex)">
+                </el-button>
+                <el-button 
+                  v-if="optionIndex !== 0"
+                  type="danger" 
+                  size="mini" 
+                  icon="el-icon-minus"
+                  circle
+                  @click="delOption(answer.options, optionIndex)">
+                </el-button>
+              </div>
+            </div>
+            <div class="option-tip">
+              <span>提示:至少保留一个选项,点击 + 按钮添加更多选项</span>
+            </div>
+          </el-form-item>
+        </div>
+        
+        <div class="add-section-btn">
+          <el-button 
+            type="primary" 
+            icon="el-icon-plus"
+            @click="addItem(form.answers.length)">
+            添加问题
+          </el-button>
+        </div>
+        
+        <!-- <div v-for="(i, index) in form.answers" :key="index">
+          <el-row>
+            <el-col :span="8">
+              <el-form-item label="标题" prop="title">
+                <el-input v-model="i.title"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-button style="margin: 5px;" v-if="index + 1 == form.answers.length"
+                @click="addItem(form.answers.length)" type="primary" size="mini">+</el-button>
+              <el-button style="margin: 5px;" v-if="index !== 0" type="danger" size="mini"
+                @click="delItem(i, index)">-</el-button>
+            </el-col>
+
+          </el-row>
+        </div> -->
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listAnswer, getAnswer, delAnswer, addAnswer, updateAnswer, exportAnswer } from "@/api/his/answer";
+
+export default {
+  name: "Answer",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 问答表格数据
+      answerList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        jsonInfo: null,
+      },
+      form: {
+            questionName: '',
+            answers: [
+              {
+                title: '',
+                options: ['']
+              }
+            ]
+          },
+          rules: {
+            questionName: [
+              { required: true, message: '请输入问答名称', trigger: 'blur' }
+            ],
+            title: [
+              { required: true, message: '请输入问题标题', trigger: 'blur' }
+            ]
+          }
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    addItem(length) {
+          this.form.answers.push({
+            title: '',
+            options: ['']
+          })
+        },
+        delItem(item, index) {
+          if (this.form.answers.length > 1) {
+            this.$confirm('确定要删除这个问题吗?', '提示', {
+              confirmButtonText: '确定',
+              cancelButtonText: '取消',
+              type: 'warning'
+            }).then(() => {
+              this.form.answers.splice(index, 1)
+              this.$message({
+                type: 'success',
+                message: '删除成功!'
+              });
+            }).catch(() => {
+              this.$message({
+                type: 'info',
+                message: '已取消删除'
+              });          
+            });
+          } else {
+            this.$message.warning('至少保留一个问题')
+          }
+        },
+        addOption(answerIndex, optionIndex) {
+          this.form.answers[answerIndex].options.push('')
+        },
+        delOption(options, index) {
+          if (options.length > 1) {
+            this.$confirm('确定要删除这个选项吗?', '提示', {
+              confirmButtonText: '确定',
+              cancelButtonText: '取消',
+              type: 'warning'
+            }).then(() => {
+              options.splice(index, 1)
+              this.$message({
+                type: 'success',
+                message: '删除成功!'
+              });
+            }).catch(() => {
+              this.$message({
+                type: 'info',
+                message: '已取消删除'
+              });          
+            });
+          } else {
+            this.$message.warning('至少保留一个选项')
+          }
+        },
+    // addItem(length) {
+    //   this.form.answers.push({
+    //     title: '',
+    //     options: [],
+    //   })
+    // },
+    // delItem(item, index) {
+    //   this.form.answers.splice(index, 1)
+    // },
+    // addItem1(length,n) {
+    //   this.form.answers[n].options.push('')
+    // },
+    // delItem2(item, index) {
+    //   this.form.answers.splice(index, 1)
+    // },
+    /** 查询问答列表 */
+    getList() {
+      this.loading = true;
+      listAnswer(this.queryParams).then(response => {
+        this.answerList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        jsonInfo: null,
+        createTime: null,
+        updateTime: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length !== 1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加问答";
+      if (this.form.answers == null) {
+        this.form = {
+          answers: [{
+            title: '',
+            options: ['']
+          }
+
+          ]
+        }
+      }
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getAnswer(id).then(response => {
+        this.form = response.data;
+        if (this.form.answers == null) {
+          this.form = {
+            answers: [{
+              title: '',
+              options: []
+            }
+
+            ]
+          }
+        }
+        this.form.questionName = response.data.questionName;
+        this.form.id = response.data.id;
+        this.open = true;
+        this.title = "修改问答";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          if (this.form.answers) {
+            this.form.jsonInfo = JSON.stringify(this.form.answers);
+          }
+          if (this.form.id != null) {
+            updateAnswer(this.form).then(response => {
+              this.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            addAnswer(this.form).then(response => {
+              this.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除问答编号为"' + ids + '"的数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function () {
+        return delAnswer(ids);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("删除成功");
+      }).catch(() => { });
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有问答数据项?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(() => {
+        this.exportLoading = true;
+        return exportAnswer(queryParams);
+      }).then(response => {
+        this.download(response.msg);
+        this.exportLoading = false;
+      }).catch(() => { });
+    }
+  }
+};
+</script>
+<style>
+    .form-container {
+      max-width: 900px;
+      margin: 30px auto;
+      padding: 25px;
+      background: #fff;
+      border-radius: 10px;
+      box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
+    }
+    .form-header {
+      margin-bottom: 25px;
+      padding-bottom: 15px;
+      border-bottom: 1px solid #ebeef5;
+    }
+    .form-header h2 {
+      margin: 0;
+      color: #303133;
+      font-size: 22px;
+    }
+    .form-header p {
+      margin: 8px 0 0;
+      color: #606266;
+      font-size: 14px;
+    }
+    .answer-section {
+      margin: 25px 0;
+      padding: 20px;
+      border: 1px solid #e6e9f0;
+      border-radius: 8px;
+      background-color: #f9fafc;
+      transition: all 0.3s ease;
+    }
+    .answer-section:hover {
+      border-color: #c0c4cc;
+      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+    }
+    .answer-section-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 20px;
+      padding-bottom: 12px;
+      border-bottom: 1px dashed #dcdfe6;
+    }
+    .answer-section-title {
+      font-weight: 600;
+      color: #303133;
+      font-size: 16px;
+    }
+    .answer-section-number {
+      display: inline-flex;
+      align-items: center;
+      justify-content: center;
+      width: 24px;
+      height: 24px;
+      background: #409EFF;
+      color: white;
+      border-radius: 50%;
+      font-size: 12px;
+      margin-right: 8px;
+    }
+    .option-item {
+      display: flex;
+      align-items: center;
+      margin-bottom: 12px;
+    }
+    .option-input {
+      flex: 1;
+    }
+    .option-actions {
+      margin-left: 10px;
+      display: flex;
+      gap: 5px;
+    }
+    .section-actions {
+      display: flex;
+      justify-content: flex-end;
+      margin-top: 20px;
+    }
+    .add-section-btn {
+      margin-top: 15px;
+      text-align: center;
+    }
+    .el-form-item {
+      margin-bottom: 20px;
+    }
+    .el-col {
+      padding-right: 15px;
+    }
+    .el-col:last-child {
+      padding-right: 0;
+    }
+    .option-tip {
+      margin-top: 10px;
+      color: #909399;
+      font-size: 12px;
+    }
+    .empty-state {
+      text-align: center;
+      padding: 30px;
+      color: #909399;
+    }
+    .empty-state-icon {
+      font-size: 48px;
+      margin-bottom: 15px;
+      color: #c0c4cc;
+    }
+  </style>
+

+ 26 - 1
src/views/his/inquiryOrder/order1.vue

@@ -47,6 +47,17 @@
              @keyup.enter.native="handleQuery"
            />
        </el-form-item>
+       
+       <el-form-item label="所属小程序" prop="coursePlaySourceConfigId">
+         <el-select v-model="queryParams.coursePlaySourceConfigId" placeholder="请选择所属小程序" clearable size="small">
+           <el-option
+             v-for="dict in appMallOptions"
+             :key="dict.id"
+             :label="dict.name + '(' + dict.appid + ')'"
+             :value="dict.id"
+           />
+         </el-select>
+       </el-form-item>
         <el-form-item label="问诊开始时间" prop="startTime">
            <el-date-picker v-model="startTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="change"></el-date-picker>
         </el-form-item>
@@ -101,6 +112,7 @@
       <el-table-column label="问诊标题" align="center" prop="title" show-overflow-tooltip />
       <el-table-column label="病人名称" align="center" prop="patientName" />
       <el-table-column label="医生名称" align="center" prop="doctorName" />
+      <el-table-column label="小程序名称" align="center" prop="miniProgramName" width="120px" />
       <el-table-column label="状态" align="center" prop="status" >
         <template slot-scope="scope">
           <dict-tag :options="inquiryStatusOptions" :value="scope.row.status" />
@@ -198,6 +210,7 @@ import inquiryOrderDetails from '../../components/his/inquiryOrderDetails.vue';
 import msgDetails from '../../components/his/msgDetails.vue';
 import msgServiceDetails from '../../components/his/msgServiceDetails.vue';
 import { getTask } from "@/api/common";
+import {list as getAppMallOptions} from '@/api/course/coursePlaySourceConfig';
 export default {
   name: "inquiryOrder",
   components: { inquiryOrderDetails,msgDetails,msgServiceDetails },
@@ -275,6 +288,7 @@ export default {
         doctorName:null,
         patientName:null,
         sendName:null,
+        coursePlaySourceConfigId:null,
       },
       // 表单参数
       form: {},
@@ -286,6 +300,7 @@ export default {
       inquiryPayOptions:[],
       inquiryOrderOptions:[],
       orOptions:[],
+      appMallOptions:[],
     };
   },
 
@@ -308,6 +323,10 @@ export default {
       this.getDicts("sys_inquiry_sub_type").then(response => {
         this.inquirySubTypeOptions = response.data;
       });
+      
+      // 获取小程序选项列表
+      this.getAppMallOptions();
+      
     this.getList();
   },
   methods: {
@@ -543,7 +562,13 @@ export default {
 			},10000);
 		  }
         }).catch(() => {});
-    }
+    },
+    // 获取小程序选项列表
+    getAppMallOptions() {
+      getAppMallOptions({pageNum:1,pageSize:100,isMall:1}).then(response => {
+        this.appMallOptions = response.rows;
+      })
+    },
   }
 };
 </script>

+ 25 - 1
src/views/his/inquiryOrder/order2.vue

@@ -37,6 +37,17 @@
       <el-form-item label="会员电话" prop="phone">
            <el-input v-model="queryParams.phone" placeholder="请输入会员电话"  clearable  size="small" @keyup.enter.native="handleQuery"/>
        </el-form-item>
+       
+       <el-form-item label="所属小程序" prop="coursePlaySourceConfigId">
+         <el-select v-model="queryParams.coursePlaySourceConfigId" placeholder="请选择所属小程序" clearable size="small">
+           <el-option
+             v-for="dict in appMallOptions"
+             :key="dict.id"
+             :label="dict.name + '(' + dict.appid + ')'"
+             :value="dict.id"
+           />
+         </el-select>
+       </el-form-item>
 
 
 
@@ -94,6 +105,7 @@
       <el-table-column label="咨询标题" align="center" prop="title" show-overflow-tooltip />
       <el-table-column label="病人名称" align="center" prop="patientName" />
       <el-table-column label="医生名称" align="center" prop="doctorName" />
+      <el-table-column label="小程序名称" align="center" prop="miniProgramName" width="120px" />
       <el-table-column label="员工" align="center" prop="companyUserName" />
       <el-table-column label="公司" align="center" prop="companyName" />
       <el-table-column label="状态" align="center" prop="status" >
@@ -193,6 +205,7 @@ import {allList}from "@/api/company/company";
 import inquiryOrderDetails from '../../components/his/inquiryOrderDetails.vue';
 import msgDetails from '../../components/his/msgDetails.vue';
 import { getTask } from "@/api/common";
+import {list as getAppMallOptions} from '@/api/course/coursePlaySourceConfig';
 export default {
   name: "ofast",
   components: { inquiryOrderDetails,msgDetails },
@@ -268,6 +281,7 @@ export default {
         phone:null,
         inquirySubType:null,
         companyUserName:null,
+        coursePlaySourceConfigId:null,
       },
       // 表单参数
       form: {},
@@ -281,6 +295,7 @@ export default {
       inquiryOrderOptions:[],
       inquirySubTypeOptions:[],
       orOptions:[],
+      appMallOptions:[],
     };
   },
   created() {
@@ -305,6 +320,9 @@ export default {
 
     this.getList();
     this.getAllCompany();
+    
+    // 获取小程序选项列表
+    this.getAppMallOptions();
   },
   methods: {
     getMsg(row){
@@ -569,7 +587,13 @@ export default {
 		   },10000);
 		 }
         }).catch(() => {});
-    }
+    },
+    // 获取小程序选项列表
+    getAppMallOptions() {
+      getAppMallOptions({pageNum:1,pageSize:100,isMall:1}).then(response => {
+        this.appMallOptions = response.rows;
+      })
+    },
   }
 };
 </script>

+ 27 - 0
src/views/his/inquiryOrder/order3.vue

@@ -49,6 +49,17 @@
            <el-input v-model="queryParams.phone" placeholder="请输入会员电话"  clearable  size="small" @keyup.enter.native="handleQuery"/>
        </el-form-item>
 
+      <el-form-item label="所属小程序" prop="coursePlaySourceConfigId">
+        <el-select v-model="queryParams.coursePlaySourceConfigId" placeholder="请选择所属小程序" clearable size="small">
+          <el-option
+            v-for="dict in appMallOptions"
+            :key="dict.id"
+            :label="dict.name + '(' + dict.appid + ')'"
+            :value="dict.id"
+          />
+        </el-select>
+      </el-form-item>
+
       <el-form-item label="订单类型" prop="orderType">
          <el-select v-model="queryParams.orderType" placeholder="状态" clearable size="small">
                  <el-option
@@ -155,6 +166,7 @@
 
       </el-table-column>
       <el-table-column label="科室名称" align="center" prop="deptName" />
+      <el-table-column label="小程序名称" align="center" prop="miniProgramName" width="120px" />
       <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="100px">
         <template slot-scope="scope">
        <el-button
@@ -200,11 +212,13 @@ import inquiryOrderDetails from '../../components/his/inquiryOrderDetails.vue';
 import msgDetails from '../../components/his/msgDetails.vue';
 import {allList}from "@/api/company/company";
 import { getTask } from "@/api/common";
+import {list as getAppMallOptions} from '@/api/course/coursePlaySourceConfig';
 export default {
   name: "omedicine",
   components: { inquiryOrderDetails,msgDetails },
   data() {
     return {
+      appMallOptions: [],
       companyList:[],
       msgForm:{
           pageNum: 1,
@@ -274,6 +288,7 @@ export default {
         patientName:null,
         sendName:null,
         phone:null,
+        coursePlaySourceConfigId:null,
       },
       // 表单参数
       form: {},
@@ -286,6 +301,7 @@ export default {
       inquiryOrderOptions:[],
       inquirySubTypeOptions:[],
       orOptions:[],
+      appMallOptions:[],
     };
   },
   created() {
@@ -307,6 +323,10 @@ export default {
     this.getDicts("sys_inquiry_sub_type").then(response => {
       this.inquirySubTypeOptions = response.data;
     });
+    
+    // 获取小程序选项列表
+    this.getAppMallOptions();
+    
     this.getList();
     this.getAllCompany();
   },
@@ -316,6 +336,12 @@ export default {
         this.companyList = response.rows;
       });
     },
+    // 获取小程序选项列表
+    getAppMallOptions() {
+      getAppMallOptions({pageNum:1,pageSize:100,isMall:1}).then(response => {
+        this.appMallOptions = response.rows;
+      })
+    },
     getMsg(row){
       const orderId = row.orderId;
       const doctorName = row.doctorName;
@@ -417,6 +443,7 @@ export default {
     this.startTime=null;
     this.queryParams.sTime=null;
     this.queryParams.eTime=null;
+    this.queryParams.coursePlaySourceConfigId=null;
     this.handleQuery();
   },
   change(){

+ 77 - 30
src/views/his/inquiryOrderReport/index.vue

@@ -1,10 +1,13 @@
 <template>
   <div class="app-container">
-    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
-      <el-form-item label="所属公司" prop="companyId" >
-      <el-select v-model="queryParams.companyId" placeholder="请选择所属公司" filterable size="small">
-            <el-option v-for="(option, index) in companyList" :key="index" :value="option.dictValue" :label="option.dictLabel"></el-option>
-       </el-select>
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="100px">
+      <el-form-item label="所属公司" prop="companyId">
+        <el-select v-model="queryParams.companyId" placeholder="请选择所属公司" filterable clearable size="small">
+          <el-option v-for="(option, index) in companyList" :key="index" :value="option.dictValue" :label="option.dictLabel"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="员工" prop="companyUserNickName">
+        <el-input v-model="queryParams.companyUserNickName" placeholder="请输入员工名称" clearable size="small" @keyup.enter.native="handleQuery"/>
       </el-form-item>
       <el-form-item label="订单号" prop="orderId">
         <el-input
@@ -15,8 +18,7 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-
-      <el-form-item label="报告编号" prop="reportSn" >
+      <el-form-item label="报告编号" prop="reportSn">
         <el-input
           v-model="queryParams.reportSn"
           placeholder="请输入报告编号"
@@ -26,14 +28,11 @@
         />
       </el-form-item>
       <el-form-item label="子类型" prop="inquirySubType">
-         <el-select v-model="queryParams.inquirySubType" placeholder="子类型" clearable size="small">
-            <el-option v-for="dict in inquirySubTypeOptions" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" />
-         </el-select>
-      </el-form-item>
-      <el-form-item label="员工" prop="companyUserNickName">
-           <el-input  v-model="queryParams.companyUserNickName"  placeholder="请输入员工名称" clearable size="small" @keyup.enter.native="handleQuery"/>
+        <el-select v-model="queryParams.inquirySubType" placeholder="子类型" clearable size="small">
+          <el-option v-for="dict in inquirySubTypeOptions" :key="dict.dictValue" :label="dict.dictLabel" :value="dict.dictValue" />
+        </el-select>
       </el-form-item>
-      <el-form-item label="患者名称" prop="patientName" >
+      <el-form-item label="患者名称" prop="patientName">
         <el-input
           v-model="queryParams.patientName"
           placeholder="请输入患者名称"
@@ -42,7 +41,7 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="手机号" prop="patientMobile" >
+      <el-form-item label="手机号" prop="patientMobile">
         <el-input
           v-model="queryParams.patientMobile"
           placeholder="请输入手机号"
@@ -51,7 +50,7 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="导医" prop="userName" >
+      <el-form-item label="导医" prop="userName">
         <el-input
           v-model="queryParams.userName"
           placeholder="请输入导医"
@@ -60,7 +59,7 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item>
-      <el-form-item label="医生名称" prop="doctorName" >
+      <el-form-item label="医生名称" prop="doctorName">
         <el-input
           v-model="queryParams.doctorName"
           placeholder="请输医生名称"
@@ -70,21 +69,34 @@
         />
       </el-form-item>
       <el-form-item label="咨询状态" prop="inquiryStatus">
-         <el-select v-model="queryParams.inquiryStatus" placeholder="状态" clearable size="small">
-                 <el-option
-                   v-for="dict in inquiryStatusOptions"
-                   :key="dict.dictValue"
-                   :label="dict.dictLabel"
-                   :value="dict.dictValue"
-                 />
-               </el-select>
+        <el-select v-model="queryParams.inquiryStatus" placeholder="状态" clearable size="small">
+          <el-option
+            v-for="dict in inquiryStatusOptions"
+            :key="dict.dictValue"
+            :label="dict.dictLabel"
+            :value="dict.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      
+      <el-form-item label="所属小程序" prop="coursePlaySourceConfigId">
+        <el-select v-model="queryParams.coursePlaySourceConfigId" placeholder="请选择所属小程序" clearable size="small">
+          <el-option
+            v-for="dict in appMallOptions"
+            :key="dict.id"
+            :label="dict.name + '(' + dict.appid + ')'"
+            :value="dict.id"
+          />
+        </el-select>
       </el-form-item>
-       <el-form-item label="提交时间" prop="createTime">
-          <el-date-picker v-model="createTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="change"></el-date-picker>
+      
+      <el-form-item label="提交时间" prop="createTime">
+        <el-date-picker v-model="createTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="change"></el-date-picker>
       </el-form-item>
       <el-form-item label="首次分诊时间" prop="updateTime">
-          <el-date-picker v-model="updateTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="change"></el-date-picker>
+        <el-date-picker v-model="updateTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="change"></el-date-picker>
       </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>
@@ -119,6 +131,7 @@
       <el-table-column label="医生名称" align="center" prop="doctorName" />
       <el-table-column label="公司" align="center" prop="companyName" />
       <el-table-column label="员工" align="center" prop="companyUserName" />
+      <el-table-column label="小程序名称" align="center" prop="miniProgramName" width="120px" />
       <el-table-column label="咨询结果" align="center" prop="inquiryResult" />
       <el-table-column label="状态" align="center" prop="status">
         <template slot-scope="scope">
@@ -368,6 +381,7 @@ import {listdocuser} from "@/api/his/doctor";
 import { getIllness } from "@/api/his/illnessLibrary";
 import {allList}from "@/api/company/company";
 import { getTask } from "@/api/common";
+import {list as getAppMallOptions} from '@/api/course/coursePlaySourceConfig';
 export default {
   name: "InquiryOrderReport",
   components: { inquiryOrderReportDetails },
@@ -432,6 +446,7 @@ export default {
       inquiryStatusOptions:[],
       inquirySubTypeOptions:[],
       companyList:[],
+      appMallOptions:[],
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -448,6 +463,7 @@ export default {
         userName: null,
         inquiryStatus:null,
         doctorName:null,
+        coursePlaySourceConfigId:null,
       },
       // 表单参数
       form: {},
@@ -479,6 +495,10 @@ export default {
     getBody().then(response => {
           this.body=response;
       });
+    
+    // 获取小程序选项列表
+    this.getAppMallOptions();
+    
     this.getAllCompany();
   },
   methods: {
@@ -511,6 +531,12 @@ export default {
         this.companyList = response.rows;
       });
     },
+    // 获取小程序选项列表
+    getAppMallOptions() {
+      getAppMallOptions({pageNum:1,pageSize:100,isMall:1}).then(response => {
+        this.appMallOptions = response.rows;
+      })
+    },
     selectOK(rows){
 
       if(this.form.inquiryResult==null){
@@ -603,9 +629,14 @@ export default {
     resetQuery() {
       this.resetForm("queryForm");
       this.createTime=null;
+      this.updateTime=null;
       this.queryParams.sTime=null;
       this.queryParams.eTime=null;
-      this.inquiryStatus=null;
+      this.queryParams.beginTime=null;
+      this.queryParams.endTime=null;
+      this.queryParams.coursePlaySourceConfigId=null;
+      // 注意:不重置status,保持当前tab状态
+      // this.queryParams.status 保持不变
       this.handleQuery();
     },
     // 多选框选中数据
@@ -888,7 +919,23 @@ export default {
           },10000);
         }
         }).catch(() => {});
-    }
+    },
+    /** tab切换操作 */
+    handleClickX(tab, event) {
+      if(tab.name=="10"){
+        this.queryParams.status=null;
+      }else{
+        this.queryParams.status=tab.name;
+      }
+      this.handleQuery();
+    },
+    /** 查看详情操作 */
+    handledetails(row){
+      this.show.open=true;
+      setTimeout(() => {
+        this.$refs.Details.getDetails(row.reportId);
+      }, 1);
+    },
   }
 };
 </script>

+ 15 - 0
src/views/his/package/index.vue

@@ -569,6 +569,16 @@
             />
           </el-select>
         </el-form-item>
+        <el-form-item label="问答" prop="questionId" >
+           <el-select v-model="form.questionId" placeholder="请选择问答">
+              <el-option
+                  v-for="dict in questionOptions"
+                  :key="dict.dictValue"
+                  :label="dict.dictLabel"
+                  :value="parseInt(dict.dictValue)"
+                />
+           </el-select>
+        </el-form-item>
       </el-form>
       <div slot="footer" class="dialog-footer">
         <el-button type="primary" @click="submitForm">确 定</el-button>
@@ -653,6 +663,7 @@ import {
 import {getAllFollowTempName } from "@/api/his/followTemp";
 import {getAllCateList} from "@/api/his/packageCate";
 import {allIcd } from "@/api/his/icd";
+import {questionOptions } from "@/api/his/answer";
 import packageDetails from '../../components/his/packageDetails.vue';
 import productAttrValueSelect from "../../components/his/productAttrValueSelect.vue";
 import { listStore } from "@/api/his/storeProduct";
@@ -702,6 +713,7 @@ export default {
               url: process.env.VUE_APP_BASE_API + "/his/package/importData"
             },
       productTypeOptions: [],
+      questionOptions: [],
       storeId:null,
       storeOPtions:[],
       usageFrequencyUnitOptions:[{
@@ -856,6 +868,9 @@ export default {
     listStore().then(response => {
       this.storeOPtions = response.rows;
     });
+    questionOptions().then(res => {
+      this.questionOptions = res.rows;
+    })
   },
   methods: {
     getSolarTermLabel(solarTerm) {

+ 59 - 6
src/views/his/packageOrder/index.vue

@@ -109,6 +109,17 @@
         </el-select>
       </el-form-item>
 
+      <el-form-item label="所属小程序" prop="coursePlaySourceConfigId">
+        <el-select v-model="queryParams.coursePlaySourceConfigId" placeholder="请选择所属小程序" clearable size="small">
+          <el-option
+            v-for="dict in appMallOptions"
+            :key="dict.id"
+            :label="dict.name + '(' + dict.appid + ')'"
+            :value="dict.id"
+          />
+        </el-select>
+      </el-form-item>
+
       <el-form-item label="开始时间" prop="startTime">
         <el-date-picker v-model="startTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="startChange"></el-date-picker>
       </el-form-item>
@@ -146,6 +157,7 @@
       <el-table-column label="订单号" align="center" prop="orderSn" width="120px"/>
       <el-table-column label="所属公司" align="center" prop="companyName" />
       <el-table-column label="员工" align="center" prop="companyUserName" />
+      <el-table-column label="小程序名称" align="center" prop="miniProgramName" width="120px" />
       <el-table-column label="套餐名称" align="center" prop="packageName" />
       <el-table-column label="套餐别名" align="center" prop="packageSecondName" width="100px"/>
       <el-table-column label="天数" align="center" prop="days" />
@@ -286,6 +298,7 @@ import { treeselect } from "@/api/company/companyDept";
 import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 import { getTask } from "@/api/common";
+import {list as getAppMallOptions} from '@/api/course/coursePlaySourceConfig';
 export default {
   watch: {
     // 监听deptId
@@ -309,6 +322,8 @@ export default {
       startTime:null,
       // 导出遮罩层
       exportLoading: false,
+      // 导出任务检查计数器
+      exportCheckCount: 0,
       // 选中数组
       ids: [],
       createTime:null,
@@ -336,6 +351,7 @@ export default {
       payTypeOptions:[],
       deliveryPayStatusOptions:[],
       deliveryStatusOptions:[],
+      appMallOptions:[],
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -364,6 +380,7 @@ export default {
         companyName:null,
         deptId:null,
         source:null,
+        coursePlaySourceConfigId:null,
       },
       // 表单参数
       form: {},
@@ -406,6 +423,9 @@ export default {
     this.getDicts("sys_package_sub_type").then(response => {
       this.packageSubTypeOptions = response.data;
     });
+    
+    // 获取小程序选项列表
+    this.getAppMallOptions();
   },
   methods: {
     /** 查询套餐订单列表 */
@@ -569,27 +589,54 @@ export default {
         this.exportLoading = true;
         return exportPackageOrder(queryParams);
       }).then(response => {
-       
-          if(response.code==200){
+        if(response.code==200){
           that.msgSuccess(response.msg);
           that.taskId=response.data;
+          that.exportCheckCount = 0; // 添加检查计数器
           that.time=setInterval(function(){
-            //查订单
+            that.exportCheckCount++;
+            //查任务状态
             getTask(that.taskId).then(res => {
+              // 任务完成
               if(res.data.status==1){
                 that.exportLoading = false;
-                clearTimeout(that.time)
+                clearInterval(that.time);
                 that.time=null;
                 that.download(res.data.fileUrl);
               }
+              // 任务失败
+              else if(res.data.status==-1 || res.data.status==2){
+                that.exportLoading = false;
+                clearInterval(that.time);
+                that.time=null;
+                that.msgError('导出任务失败,请重试');
+              }
+              // 超时处理(检查超过30次,即5分钟)
+              else if(that.exportCheckCount > 30){
+                that.exportLoading = false;
+                clearInterval(that.time);
+                that.time=null;
+                that.msgError('导出任务超时,请稍后重试');
+              }
+            }).catch(err => {
+              // API调用失败
+              that.exportCheckCount++;
+              if(that.exportCheckCount > 30){
+                that.exportLoading = false;
+                clearInterval(that.time);
+                that.time=null;
+                that.msgError('导出任务查询失败,请重试');
+              }
             });
-          },10000);
+          },10000); // 10秒查询一次
         }
         else{
           that.msgError(response.msg);
           that.exportLoading = false;
         }
-      }).catch(() => {});
+      }).catch(() => {
+        that.exportLoading = false;
+      });
     },
     /** 查询部门下拉树结构 */
     getTreeselect() {
@@ -611,6 +658,12 @@ export default {
       this.queryParams.deptId=val;
       this.getList();
     },
+    // 获取小程序选项列表
+    getAppMallOptions() {
+      getAppMallOptions({pageNum:1,pageSize:100,isMall:1}).then(response => {
+        this.appMallOptions = response.rows;
+      })
+    },
   }
 };
 </script>

+ 352 - 0
src/views/his/statistics/afterSalesOrder.vue

@@ -0,0 +1,352 @@
+<template>
+    <div class="app-container">
+        <div class="app-content">
+             <div class="title">
+               售后订单统计
+            </div>
+           <el-form class="search-form" :inline="true" >
+            <el-form-item >
+              <el-select v-model="value" placeholder="请选择日期">
+                <el-option
+                  v-for="item in options"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value">
+                </el-option>
+              </el-select>
+            </el-form-item>
+            <el-form-item >
+              <treeselect :clearable="false"  v-model="deptId"  :options="deptOptions" :show-count="true" placeholder="请选择归属部门" />
+            </el-form-item>
+            <el-form-item>
+              <el-select filterable v-model="userIds" placeholder="请选择员工" clearable size="small">
+                  <el-option
+                    v-for="item in users"
+                    :key="item.userId"
+                    :label="item.nickName"
+                    :value="item.userId">
+                  </el-option>
+                </el-select>
+            </el-form-item>
+           <el-form-item label="下单日期" prop="createTime">
+                    <el-date-picker clearable size="small" style="width: 205.4px"
+                      v-model="dateRange"
+                      type="daterange"
+                      value-format="yyyy-MM-dd"
+                      start-placeholder="开始日期" end-placeholder="结束日期"
+                      >
+                    </el-date-picker>
+            </el-form-item>
+            <el-form-item>
+                <el-button type="cyan" icon="el-icon-search"   @click="afterSalesOrder">搜索</el-button>
+            </el-form-item>
+          </el-form>
+           <div class="data-box">
+              <div class="echart-box">
+                <div id="echart-customer"></div>
+              </div>
+              <div class="table-box">
+                    <el-button class="export" size="small"  @click="handleExport" >导出</el-button>
+                    <el-table
+                    :data="list"
+                    border
+                    :summary-method="getSummaries"
+                    show-summary
+                    max-height="500"
+                    style="width: 100%;">
+                    <el-table-column
+                      prop="nickName"
+                      label="员工姓名">
+                    </el-table-column>
+                    <el-table-column
+                      prop="orderCount"
+                      label="订单数">
+                    </el-table-column>
+                    <el-table-column
+                      prop="payPrice"
+                      label="订单金额">
+                    </el-table-column>
+  
+                  </el-table>
+              </div>
+          </div>
+        </div>
+  
+      </div>
+  </template>
+  
+  <script>
+  import { afterSalesOrder,exportAfterSalesOrder } from "@/api/company/statistics";
+  import { getUserListByDeptId} from "@/api/company/companyUser";
+  import echarts from 'echarts'
+  import resize from '../../dashboard/mixins/resize'
+  import { treeselect } from "@/api/company/companyDept";
+  import Treeselect from "@riophae/vue-treeselect";
+  import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+  
+  export default {
+  name: 'Index',
+  mixins: [resize],
+  components: { Treeselect },
+  watch: {
+  // 监听deptId
+  'deptId': 'currDeptChange'
+  },
+  data() {
+  return {
+   deptOptions:[],
+   deptId:undefined,
+   userIds:undefined,
+   users:[],
+   dateRange:[],
+   chart: null,
+   options: [{
+      value: '1',
+      label: '今天'
+    }, {
+      value: '2',
+      label: '昨天'
+    }, {
+      value: '3',
+      label: '本周'
+    }, {
+      value: '4',
+      label: '上周'
+    }, {
+      value: '5',
+      label: '本月'
+    }
+    , {
+      value: '6',
+      label: '上月'
+    }
+    , {
+      value: '7',
+      label: '本季度'
+    }
+    , {
+      value: '8',
+      label: '上季度'
+    }
+    , {
+      value: '9',
+      label: '本年'
+    }
+    , {
+      value: '10',
+      label: '上年'
+    }],
+    value: '5',
+    list:[],
+    dates:[],
+    orderCount:[],
+    payPrice:[],
+  
+  }
+  },
+  created() {
+  this.getTreeselect();
+  },
+  methods: {
+    currDeptChange(val){
+    console.log(val)
+    this.deptId=val;
+    this.getUserListByDeptId();
+  },
+  /** 查询部门下拉树结构 */
+  getTreeselect() {
+  var that=this;
+  treeselect().then((response) => {
+    this.deptOptions = response.data;
+    console.log(this.deptOptions)
+    if(response.data!=null&&response.data.length>0){
+      this.deptId=response.data[0].id;
+      that.afterSalesOrder()
+    }
+  });
+  },
+  handleExport(){
+    var data;
+    if(this.userIds!=undefined){
+        data={type:this.value,userIds:this.userIds+"",deptId:this.deptId}
+    }
+    else{
+        data={type:this.value,deptId:this.deptId}
+    }
+    if(this.dateRange){
+        data.startTime = this.dateRange[0];
+        data.endTime = this.dateRange[1];
+      }
+    exportAfterSalesOrder(data).then((response) => {
+        console.log(response)
+       this.download(response.msg);
+    });
+  
+  },
+  getUserListByDeptId() {
+    this.userIds=undefined;
+    var data={deptId:this.deptId};
+    getUserListByDeptId(data).then(response => {
+      this.users = response.data;
+  
+    });
+  },
+  afterSalesOrder(){
+      var data;
+      if(this.userIds!=undefined){
+          data={type:this.value,userIds:this.userIds+"",deptId:this.deptId}
+      }
+      else{
+          data={type:this.value,deptId:this.deptId}
+      }
+      if(this.dateRange){
+        data.startTime = this.dateRange[0];
+        data.endTime = this.dateRange[1];
+      }
+      afterSalesOrder(data).then((response) => {
+       this.list=response.list;
+       this.dates=response.dates;
+       this.orderCount=response.orderCount;
+       this.payPrice=response.payPrice;
+        setTimeout(() => {
+          this.initEchart();
+        }, 500);
+    });
+  },
+  initEchart(){
+    var option = {
+      tooltip: {
+          trigger: 'axis',
+          axisPointer: {            // 坐标轴指示器,坐标轴触发有效
+              type: 'shadow'        // 默认为直线,可选为:'line' | 'shadow'
+          }
+      },
+      legend: {
+          data: ['订单数', '订单金额' ]
+      },
+      grid: {
+          left: '3%',
+          right: '4%',
+          bottom: '3%',
+          containLabel: true
+      },
+      xAxis: [
+          {
+              type: 'category',
+              data: this.dates
+          }
+      ],
+      yAxis: [
+          {
+              type: 'value',
+              axisLabel:{
+                formatter:'{value}'
+              }
+          }
+      ],
+      series: [
+          {
+  
+              name: '订单数',
+              type: 'line',
+              emphasis: {
+                  focus: 'series'
+              },
+              data: this.orderCount
+          },
+          {
+  
+              name: '订单金额',
+              type: 'line',
+              emphasis: {
+                  focus: 'series'
+              },
+              data: this.payPrice
+          }
+  
+      ]
+    };
+    this.chart=echarts.init(document.getElementById("echart-customer"));
+    this.chart.setOption(option,true);
+  },
+   getSummaries(param) {
+    const { columns, data } = param;
+    const sums = [];
+    columns.forEach((column, index) => {
+      if (index === 0) {
+        sums[index] = '总计';
+        return;
+      }
+      const values = data.map(item => Number(item[column.property]));
+      if (!values.every(value => isNaN(value))) {
+        const total = values.reduce((prev, curr) => {
+          const value = Number(curr);
+          return !isNaN(value) ? prev + curr : prev;
+        }, 0);
+        sums[index] = total.toFixed(2);
+      } else {
+        sums[index] = '';
+      }
+    });
+  
+    return sums;
+  }
+  }
+  }
+  </script>
+  
+  <style lang="scss" scoped>
+  .app-container{
+  border: 1px solid #e6e6e6;
+  padding: 12px;
+  
+  .app-content{
+  background-color: white;
+  .title{
+    padding: 20px 30px 0px 30px;
+    font-size: 18px;
+    font-weight: bold;
+    color: black;
+  
+  }
+  .search-form{
+    margin: 20px 30px 0px 30px;
+  }
+  .data-box{
+    padding: 30px;
+    background-color:  rgb(255, 255, 255);
+    height: 100%;
+  
+    .echart-box{
+      margin: 0 auto;
+      text-align: center;
+    }
+    .el-select{
+      margin: 5px 10px;
+    }
+    .table-box{
+      margin-top: 15px;
+      .export{
+        float: right;
+        margin: 10px 0px;
+      }
+    }
+  }
+  }
+  }
+  #echart-customer{
+  width:100%;
+  height:320px
+  }
+  .vue-treeselect{
+  width: 217px;
+  height: 36px;
+  }
+  
+  </style>
+  <style>
+  .vue-treeselect__control{
+  display: block;
+  }
+  </style>
+  

+ 54 - 64
src/views/his/storeOrder/order1.vue

@@ -292,6 +292,17 @@
         </el-select>
       </el-form-item>
 
+      <el-form-item label="所属小程序" prop="coursePlaySourceConfigId">
+        <el-select v-model="queryParams.coursePlaySourceConfigId" placeholder="请选择所属小程序" clearable size="small">
+          <el-option
+            v-for="dict in appMallOptions"
+            :key="dict.id"
+            :label="dict.name + '(' + dict.appid + ')'"
+            :value="dict.id"
+          />
+        </el-select>
+      </el-form-item>
+
       <el-form-item label="下单时间" prop="createTime">
             <el-date-picker v-model="createTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="changeTime"></el-date-picker>
       </el-form-item>
@@ -474,8 +485,8 @@
       <el-table ref="orderTable" height="500" v-loading="loading" border :data="orderList" @selection-change="handleSelectionChange"
         @sort-change="handleSortChange" :default-sort="{prop: 'createTime', order: 'descending'}">
         <el-table-column type="selection" width="55" align="center" />
-        <el-table-column label="ERP电话" align="center" prop="erpPhone" v-if="SFDFopen && orderStatus!=null && orderStatus != 1"/>
-        <el-table-column label="ERP账号" align="center" prop="erpAccount" v-if="SFDFopen && orderStatus!=null && orderStatus != 1"/>
+        <el-table-column label="ERP电话" align="center" prop="erpPhone" width="120px" v-if="SFDFopen && orderStatus!=null && orderStatus != 1"/>
+        <el-table-column label="ERP账号" align="center" prop="erpAccount" width="120px" v-if="SFDFopen && orderStatus!=null && orderStatus != 1"/>
         <el-table-column label="处方单编号" align="center" prop="prescribeCode" width="180px"/>
         <el-table-column label="药品订单号" align="center" prop="orderCode" width="180px"/>
         <el-table-column label="所属公司" align="center" prop="companyName" />
@@ -486,6 +497,7 @@
           </template>
         </el-table-column>
         <el-table-column label="店铺名称" align="center" prop="storeName" />
+        <el-table-column label="小程序名称" align="center" prop="miniProgramName" width="120px" />
         <el-table-column label="就诊人" align="center" prop="patientName" />
         <el-table-column label="收货人" align="center" prop="userName" />
         <el-table-column label="套餐名称" align="center" prop="packageName" width="100px" sortable="custom" :sort-orders="['ascending', 'descending']">
@@ -534,7 +546,7 @@
                 <dict-tag :options="deliveryPayStatusOptions" :value="scope.row.deliveryPayStatus"/>
           </template>
         </el-table-column>
-        <el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right">
+        <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="100px" fixed="right">
           <template slot-scope="scope">
               <el-button
                   size="mini"
@@ -751,9 +763,6 @@
               </el-option>
             </el-select>
           </el-form-item>
-          <el-form-item label="包裹数量">
-            <el-input-number v-model="erpAccountForm.parcelQuantity"  :min="1" :max="10" label="发货包裹数量(默认1)"></el-input-number>            
-          </el-form-item>
         </el-form>
         
         <!-- 订单统计信息 -->
@@ -851,6 +860,7 @@ import { treeselect } from "@/api/company/companyDept";
 import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 import { getTask } from "@/api/common";
+import {list as getAppMallOptions} from '@/api/course/coursePlaySourceConfig';
 export default {
   name: "Order",
   components: { storeOrderDetails,Treeselect  },
@@ -903,8 +913,7 @@ export default {
       erpAccountList: [], // ERP账户列表
       erpAccountQueryList:[], // ERP账户查询条件列表
       erpAccountForm: {
-        selectedAccount: [], // 选中的账户ID
-        parcelQuantity:1
+        selectedAccount: [] // 选中的账户ID
       },
       orderSummary: null, // 订单统计信息
       erpPhoneValue:[],
@@ -989,6 +998,7 @@ export default {
         { key: 'companyName', label: '所属公司', checked: true },
         { key: 'companyUserNickName', label: '所属销售', checked: true },
         { key: 'storeName', label: '店铺名称', checked: true },
+        { key: 'miniProgramName', label: '小程序名称', checked: true },
         { key: 'orderType', label: '订单类型', checked: false },
         { key: 'userName', label: '收货人姓名', checked: true },
         { key: 'userPhone', label: '收货人电话', checked: true },
@@ -1033,6 +1043,8 @@ export default {
         { key: 'packageCateName', label: '套餐包分类', checked: false },
         { key: 'age', label: '年龄', checked: false },
         { key: 'sex', label: '性别', checked: false },
+        { key: 'erpPhone', label: 'ERP电话', checked: false },
+        { key: 'erpAccount', label: 'ERP账号', checked: false },
         { key: 'source', label: '订单来源', checked: false }
       ],
       // 已选择的导出字段
@@ -1121,6 +1133,7 @@ export default {
 		    source:null,
         companyId:null,
         companyIds:null,
+        coursePlaySourceConfigId:null,
       },
       // 表单参数
       form: {},
@@ -1140,6 +1153,7 @@ export default {
        storeOPtions:[],
        deliveryPayStatusOptions:[],
        deliveryStatusOptions:[],
+       appMallOptions:[],
     };
   },
   created() {
@@ -1204,6 +1218,7 @@ export default {
           this.deliveryStatusOptions = response.data;
     });
     this.getErpAccountList();
+    this.getAppMallOptions();
   },
   methods: {
     // 新增排序处理方法
@@ -1552,11 +1567,12 @@ export default {
 
     async executSetErpOrder() {
       this.erpAccountDialog.submitting = true;
+      
       try {
         let param = {
-          loginAccount: this.erpAccountForm.selectedAccount,
-          parcelQuantity: this.erpAccountForm.parcelQuantity
+          loginAccount: this.erpAccountForm.selectedAccount
         };
+        
         if (this.ids.length > 0) {
           // 如果有选中的订单,只推送选中的
           param.orderIds = this.ids;
@@ -1597,6 +1613,7 @@ export default {
           this.$message.success('订单ERP账号设置成功');
           this.cancelErpAccountDialog();
           this.getErpAccountList(); // 刷新列表
+          this.getList();
         } else {
           this.$message.error(response.msg || 'ERP账号设置失败');
         }
@@ -1606,7 +1623,6 @@ export default {
       } finally {
         this.erpAccountDialog.submitting = false;
       }
-      this.erpAccountForm.parcelQuantity = 1
     },
     
     //执行创建ERP订单
@@ -1615,8 +1631,7 @@ export default {
       
       try {
         let param = {
-          loginAccount: this.erpAccountForm.selectedAccount,
-          parcelQuantity: this.erpAccountForm.parcelQuantity
+          loginAccount: this.erpAccountForm.selectedAccount
         };
         
         if (this.ids.length > 0) {
@@ -1659,6 +1674,7 @@ export default {
           this.$message.success('ERP订单创建成功');
           this.cancelErpAccountDialog();
           this.getErpAccountList(); // 刷新列表
+          this.getList();
         } else {
           this.$message.error(response.msg || 'ERP订单创建失败');
         }
@@ -1668,7 +1684,6 @@ export default {
       } finally {
         this.erpAccountDialog.submitting = false;
       }
-      this.erpAccountForm.parcelQuantity = 1
     },
     
     // 新增:取消ERP账户选择对话框
@@ -2250,7 +2265,7 @@ export default {
       this.unselectAllFields();
       // 然后选择常用字段
       const defaultFields = ['orderCode', 'prescribeCode', 'companyName', 'companyUserNickName', 
-                           'storeName', 'userName', 'userPhone', 'userAddress', 'totalPrice', 
+                           'storeName', 'miniProgramName', 'userName', 'userPhone', 'userAddress', 'totalPrice', 
                            'totalNum', 'payPrice', 'payMoney', 'createTime', 'payTime', 
                            'payType', 'status', 'packageName', 'patientName'];
       this.exportFieldOptions.forEach(field => {
@@ -2298,32 +2313,31 @@ export default {
       // 处理查询参数
       if(this.payTypeArr.length>0){
         this.queryParams.payType=this.payTypeArr.toString();
-      }
-      else{
+      } else {
         this.queryParams.payType=null
       }
+      
       if(this.scheduleIdArr.length>0){
         this.queryParams.scheduleId=this.scheduleIdArr.toString();
-      }
-      else{
+      } else {
         this.queryParams.scheduleId=null
       }
+      
       if(this.buyTypeArr.length>0){
         this.queryParams.orderBuyType=this.buyTypeArr.toString();
-      }
-      else{
+      } else {
         this.queryParams.orderbuyType=null
       }
+      
       if(this.channelArr.length>0){
         this.queryParams.orderChannel=this.channelArr.toString();
-      }
-      else{
+      } else {
         this.queryParams.orderChannel=null
       }
+      
       if(this.qwSubjectArr.length>0){
         this.queryParams.qwSubject=this.qwSubjectArr.toString();
-      }
-      else{
+      } else {
         this.queryParams.qwSubject=null
       }
       
@@ -2410,6 +2424,12 @@ export default {
           this.queryParams.deptId=val;
           this.getList();
     },
+    // 获取小程序选项列表
+    getAppMallOptions() {
+      getAppMallOptions({pageNum:1,pageSize:100,isMall:1}).then(response => {
+        this.appMallOptions = response.rows;
+      })
+    },
   }
 };
 </script>
@@ -2490,6 +2510,15 @@ export default {
   padding: 8px 0;
 }
 
+/* 表格布局优化 */
+.el-table {
+  min-width: 100%;
+  table-layout: fixed;
+}
+
+.el-table .el-table__body-wrapper {
+  overflow-x: auto;
+}
 
 .tip-text {
   display: flex;
@@ -2558,43 +2587,4 @@ export default {
     gap: 8px;
   }
 }
-
-/* 导出字段选择弹窗样式 */
-.field-selection-container {
-  max-height: 400px;
-  overflow-y: auto;
-  border: 1px solid #e4e7ed;
-  border-radius: 4px;
-  padding: 16px;
-  background-color: #fafafa;
-}
-
-.field-selection-container .el-checkbox {
-  display: flex;
-  align-items: center;
-  margin-right: 0;
-  margin-bottom: 8px;
-  padding: 8px 12px;
-  border-radius: 4px;
-  transition: background-color 0.3s;
-}
-
-.field-selection-container .el-checkbox:hover {
-  background-color: #f0f2f5;
-}
-
-.field-selection-container .el-checkbox.is-checked {
-  background-color: #e6f7ff;
-  border: 1px solid #91d5ff;
-}
-
-.field-count-info {
-  font-size: 14px;
-  color: #606266;
-}
-
-.field-count-info i {
-  margin-right: 8px;
-  color: #409EFF;
-}
 </style>

+ 10 - 2
src/views/his/storeOrder/order2.vue

@@ -79,7 +79,6 @@
       </el-form-item>
 
 
-
         <el-form-item label="创建时间" prop="createTime">
            <el-date-picker v-model="createTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="change"></el-date-picker>
         </el-form-item>
@@ -186,6 +185,7 @@ import { listPrescribe, getPrescribe, delPrescribe, addPrescribe, updatePrescrib
 import prescribeDetails from '../../components/his/prescribeDetails.vue';
 import {allList}from "@/api/company/company";
 import { getTask } from "@/api/common";
+import {list as getAppMallOptions} from '@/api/course/coursePlaySourceConfig';
 export default {
   name: "Prescribe",
   components: { prescribeDetails },
@@ -255,7 +255,8 @@ export default {
         auditSTime:null,
         auditETime:null,
         doctorName:null,
-        orderStatus:null
+        orderStatus:null,
+        appId:null
       },
        actName:"10",
       // 表单参数
@@ -267,6 +268,7 @@ export default {
       prescribeType:[],
       orOptions:[],
       sexOptions:[],
+      appMallOptions:[],
     };
   },
   created() {
@@ -287,9 +289,15 @@ export default {
         this.orderStatusOptions = response.data;
       });
 
+    this.getAppMallOptions();
     this.getList();
   },
   methods: {
+    getAppMallOptions() {
+      getAppMallOptions({pageNum:1,pageSize:100,isMall:1}).then(response => {
+        this.appMallOptions = response.rows;
+      })
+    },
     getAllCompany() {
       allList().then(response => {
         this.companyList = response.rows;

+ 24 - 1
src/views/his/storePayment/index.vue

@@ -104,6 +104,16 @@
           @keyup.enter.native="handleQuery"
         />
       </el-form-item> -->
+       <el-form-item label="所属小程序" prop="coursePlaySourceConfigId">
+         <el-select v-model="queryParams.coursePlaySourceConfigId" placeholder="请选择所属小程序" clearable size="small">
+           <el-option
+             v-for="dict in appMallOptions"
+             :key="dict.id"
+             :label="dict.name + '(' + dict.appid + ')'"
+             :value="dict.id"
+           />
+         </el-select>
+       </el-form-item>
        <el-form-item label="创建时间" prop="createTime">
           <el-date-picker v-model="createTime" size="small" style="width: 220px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" @change="change"></el-date-picker>
       </el-form-item>
@@ -157,6 +167,7 @@
         </template>
       </el-table-column>
 
+      <el-table-column label="小程序名称" align="center" prop="miniProgramName" width="120px" />
       <el-table-column label="状态" align="center" prop="status">
         <template slot-scope="scope">
           <dict-tag :options="statusOptions" :value="scope.row.status"/>
@@ -213,6 +224,7 @@ import { listStorePayment, getStorePayment, delStorePayment, addStorePayment, up
 import { getTask } from "@/api/common";
 import storePayDetails from '../../components/his/storePayDetails.vue';
 import { getCompanyList } from "@/api/company/company";
+import {list as getAppMallOptions} from '@/api/course/coursePlaySourceConfig';
 export default {
   name: "StorePayment",
   components: { storePayDetails },
@@ -251,6 +263,7 @@ export default {
       statusOptions: [],
       busineOptitons: [],
        actName:"10",
+      appMallOptions:[],
       // 查询参数
       queryParams: {
         pageNum: 1,
@@ -274,6 +287,7 @@ export default {
         storeId: null,
         businessCode:null,
         phone:null,
+        coursePlaySourceConfigId:null,
       },
       // 表单参数
       form: {},
@@ -299,6 +313,9 @@ export default {
     this.getDicts("sys_store_payment_share_status").then(response => {
       this.shareOptions = response.data;
     });
+    
+    // 获取小程序选项列表
+    this.getAppMallOptions();
   },
   methods: {
     handleClickX(tab, event) {
@@ -476,7 +493,13 @@ export default {
           },10000);
         }
         }).catch(() => {});
-    }
+    },
+    // 获取小程序选项列表
+    getAppMallOptions() {
+      getAppMallOptions({pageNum:1,pageSize:100,isMall:1}).then(response => {
+        this.appMallOptions = response.rows;
+      })
+    },
   }
 };
 </script>

+ 1 - 1
src/views/his/user/indexProject.vue

@@ -246,7 +246,7 @@
             type="text"
             icon="el-icon-delete"
             @click="handleDelete(scope.row)"
-            v-hasPermi="['store:user:remove']"
+            v-hasPermi="['his:userCompanyUser:remove']"
           >删除</el-button>
         </template>
       </el-table-column>

+ 10 - 0
src/views/hisStore/storeOrder/index.vue

@@ -296,6 +296,16 @@
               <span v-if="scope.row.payPrice!=null">{{scope.row.payPrice.toFixed(2)}}</span>
           </template>
       </el-table-column>
+      <el-table-column label="实付金额" align="center" prop="payMoney" >
+          <template slot-scope="scope">
+              <span v-if="scope.row.payPrice!=null">{{scope.row.payMoney.toFixed(2)}}</span>
+          </template>
+      </el-table-column>
+      <el-table-column label="物流代收金额" align="center" prop="payDelivery" >
+          <template slot-scope="scope">
+              <span v-if="scope.row.payPrice!=null">{{scope.row.payDelivery.toFixed(2)}}</span>
+          </template>
+      </el-table-column>
       <el-table-column label="下单时间" align="center" prop="createTime" />
       <!-- <el-table-column label="支付状态" align="center" prop="paid" /> -->
       <el-table-column label="支付时间" align="center" prop="payTime" width="180">

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

@@ -951,7 +951,8 @@ export default {
   data() {
     return {
       isMedicalMall: this.$store.state.user.medicalMallConfig.medicalMall,
-      isStores: this.$store.state.user.medicalMallConfig.stores,
+      // isStores: this.$store.state.user.medicalMallConfig.stores,
+      isStores: true,
       companyId: null,
       storeId: null,
       isAudit: null,
@@ -1681,7 +1682,7 @@ export default {
         return bulkCopy(productIds);
       }).then(() => {
         this.getList();
-        this.msgSuccess("删除成功");
+        this.msgSuccess("复制成功");
       }).catch(function() {});
     },
     /** 导出按钮操作 */

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

@@ -543,10 +543,15 @@
           <el-form-item v-if="form9.type=='wx'" label="微信Key" prop="wxMchKey">
             <el-input v-model="form9.wxMchKey" label="请输入微信Key"></el-input>
           </el-form-item>
-          <el-form-item v-if="form9.type=='wx'" label="微信商户V3密钥" prop="wxMchKey">
+          <el-form-item v-if="form9.type=='wx'" label="微信商户V3密钥" prop="wxApiV3Key">
             <el-input v-model="form9.wxApiV3Key" label="请输入商户V3密钥"></el-input>
           </el-form-item>
-
+          <el-form-item v-if="form9.type=='wx'" label="微信回调地址(scrm)" prop="notifyUrlScrm">
+            <el-input v-model="form9.notifyUrlScrm" label="请输入商城微信回调地址"></el-input>
+          </el-form-item>
+          <el-form-item v-if="form9.type=='wx'" label="p12证书路径" prop="keyPath">
+            <el-input v-model="form9.keyPath" label="请输入p12证书文件的绝对路径"></el-input>
+          </el-form-item>
 
           <el-form-item v-if="form9.type=='hf'" label="汇付产品号" prop="hfProductId">
             <el-input v-model="form9.hfProductId" label="汇付产品号"></el-input>
@@ -1448,7 +1453,13 @@
                inactive-color="#ff4949">
              </el-switch>
            </el-form-item>
-
+          <el-form-item label="是否开启企微二维码" prop="showQwCode">
+            <el-switch
+              v-model="form18.showQwCode"
+              active-color="#13ce66"
+              inactive-color="#ff4949">
+            </el-switch>
+          </el-form-item>
           <div class="line"></div>
           <div style="float:right;margin-right:20px">
             <el-button type="primary" @click="submitForm18">提交</el-button>

+ 10 - 1
src/views/system/user/index.vue

@@ -146,6 +146,14 @@
           <el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" />
           <el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible" :show-overflow-tooltip="true" />
           <el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" />
+          <el-table-column label="账户角色" align="center" key="roleName" v-if="columns[7].visible" :show-overflow-tooltip="true">
+            <template slot-scope="scope">
+              <span v-if="scope.row.roleName && scope.row.roleName.length > 0">
+                {{ Array.isArray(scope.row.roleName) ? scope.row.roleName.join('、') : scope.row.roleName }}
+              </span>
+              <span v-else>-</span>
+            </template>
+          </el-table-column>
           <el-table-column label="状态" align="center" key="status" v-if="columns[5].visible">
             <template slot-scope="scope">
               <el-switch
@@ -434,7 +442,8 @@ export default {
         { key: 3, label: `部门`, visible: true },
         { key: 4, label: `手机号码`, visible: true },
         { key: 5, label: `状态`, visible: true },
-        { key: 6, label: `创建时间`, visible: true }
+        { key: 6, label: `创建时间`, visible: true },
+        { key: 7, label: `账户角色`, visible: true }
       ],
       // 表单校验
       rules: {