浏览代码

Merge branch 'master' of http://8.136.199.33:3000/hbchen/hongze_fsms_web into techPool_641

hbchen 1 年之前
父节点
当前提交
407fedde61

+ 5 - 0
src/App.vue

@@ -38,4 +38,9 @@ provide('$moment',moment)
     width: 100%;
     table-layout: fixed!important;;
   }
+  #nprogress{
+    .bar{
+      background-color: $themeColor !important;;
+    }
+  }
 </style>

+ 13 - 2
src/api/crm.js

@@ -16,7 +16,7 @@ export function getPermissionList(data) {
       params:data
   })
 }
-// 获取销售列表(包括禁用的销售)
+// 获取销售列表(包括禁用的销售) -- 已替换为 getSellerTeamList()
  /**
   * @param {
   * } data 
@@ -40,7 +40,18 @@ export function getSellerListNoG() {
      method:'get'
  })
 }
-
+// 获取详细的销售列表(包含小组以及禁用的小组)
+ /**
+  * @param {
+ * } data 
+ * @returns 
+ */
+export function getSellerTeamList() {
+ return request({
+     url:'/crm/company_seller/team_list',
+     method:'get'
+ })
+}
 // 根据合同编号搜索合同列表
  /**
   * 

+ 63 - 1
src/api/financialStatistics.js

@@ -99,4 +99,66 @@ export function setServiceAmount(data) {
         method:'post',
         data
     })
-}
+}
+
+// 业务收入金额统计
+ /**
+ * 获取业务收入金额
+ * @param data.start_date - 开始时间
+ * @param data.end_date - 结束时间
+ * @param data.is_export - 是否是导出 0-否 1-是
+ * @param data.list_param - 统计类型: 0-月度; 1-季度; 2-半年度;3-年度;4-月度累计
+ * @param data.company_type - 客户类型 0全部 1新客户 2老客户
+ * @param data.seller_ids - 销售ids
+ * @returns 
+ */
+ export function getIncomeChartData(data) {
+    return request({
+        url:'/census/invoice_payment/income/list',
+        method:'get',
+        params:data,
+        responseType:data.is_export==1?'blob':'text',
+    })
+   }
+// 未开票统计
+ /**
+ * 未开票统计列表
+ * @param data.page_size - 每页数据量 - 必填
+ * @param data.current - 页码 - 必填
+ * @param data.keyword - 关键词-客户名称/销售
+ * @param data.seller_ids - 销售ID
+ * @param data.service_type - 套餐类型
+ * @param data.sort_param - 'start_date':开票日 、 'end_date':到款日
+ * @param data.sort_type - asc 正序,desc 倒叙
+ * @param data.is_export - 是否是导出:0-否;1-是
+ * @returns 
+ */
+export function getWaitInvoiceList(data) {
+    return request({
+        url:'/census/invoice_payment/not_invoice/list',
+        method:'get',
+        params:data,
+        responseType:data.is_export==1?'blob':'text',
+    })
+}
+// 开票未到款统计
+ /**
+ * 开票未到款统计列表
+ * @param data.page_size - 每页数据量 - 必填
+ * @param data.current - 页码 - 必填
+ * @param data.keyword - 关键词-客户名称/销售
+ * @param data.seller_ids - 销售ID
+ * @param data.service_type - 套餐类型
+ * @param data.sort_param - 'invoice_time':开票日
+ * @param data.sort_type - asc 正序,desc 倒叙
+ * @param data.is_export - 是否是导出:0-否;1-是
+ * @returns 
+ */
+ export function getWaitPaymentList(data) {
+    return request({
+        url:'/census/invoice_payment/not_payment/list',
+        method:'get',
+        params:data,
+        responseType:data.is_export==1?'blob':'text',
+    })
+}

+ 2 - 2
src/assets/svg-icons/financial/info.svg

@@ -1,5 +1,5 @@
-<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
-<path d="M9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5Z" fill="#C0C4CC"/>
+<svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
+<path d="M9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5Z"/>
 <path d="M9 12V9" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
 <path d="M9 6H9.0075" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
 </svg>

+ 58 - 0
src/components/echart/baseOptions.js

@@ -0,0 +1,58 @@
+export const baseOptions=()=>{
+  return {
+    title: {
+      text:'默认图表',
+      textStyle:{
+        fontSize:20,
+        fontWeight:500
+      },
+      left:'center'
+    },
+    legend:{
+      icon:'circle',
+      left:'center',
+      top:40,
+      textStyle:{
+        fontSize:14
+      },
+      itemStyle:{},
+      itemGap:34,
+      itemWidth:12
+    },
+    tooltip:{
+      textStyle:{
+        align:'left'
+      },
+      trigger:'axis'
+    },
+    grid:{
+      top:120,
+      bottom:60
+    },
+    color: ['#FF903E', '#FBE947'],
+    xAxis:{
+      type: 'category',
+      axisLabel: {
+        color: '#999', //更改坐标轴文字颜色
+        fontSize: 14, //更改坐标轴文字大小
+      }
+    },
+    yAxis: [{
+      name:'万元',
+      type: 'value',
+      nameGap:20,
+      splitNumber:10,
+      alignTicks:true,
+      nameTextStyle:{
+        align:'right',
+        color:'#999'
+      },
+      axisLabel:{
+        color:'#999',
+        formatter:(value)=>{
+          return Math.round(value*100)/1000000
+        }
+      }
+    }]
+  }
+}

+ 88 - 0
src/components/echart/index.vue

@@ -0,0 +1,88 @@
+<script setup>
+  import * as echarts from 'echarts/core';
+  // 引入柱状图图表,图表后缀都为 Chart
+  import { BarChart,LineChart } from 'echarts/charts';
+  // 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component
+  import {
+    TitleComponent,
+    TooltipComponent,
+    GridComponent,
+    DatasetComponent,
+    LegendComponent
+  } from 'echarts/components';
+  // 标签自动布局、全局过渡动画等特性
+  import { LabelLayout, UniversalTransition } from 'echarts/features';
+  // 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
+  import { SVGRenderer } from 'echarts/renderers';
+
+  // 注册必须的组件
+  echarts.use([
+    TitleComponent,
+    TooltipComponent,
+    GridComponent,
+    DatasetComponent,
+    LegendComponent,
+    BarChart,
+    LineChart,
+    LabelLayout,
+    UniversalTransition,
+    SVGRenderer
+  ]);
+
+  const chartProp=defineProps({
+    options:{
+      type:Object,
+      require:true
+    },
+    title:{
+      type:String,
+      default:''
+    }
+  })
+  // 侧边导航栏收缩/展开值
+  const isCollapse=inject('isCollapse')
+
+  watch(()=>isCollapse.value,(value)=>{
+    setTimeout(()=>{
+      resizeChart()
+    },300)
+  })
+
+  const barChartRef = ref(null)
+  let barChart = null
+
+  const resizeChart=()=>{
+    barChart.resize();
+  }
+
+  const chartDraw=(option)=>{
+    // nextTick(()=>{
+      barChart.clear()
+      barChart.setOption(option)
+    // })
+  }
+
+  watch(()=>chartProp.options,(newVal)=>{
+    // console.log(newVal,'newVal');
+    if(!newVal.series) return 
+    chartDraw(newVal)
+  },{deep:true})
+
+  onMounted(()=>{
+    barChart = echarts.init(barChartRef.value)
+    window.addEventListener('resize', resizeChart);
+  })
+
+  onUnmounted(()=>{
+    barChart?.dispose()
+    window.removeEventListener('resize', resizeChart);
+  })
+</script>
+
+<template>
+    <div ref="barChartRef" style="height: 100%;"></div>
+</template>
+  
+<style lang="scss" scoped>
+  
+</style>

+ 3 - 1
src/layout/index.vue

@@ -7,6 +7,8 @@
   import {changePsdFirst} from '@/api/systemMana'
 
   const isCollapse = ref(false)
+  provide('isCollapse',isCollapse)
+  
   if (document.body.clientWidth <= 1500) {
     isCollapse.value = true;
   }
@@ -79,7 +81,7 @@
             <router-view v-slot="{ Component }">
             <!-- 使用transition 每个vue文件必须要有一个根节点 和vue2一样 -->
               <transition name="fade" mode="out-in">
-                  <component :is="Component" :key="$route.name" />
+                  <component :is="Component" :key="$route.name" ref="routerComponent"/>
               </transition>
             </router-view>
         </div>

+ 2 - 0
src/styles/main.scss

@@ -85,6 +85,8 @@ div::-webkit-scrollbar-corner {
   border: 1px solid $themeColor;
   font-size: 16px;
   width: 130px;
+  cursor: pointer;
+  box-sizing: border-box;
 }
 // 主题按钮 - 大
 .main-button-large{

+ 32 - 6
src/utils/request.js

@@ -8,20 +8,42 @@ const request = axios.create({
 
 })
 
-let requestList=new Set()
+// 对于重复的post请求,只处理第一次请求,后续重复的请求在上一次返回之前都取消
+const postRequestList=new Set()
+
+
+// 需要储存每次请求对应的取消方法
+let lastGetRequestList=new Map()
+// 取消方法
+const removePreRequest=(Url,fun)=>{
+  console.log(lastGetRequestList);
+  if(lastGetRequestList.has(Url)){
+    // 取消上一次请求
+    lastGetRequestList.get(Url)(`${Url}---重复请求被中断`)
+    // 设置 新的取消方法
+    lastGetRequestList.set(Url,fun)
+  }
+}
 
 request.interceptors.request.use(
   config=>{
-    // console.log(config);
     config.headers['Authorization'] = localStorage.getItem('fsms_token') || ''
        // 不处理get请求
     if (config.method !== 'get') {
       // 利用axios cancelToken 先取消请求
       config.cancelToken = new axios.CancelToken(e => {
-        // console.log(e, config, 'CancelToken')
         // 在这里取消重复请求,上个请求未完成时,相同的请求不会再次执行
-        requestList.has(`${config.url}`) ? e(`${config.url}---重复请求被中断`) : requestList.add(`${config.url}`)
+        postRequestList.has(config.url) ? e(`${config.url}---重复请求被中断`) : postRequestList.add(config.url)
       })
+    }else if(config.params?.takeLastRequestResult){
+      // 对于get请求中的参数有 takeLastRequestResult 且值为真 进行特殊处理,若重名 请不要更改这个名字
+      config.cancelToken = new axios.CancelToken((c)=>{
+        lastGetRequestList.has(config.url) ? removePreRequest(config.url,c) : lastGetRequestList.set(config.url,c)
+      });
+      // 去除参数中的 takeLastRequestResult
+      if(config.params){
+        config.params.takeLastRequestResult=undefined
+      }
     }
     return config
   },
@@ -33,7 +55,8 @@ request.interceptors.request.use(
 
 request.interceptors.response.use(
   res=>{
-    requestList.delete(`${res.config.url}`)
+    postRequestList.delete(`${res.config.url}`)
+    lastGetRequestList.delete(`${res.config.url}`)
     if(res.request.responseType==='blob' || res.request.responseType==='Blob'){
        // 字节流
        if(res.status === 200){
@@ -64,10 +87,13 @@ request.interceptors.response.use(
     }
   },
   err=>{
-    requestList.clear()
     const {message} = err
     console.log(message,'--错误信息');
     if(!err.__CANCEL__){
+      // 清除
+      postRequestList.clear()
+      lastGetRequestList.clear()
+
       // 多次点击由CancelToken取消的请求不给错误提示
       ElMessage({
         message: message || '网络异常',

+ 20 - 116
src/views/dashboard/index.vue

@@ -1,136 +1,37 @@
 <script setup>
 
   import {getStatistic} from '@/api/dashboard'
-  import * as echarts from 'echarts/core';
-  // 引入柱状图图表,图表后缀都为 Chart
-  import { BarChart } from 'echarts/charts';
-  // 引入提示框,标题,直角坐标系,数据集,内置数据转换器组件,组件后缀都为 Component
-  import {
-    TitleComponent,
-    TooltipComponent,
-    GridComponent,
-    DatasetComponent,
-    LegendComponent
-  } from 'echarts/components';
-  // 标签自动布局、全局过渡动画等特性
-  import { LabelLayout, UniversalTransition } from 'echarts/features';
-  // 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
-  import { CanvasRenderer } from 'echarts/renderers';
-
+  import chart from '@/components/echart/index.vue'
   import {useRouter} from 'vue-router'
-
-  // 注册必须的组件
-  echarts.use([
-    TitleComponent,
-    TooltipComponent,
-    GridComponent,
-    DatasetComponent,
-    LegendComponent,
-    BarChart,
-    LabelLayout,
-    UniversalTransition,
-    CanvasRenderer
-  ]);
+  import {baseOptions} from '@/components/echart/baseOptions'
   
   const router = useRouter()
-
-  const barChartRef = ref(null)
-  let barChart = null
-
+  const basicOptions=baseOptions()
+  const chartOptions=ref()
+  
   const paymentNavigator=()=>{
     // 去往商品到款统计页面
     router.push('/financialStatistics/commodityPayment')
   }
 
-  const resizeChart=()=>{
-    barChart.resize();
-  }
-
   const getChartData=()=>{
     getStatistic().then(res=>{
-      nextTick(()=>{
-        chartDraw(res.data.ContractMoney || [],res.data.ArrivalMoney || [],res.data.Date || [])
-      })
-    })
-  }
-
-  const chartDraw=(invoiceData,placementData,dateData)=>{
-    // console.log(barChartRef.value);
-    barChart = echarts.init(barChartRef.value)
-    barChart.setOption({
-      title: {
-        text:'开票到款统计图',
-        textStyle:{
-          fontSize:20,
-          fontWeight:500
-        },
-        left:'center'
-      },
-      legend:{
-        icon:'circle',
-        left:'center',
-        top:40,
-        textStyle:{
-          fontSize:14
-        },
-        itemGap:34,
-        itemWidth:12
-      },
-      tooltip:{
-        textStyle:{
-          align:'left'
-        }
-      },
-      grid:{
-        top:120
-      },
-      color: ['#FF903E', '#FBE947'],
-      xAxis:{
-        type: 'category',
-        data:dateData,
-        axisLabel: {
-          color: '#999', //更改坐标轴文字颜色
-          fontSize: 14, //更改坐标轴文字大小
-        },
-      },
-      yAxis: {
-        name:'万元',
-        type: 'value',
-        nameGap:20,
-        splitNumber:10,
-        nameTextStyle:{
-          align:'right',
-          color:'#999'
-        },
-        axisLabel:{
-          color:'#999',
-          formatter:(value)=>{
-            return Math.round(value*10)/100000
-          }
-        }
-      },
-      series:[{
-        data: invoiceData,
+      let invoiceData=res.data.Date.map((item,index)=> [item,res.data.ContractMoney[index]])
+      let paymentData=res.data.Date.map((item,index)=> [item,res.data.ArrivalMoney[index]])
+      basicOptions.title.text = '开票到款统计图'
+      basicOptions.series=[
+        {data: invoiceData,
         type: 'bar',
-        name:'开票金额'
-      },
-      {
-        data: placementData,
+        name:'开票金额'},
+        {data: paymentData,
         type: 'bar',
-        name:'到款金额'
-      }]
+        name:'到款金额'}
+      ]
+      chartOptions.value=basicOptions
     })
-    window.addEventListener('resize', resizeChart);
   }
 
-  onUnmounted(()=>{
-    barChart?.dispose()
-    window.removeEventListener('resize', resizeChart);
-  })
-
-  onMounted(()=>{
-    getChartData()
-  })
+  getChartData()
 
 
 </script>
@@ -145,7 +46,10 @@
           </el-icon>
         </span>
       </div>
-      <div ref="barChartRef" class="bar-chart"></div>
+
+      <div class="bar-chart">
+        <chart :options="chartOptions"/>
+      </div>
     </div>
 </template>
   

+ 4 - 11
src/views/financialManagement/contractProgress-component/Compliance.vue

@@ -64,7 +64,6 @@
       contract_code:'',
       company_name:'',
       currency_unit:'CNY',
-      new_company:0,
       seller_ids:'',
       seller_id:0,
       contract_status:'',
@@ -179,7 +178,6 @@
     compliance.form.contract_code='',
     compliance.form.company_name='',
     compliance.form.currency_unit='CNY',
-    compliance.form.new_company=0,
     compliance.form.seller_ids='',
     compliance.form.seller_id='',
     compliance.form.contract_status='',
@@ -251,14 +249,8 @@
     if(compliance.form.has_payment==0){
       compliance.form.has_invoice=1
     }
+    // 新签 -- 新客户 其余的算老客户
     compliance.form.contract_type = value[1]
-    if(compliance.form.contract_type==1){
-      // 新签 -- 新客户
-      compliance.form.new_company = 1
-    }else{
-      // 续约、补充 -- 老客户
-      compliance.form.new_company = 0
-    }
     if(compliance.form.contract_type!=4){
       // 新签、续约
       compliance.form.relate_contract_main_code=''
@@ -575,6 +567,7 @@
             // 预登记过来的
             params={...params,contract_register_id:props.supplementaryInfo.id}
           }
+          // console.log(params);
           // 新增
           contractRegisterCheck({company_name:compliance.form.company_name,
             start_date:compliance.form.start_date,end_date:compliance.form.end_date,seller_ids:compliance.form.seller_ids}).then(res=>{
@@ -750,10 +743,11 @@
     compliance.form.supplement =1
     compliance.form.company_name = props.supplementaryInfo.company_name
     compliance.form.currency_unit = props.supplementaryInfo.currency_unit
-    compliance.form.new_company = parseInt(props.supplementaryInfo.new_company)
     compliance.form.start_date = props.supplementaryInfo.start_date
     compliance.form.end_date = props.supplementaryInfo.end_date
     compliance.contractValidityDate = [compliance.form.start_date,compliance.form.end_date]
+    compliance.contractTypeCheck=[props.supplementaryInfo.has_payment,props.supplementaryInfo.contract_type]
+    contractTypeChange(compliance.contractTypeCheck)
     serviceDataHandle(props.supplementaryInfo.services)
   }
 
@@ -764,7 +758,6 @@
     compliance.form.contract_code=props.detailInfo.contract_code
     compliance.form.company_name=props.detailInfo.company_name
     compliance.form.currency_unit=props.detailInfo.currency_unit
-    compliance.form.new_company=props.detailInfo.new_company
     compliance.form.seller_ids=props.detailInfo.seller_ids
     compliance.form.seller_id=props.detailInfo.seller_id || props.detailInfo.rai_seller_id
     compliance.form.contract_status=props.detailInfo.contract_status

+ 59 - 9
src/views/financialManagement/contractProgress-component/InvoiceAndPayment.vue

@@ -129,11 +129,59 @@
 // ------------------------------------------方法
   // 切换套餐类型
   const productIdChange=(value,row)=>{
-    // 清空销售
-    if(props.type=='开票'){
-      row.seller_id=''
-      row.seller_name=''
+    // value 1-FICC 2-权益
+    let sellerId,sellerName='';
+    // 已经找到对应记录的
+    let hasFindCount=0
+    // 存在的记录条数 - 注意需要把自己这项排除掉
+    let allCount=amountForm.amountData.filter(item => item.service_product_id==value && item!=row).length
+    // 可编辑情况下
+    for (let i = 0; i < amountForm.submittedAmountData.length; i++) {
+      const element = amountForm.submittedAmountData[i];
+      if(element.service_product_id!=value) continue
+      // 符合条件,继续找
+      if(amountForm.amountData.some(it => it.service_product_id == value) &&
+        hasFindCount<allCount){
+        hasFindCount++
+        continue
+      } 
+      // 不符合条件,那需要添加的数据就 对应这一条
+      sellerId=element.seller_id || ''
+      sellerName=element.seller_name || ''
+      // 找到第一条就break掉
+      break
+    }
+    // 判断销售是否离职
+    if(sellerId){
+      if(value==1){
+        // FICC销售和权益销售都要判断,并且页面呈现为级联选择器
+        if([...props.sellerData.ficc_list,...props.sellerData.rai_list]
+        .findIndex(seller => seller.seller_id==sellerId)==-1){
+          props.sellerData.all_list.push({
+            seller_id:sellerId,
+            seller_name:sellerName+'-已离职',
+            disabled:true,
+            child:null
+          })
+          sellerName=sellerName+'-已离职'
+        }
+      }else{
+        if(props.sellerData.rai_list.findIndex(seller => seller.seller_id==sellerId)==-1){
+          sellerId = sellerName+'-已离职'
+          sellerName=sellerName+'-已离职'
+        }
+      }
     }
+    row=Object.assign(row,{
+        service_product_id:value,              
+        seller_id:sellerId,
+        seller_name:sellerName,
+        // 到款有对应的销售需要禁用
+        hasRelativeSeller:!!sellerId
+      }
+    )
+    // console.log(row,hasFindCount,allCount,'allCountallCountallCount');
+
     if(!row.origin_amount) return
       // 开票
     if(value==1){
@@ -428,7 +476,7 @@
 
     // if(amoutList.length>0){
     amountForm.amountData=[]
-    amoutList.map(item=>{
+    amoutList.map((item,index)=>{
       if(item.service_product_id==1){
         // FICC
         IandP.moneyData.haveMoneyFICC+=item.origin_amount
@@ -446,6 +494,8 @@
         remark:item.remark,
         seller_id:item.seller_id,
         seller_name:item.seller_name,
+        // 到款有对应的销售需要禁用
+        hasRelativeSeller:!!amountForm.submittedAmountData[index]?.seller_id,
         amountDomType:'text',
         remarkDomType:'text',
         isEdit:false
@@ -556,7 +606,7 @@
                   <span style="color: var(--dangerColor);">*</span>套餐类型
                 </template>
                 <template #default="{row,$index}">
-                  <el-form-item :prop="`amountData.${$index}.service_product_id`" :show-message="false" v-show="!row.invoice_id || row.isEdit"
+                  <el-form-item :prop="`amountData.${$index}.service_product_id`" :show-message="false" v-show="!row.invoice_id"
                   :rules="{required:true,message:()=>{ ElMessage.error('套餐类型不能为空')},trigger:'change'}">
                     <el-select v-model="row.service_product_id" style="width: 124px;" @change="value=> productIdChange(value,row)"
                     placeholder="请选择套餐" filterable>
@@ -564,7 +614,7 @@
                       <el-option label="权益套餐" :value="2"></el-option>
                     </el-select>
                   </el-form-item>
-                  <span v-show="row.invoice_id && !row.isEdit">{{ row.service_product_id?row.service_product_id==1?'FICC套餐':'权益套餐' : '--' }}</span>
+                  <span v-show="row.invoice_id">{{ row.service_product_id?row.service_product_id==1?'FICC套餐':'权益套餐' : '--' }}</span>
                 </template>
               </el-table-column>
               <el-table-column :label="type+'金额'" width="160" show-overflow-tooltip  align="center" prop="origin_amount">
@@ -659,8 +709,8 @@
                 <template #default="{row,$index}">
                   <span class="table-operation-button" v-show="$index==amountForm.amountData.length-1" 
                   @click="addRow(row,$index)" style="margin-right: 10px;">添加</span>
-                  <!-- <span class="table-operation-button" style="margin-right: 6px;" v-show="row.invoice_id" 
-                  @click="editRow(row)">{{ row.isEdit?'确定':'编辑' }}</span> -->
+                  <span class="table-operation-button" style="margin-right: 6px;" v-show="row.invoice_id" 
+                  @click="editRow(row)">{{ row.isEdit?'确定':'编辑' }}</span>
                   <span class="table-operation-button" style="color: var(--dangerColor);" 
                   @click="deleteRow(row,$index)">删除</span>
                 </template>

+ 2 - 2
src/views/financialManagement/contractProgress.vue

@@ -261,7 +261,6 @@
         contract_code:res.data.contract_code,
         company_name:res.data.company_name,
         currency_unit:res.data.currency_unit,
-        new_company:res.data.new_company,
         seller_ids:res.data.seller_ids,
         seller_id:res.data.seller_id,
         seller_name:res.data.seller_name,
@@ -318,8 +317,9 @@
         id:supplementary_item.id,
         supplement:1,
         company_name:res.data.company_name,
+        has_payment:res.data.has_payment,
+        contract_type:res.data.contract_type,
         currency_unit:res.data.list[0]?.currency_unit,
-        new_company:parseInt(res.data.new_company),
         start_date : res.data.start_date,
         end_date:res.data.end_date,
         services:res.data.services

+ 6 - 18
src/views/financialManagement/invoice/invoiceList.vue

@@ -1,5 +1,6 @@
 <script setup>
-import {getSellerList} from '@/api/crm'
+import {getSellerTeamList} from '@/api/crm'
+import currencyAmountBox from '@/views/financialStatistics/components/currencyAmountBox.vue';
 import getCom from '../composition/IandPList'
 import '../style/iandPList.scss'
 
@@ -9,7 +10,7 @@ const data = invoice.data
 const sellerArray=ref([])
 
 const getSellerListFun=()=>{
-  getSellerList().then(res=>{
+  getSellerTeamList().then(res=>{
     sellerArray.value = res.data?.all_list || []
     // console.log(res);
   })
@@ -55,22 +56,9 @@ invoice.placementList()
       </div>
       <div class="iandP-table-container">
         <div class="iandP-table-top">
-          <div class="iandP-top-amout">
-            <div class="iandP-amout-box">
-              <div class="iandP-amout-box-text">
-                <span>已开票合计金额(换算后)</span>
-                <span>{{ data.amountTotal }}(CNY)</span>
-              </div>
-              <svg-Icon name="svgIcon-financial-calculation" size="40" style="min-width: 40px;" />
-            </div>
-            <div class="iandP-amout-box" v-for="item in data.countryAmountList" :key="item.code">
-              <div class="iandP-amout-box-text">
-                <span>{{ item.name }}({{ item.code }})</span>
-                <span>{{ item.amount }}</span>
-              </div>
-              <img :src="item.flag_img" style="height: 40px;width: 40px;" />
-            </div>
-          </div>
+          <currencyAmountBox :currnecyData="{currencyList:data.countryAmountList,currencyTotal:data.amountTotal}">
+            已开票合计金额(换算后)
+          </currencyAmountBox>
           <el-button class="element-common-button" style="margin-bottom: 10px;" size="large" @click="invoice.placementExport">导出</el-button>
         </div>
         <!-- 表格 -->

+ 6 - 19
src/views/financialManagement/placement/placementList.vue

@@ -1,5 +1,6 @@
 <script setup>
-import {getSellerList} from '@/api/crm'
+import {getSellerTeamList} from '@/api/crm'
+import currencyAmountBox from '@/views/financialStatistics/components/currencyAmountBox.vue';
 import getCom from '../composition/IandPList'
 import '../style/iandPList.scss'
 
@@ -11,7 +12,7 @@ const sellerArray=ref([])
 // ---------------method
 
 const getSellerListFun=()=>{
-  getSellerList().then(res=>{
+  getSellerTeamList().then(res=>{
     sellerArray.value = res.data?.all_list || []
     // console.log(res);
   })
@@ -57,23 +58,9 @@ placement.placementList()
       </div>
       <div class="iandP-table-container">
         <div class="iandP-table-top">
-          <div class="iandP-top-amout">
-            <div class="iandP-amout-box">
-              <div class="iandP-amout-box-text">
-                <span>已到款合计金额(换算后)</span>
-                <span>{{ data.amountTotal }}(CNY)</span>
-              </div>
-              <svg-Icon name="svgIcon-financial-calculation" style="min-width: 40px;"
-              size="40" />
-            </div>
-            <div class="iandP-amout-box" v-for="item in data.countryAmountList" :key="item.code">
-              <div class="iandP-amout-box-text">
-                <span>{{ item.name }}({{ item.code }})</span>
-                <span>{{ item.amount }}</span>
-              </div>
-              <img :src="item.flag_img" style="height: 40px;width: 40px;" />
-            </div>
-          </div>
+          <currencyAmountBox :currnecyData="{currencyList:data.countryAmountList,currencyTotal:data.amountTotal}">
+            已到款合计金额(换算后)
+          </currencyAmountBox>
           <el-button class="element-common-button" style="margin-bottom: 10px;" size="large" @click="placement.placementExport">导出</el-button>
         </div>
         <!-- 表格 -->

+ 1 - 1
src/views/financialManagement/placementPre.vue

@@ -1,5 +1,5 @@
 <!-- 1、到款预登记,之后的版本改为预登记 - registrationPre.vue
-      2、此文件仅作备份,保留至2023-4-7 -->
+      2、此文件仅作备份-->
 <script setup>
 import { Search } from '@element-plus/icons-vue'
 import {useRouter} from 'vue-router'

+ 57 - 3
src/views/financialManagement/registrationPre.vue

@@ -6,9 +6,12 @@ import {getSellerList,getSellerListNoG} from '@/api/crm'
 import {getCurrencyList} from '@/api/common'
 import {getServiceList,getPreRegistrationList,preRegistrationAdd,preRegistrationCheck,
   preRegistrationDetail,preRegistrationEdit,preRegistrationDelete,preRegistrationSave} from '@/api/financialMana'
+import financialCommon from './composition/common'
 import serviceCascader from './composition/serivceCascader.js'
 // 套餐的composition
 const serviceComposition = serviceCascader()
+// 合同类型数组
+const contractTypeArray=financialCommon().contractTypeArray
 
 const router = useRouter()
 const store = useStore()
@@ -23,6 +26,7 @@ const store = useStore()
     tableData:[],
     total:0,
   })
+
   // -----------------弹窗
   const registrationPreFormRef=ref(null)
 
@@ -37,6 +41,8 @@ const store = useStore()
       start_date:'',
       end_date:'',
       services:[],
+      has_payment:'',
+      contract_type:'',
       IorPInfo:[
         {
           service_product_id:'',
@@ -57,6 +63,7 @@ const store = useStore()
     selectServices:[],
     validityDate:[]
   })
+
   // 开票/到款预登记删除的id
   let hasDeleteContractInvoiceIds=[]
   let hasDeletePreRegisterIds=[]
@@ -73,6 +80,18 @@ const store = useStore()
     }
   })
 
+  // 合同类型选中
+  const contractTypeCheck=ref([])
+  // 合同类型改变
+  const contractTypeChange=(value)=>{
+    if(!value){
+      dialog.registrationPreForm.has_payment = dialog.registrationPreForm.contract_type = ''
+    }
+    dialog.registrationPreForm.has_payment = value[0]
+    dialog.registrationPreForm.contract_type = value[1]
+  }
+  
+
 // -----------------------------------------套餐部分 - 开始
 // 套餐列表
 const servicesList=ref([])
@@ -285,6 +304,9 @@ const editRegistrationPre=(row)=>{
     dialog.registrationPreForm.contract_register_id = res.data.contract_register_id
     dialog.registrationPreForm.company_name = res.data.company_name
     dialog.registrationPreForm.invoice_type = row.invoice_type
+    dialog.registrationPreForm.has_payment = res.data.has_payment
+    dialog.registrationPreForm.contract_type = res.data.contract_type
+    contractTypeCheck.value=[res.data.has_payment,res.data.contract_type]
     // 排序 将编辑入口对应的记录提到第一位
     dialog.registrationPreForm.IorPInfo=res.data.list.sort((a,b)=>a.pre_register_id == row.pre_register_id?-1:1)
     dialog.currentEditPreId = row.pre_register_id
@@ -311,6 +333,10 @@ const dialogClosed=()=>{
   hasDeleteContractInvoiceIds=[]
   hasDeletePreRegisterIds=[]
   dialog.registrationPreForm.company_name=''
+  dialog.registrationPreForm.has_payment=''
+  dialog.registrationPreForm.contract_type=''
+  contractTypeCheck.value=[]
+  dialog.registrationPreForm.company_name=''
   dialog.registrationPreForm.contract_register_id=''
   dialog.registrationPreForm.services=[]
   dialog.registrationPreForm.IorPInfo=[
@@ -347,6 +373,8 @@ const submitForm=()=>{
         register_type:dialog.registrationType=='开票'?3:4,
         start_date:dialog.registrationPreForm.start_date,
         end_date:dialog.registrationPreForm.end_date,
+        has_payment:dialog.registrationPreForm.has_payment,
+        contract_type:dialog.registrationPreForm.contract_type,
         list:dialog.registrationPreForm.IorPInfo,
         services:dialog.hasServiceChange?serviceData:dialog.registrationPreForm.services,
         del_invoice_ids:hasDeleteContractInvoiceIds,
@@ -414,6 +442,8 @@ const preDialog=reactive({
     service_product_id:'',
     start_date:'',
     end_date:'',
+    has_payment:'',
+    contract_type:'',
     services:[],
     amount:'',
     currency_unit:'CNY',
@@ -425,6 +455,8 @@ const preDialog=reactive({
   validityDate:[],
   selectService:[],
   rules:{
+    company_name:{required:true,message:'客户名称不能为空',trigger:'blur'},
+    contract_type:{required:true,message:'合同类型不能为空',trigger:'change'},
     end_date:{required:true,message:"约定有效期不能为空",trigger:'change'},
     services:{required:true,message:'套餐不能为空',trigger:'change'},
     amount:[{required:true,message:'金额不能为空',trigger:'blur'},
@@ -442,6 +474,8 @@ const preDialog=reactive({
     register_date:{required:true,message:'开票日不能为空',trigger:'change'}
   }
 })
+const contractTypeCheckPre=ref([])
+
 const preFormRef=ref(null)
 const selectServicesPreRef=ref(null)
 watch(()=>preDialog.validityDate,(newVal)=>{
@@ -461,6 +495,9 @@ const preIorP=(row)=>{
     if(!res.data) return
     preDialog.preForm.contract_register_id = res.data.contract_register_id
     preDialog.preForm.company_name = res.data.company_name
+    preDialog.preForm.has_payment = res.data.has_payment
+    preDialog.preForm.contract_type = res.data.contract_type
+    contractTypeCheckPre.value=[res.data.has_payment,res.data.contract_type]
     preDialog.preForm.invoice_type = row.invoice_type==3?4:3
     preDialog.preForm.service_product_id=row.service_product_id==0?'':row.service_product_id
     preDialog.preForm.pre_register_id = row.pre_register_id || 0
@@ -501,6 +538,8 @@ const submitPreForm=()=>{
         register_type:preDialog.title=='预到款'?4:3,
         start_date:preDialog.preForm.start_date,
         end_date:preDialog.preForm.end_date,
+        has_payment:preDialog.preForm.has_payment,
+        contract_type:preDialog.preForm.contract_type,
         list:[{
           contract_invoice_id:preDialog.preForm.contract_invoice_id||0,
           amount:preDialog.preForm.amount,
@@ -527,6 +566,8 @@ const preDialogClosed=()=>{
   preDialog.preForm={
     service_product_id:'',
     start_date:'',
+    has_payment:'',
+    contract_type:'',
     end_date:'',
     services:[],
     amount:'',
@@ -535,6 +576,7 @@ const preDialogClosed=()=>{
     register_date:''
   },
   preDialog.validityDate=[]
+  contractTypeCheckPre.value=[]
   preDialog.selectServices=[]
   serviceComposition.resetDisable(servicesList.value)
   setTimeout(()=>{
@@ -658,6 +700,7 @@ placementPreList()
             {{row.start_date&&row.start_date!='0001-01-01'?(row.start_date+' 至 '+row.end_date):''}}
           </template>
         </el-table-column>
+        <el-table-column label="合同类型" align="center" width="90" prop="contract_type_string"></el-table-column>
         <el-table-column label="套餐" prop="services" show-overflow-tooltip></el-table-column>
         <el-table-column label="开票日" prop="invoice_time" width="110"></el-table-column>
         <el-table-column label="开票金额" prop="origin_amount" width="120"></el-table-column>
@@ -750,12 +793,18 @@ placementPreList()
             :clearable="false">
             </el-date-picker>
         </el-form-item>
-        <el-form-item label="套餐" prop="services" label-width="90" style="margin-right: 20px;"
+        <el-form-item label="合同类型" prop="contract_type" label-width="90" style="margin-right: 30px;"
+          :rules="{required:true,message:'合同类型不能为空',trigger:'change'}">
+          <el-cascader :options="contractTypeArray" placeholder="请选择合同类型" style="min-width: 320px;"
+            v-model="contractTypeCheck" :clearable="false" key="contractType" @change="contractTypeChange">
+          </el-cascader>
+        </el-form-item>
+        <el-form-item label="套餐" prop="services" label-width="102" style="margin-right: 20px;"
         :rules="{required:true,message:'套餐不能为空',trigger:'change'}">
           <el-cascader filterable :options="servicesList" placeholder="请选择套餐" @change="(value)=>servicesChange(value,1)"
             :show-all-levels="true" v-model="dialog.selectServices" :clearable="false" ref="selectServicesRef"
             :props="{multiple:true,label:'title',value:'service_template_id',emitPath:false}" collapse-tags collapse-tags-tooltip
-            key="seriveces" style="min-width: 775px;z-index: 100;">
+            key="seriveces" style="min-width: 320px;z-index: 100;">
           </el-cascader>
         </el-form-item>
         <el-scrollbar max-height="470px" noresize style="margin: 0 -10px;padding: 0 10px;" >
@@ -854,6 +903,11 @@ placementPreList()
             :clearable="false">
             </el-date-picker>
         </el-form-item>
+        <el-form-item label="合同类型" prop="contract_type" :rules="{required:true,message:'合同类型不能为空',trigger:'change'}">
+          <el-cascader :options="contractTypeArray" placeholder="请选择合同类型" style="min-width: 286px;"
+            v-model="contractTypeCheckPre" :clearable="false" key="contractType" disabled>
+          </el-cascader>
+        </el-form-item>
         <el-form-item label="套餐" prop="services">
           <el-cascader filterable :options="servicesList" placeholder="请选择套餐" 
           @change="(value)=>servicesChange(value,2)" disabled
@@ -866,7 +920,7 @@ placementPreList()
         :rules="{required:true,message:'套餐类型不能为空',trigger:'change'}">
           <el-select v-model="preDialog.preForm.service_product_id"
           style="width: 286px;" @change="productIdChange(preDialog.preForm)"
-          placeholder="请选择套餐">
+          placeholder="请选择套餐" :disabled="preDialog.title=='预到款'">
             <el-option label="FICC套餐" :value="1"></el-option>
             <el-option label="权益套餐" :value="2"></el-option>
           </el-select>

+ 0 - 33
src/views/financialManagement/style/iandPList.scss

@@ -34,39 +34,6 @@
       align-items: flex-end;
       justify-content: space-between;
       margin-bottom: 20px;
-      .iandP-top-amout{
-        display: flex;
-        flex-wrap: wrap;
-        .iandP-amout-box{
-          display: flex;
-          justify-content: space-between;
-          height: 88px;
-          width: 274px;
-          background: #FFFFFF;
-          border: 1px solid #DCDFE6;
-          box-shadow: 0px 4px 12px rgba(153, 153, 153, 0.08);
-          border-radius: 8px;
-          padding: 14px 20px 20px;
-          box-sizing: border-box;
-          margin-right: 30px;
-          margin-bottom: 10px;
-          .iandP-amout-box-text{
-            display: flex;
-            flex-direction: column;
-            justify-content: space-between;
-            span{
-              font-size: 18px;
-              font-weight: 700;
-              color: $mainTextColor;
-              &:first-child{
-                font-size: 14px;
-                font-weight: 400;
-                color: $secondaryTextColor;
-              }
-            }
-          }
-        }
-      }
     }
   }
 }

+ 212 - 0
src/views/financialStatistics/businessIncome.vue

@@ -0,0 +1,212 @@
+<script setup>
+  import {downloadByFlow} from '@/utils/common-methods'
+  import {getSellerTeamList} from '@/api/crm'
+  import {getIncomeChartData} from '@/api/financialStatistics'
+  import chart from '@/components/echart/index.vue'
+  import {baseOptions} from '@/components/echart/baseOptions'
+
+  const basicOptions=baseOptions()
+
+  const dimensionArray=[{label:'月度',tag:0},{label:'季度',tag:1},{label:'半年度',tag:2},{label:'年度',tag:3},{label:'月度累计',tag:4}]
+  const customerTypeArray=[{label:'全部',value:0},{label:'新客户',value:1},{label:'老客户',value:2}]
+  const sellerArray=ref(null)
+
+  const searchParams=reactive({
+    list_param:0,
+    company_type:0,
+    start_date:'',
+    end_date:'',
+    seller_ids:'',
+    is_export:0,
+    // 不是后端所需要的值,在axios中用到的值,具体请看@/utils/request.js文件
+    takeLastRequestResult:true
+  })
+  // 加载状态
+  const loading=reactive({
+    list:true,
+    export:false
+  })
+  const chartOptions=ref(basicOptions)
+  
+  const invoiceTime=ref(null)
+  watch(invoiceTime,(value)=>{
+    if(!value){
+      searchParams.start_date=searchParams.end_date = ''
+    }else{
+      searchParams.start_date = value[0]
+      searchParams.end_date=value[1]
+    }
+    getList()
+  })
+
+  const sellersCheckList=ref(null)
+  watch(sellersCheckList,(value)=>{
+    if(!value){
+      searchParams.seller_ids = ''
+    }else{
+      searchParams.seller_ids = value.join(',')
+    }
+    getList()
+  })
+
+  const getSellerData=()=>{
+    getSellerTeamList().then(res=>{
+      sellerArray.value = res.data?.all_list || []
+    })
+  }
+
+  const initOptions=()=>{
+    chartOptions.value.title.text = "业务收入金额统计图"
+    chartOptions.value.title.textStyle.color='#333333'
+    chartOptions.value.color=['#FF903E', '#409EFF']
+    // x轴配置
+    chartOptions.value.xAxis.axisLabel.align='center' 
+    chartOptions.value.xAxis.axisLabel.rotate=45
+    chartOptions.value.xAxis.axisLabel.margin=27
+    // Y轴配置
+    chartOptions.value.yAxis[0].splitLine={
+      lineStyle:{
+        type:'dashed'
+      }
+    }
+    chartOptions.value.yAxis[0].splitNumber=8
+    chartOptions.value.yAxis[1]={
+      alignTicks:true,
+      axisLabel:{
+        color:'#999',
+        formatter:(value)=>{
+          // 防止失真
+          return Math.round(value*10000)/10000
+        }
+      },
+      splitLine:{
+        lineStyle:{
+          type:'dashed'
+        }
+      },
+      splitNumber:8
+    }
+      
+    // 数据配置
+    chartOptions.value.series=[
+      {
+        data: [],
+        type: 'bar',
+        name:'业务收入金额'
+      },
+      {
+        data: [],
+        type: 'line',
+        lineStyle:{
+          width:3
+        },
+        yAxisIndex:1,
+        name:'同比值',
+        connectNulls:true,
+        symbol:'circle',
+        symbolSize:2
+      }
+    ]
+  }
+  const getList=()=>{
+    loading.list=true
+    getIncomeChartData(searchParams).then(res=>{
+      // console.log(res);
+      let dates = res.data.Date || []
+      chartOptions.value.series[0].data=dates.map((item,index)=> [item,res.data.TotalMoney[index]])
+      chartOptions.value.series[1].data=dates.map((item,index)=> [item,res.data.Yoy[index]])
+      loading.list=false
+    }).catch(err=>{
+      if(!err.__CANCEL__){
+        // 不是因为取消的错误才设置为false
+        loading.list=false
+      }
+    })
+  }
+
+  const exportData=()=>{
+    loading.export=true
+    getIncomeChartData({...searchParams,is_export:1}).then(res=>{
+      downloadByFlow(res,'xlxs','业务收入金额统计')
+    }).finally(()=>{
+      loading.export=false
+    })
+  }
+
+  initOptions()
+  getSellerData()
+  getList()
+</script>
+
+<template>
+    <div class="business-income-container" id="business-income-container">
+      <div class="business-income-top">
+        <div class="business-income-search-zone">
+          <el-radio-group v-model="searchParams.list_param" size="large" @change="getList"
+          style="margin: 0 30px 8px 0;">
+            <el-radio-button v-for="item in dimensionArray" :key="item.tag" class="dimension-radio"
+            :label="item.tag" >{{ item.label }}</el-radio-button>
+          </el-radio-group>
+          <el-radio-group v-model="searchParams.company_type" size="large" @change="getList"
+          style="margin: 0 30px 8px 0;">
+            <el-radio-button v-for="item in customerTypeArray" :key="item.value" class="dimension-radio"
+            :label="item.value" >{{ item.label }}</el-radio-button>
+          </el-radio-group>
+          <el-cascader :options="sellerArray" v-model="sellersCheckList" clearable placeholder="请选择销售"
+          collapse-tags :show-all-levels="false" collapse-tags-tooltip key="seller" filterable 
+          style="max-width: 238px;margin:0 30px 8px 0;"
+          :props="{multiple:true,label:'seller_name',value:'seller_id',children:'child',emitPath:false}" ></el-cascader>
+          <el-date-picker v-model="invoiceTime" type="monthrange"
+          start-placeholder="开始日期" end-placeholder="结束日期" style="max-width: 238px;margin:0 30px 8px 0;"
+          value-format="YYYY-MM"></el-date-picker>
+        </div>
+        <el-button @click="exportData" type="primary" size="large" style="width: 118px;" :loading="loading.export">导出数据</el-button>
+      </div>
+      <div class="business-income-chart" v-loading="loading.list" element-loading-text="图表加载中……">
+        <chart :options="chartOptions" style="width: 75%;height: 80%;"/>
+      </div>
+    </div>
+</template>
+  
+<style lang="scss" scoped>
+  .business-income-container{
+    min-height: calc(100vh - 120px);
+    box-sizing: border-box;
+    .business-income-top{
+      display: flex;
+      justify-content: space-between;
+      margin-bottom: 20px;
+      .business-income-search-zone{
+        display: flex;
+        flex-wrap: wrap;
+      }
+    }
+    .business-income-chart{
+      border: 1px solid #DCDFE6;
+      background-color: white;
+      height: calc(100vh - 190px);
+      padding: 20px 30px;
+      box-sizing: border-box;
+      display: flex;
+      justify-content: center;
+      align-items: center;
+    }
+
+  }
+</style>
+<style lang="scss">
+  #business-income-container{
+    .dimension-radio{
+      span{
+        display: inline-block;
+        color: $hitTextColorTwo;
+        padding: 12px 12px;
+      }
+    }
+    .is-active{
+      span{
+        color:white
+      }
+    }
+  }
+</style>

+ 18 - 28
src/views/financialStatistics/commodityPayment.vue

@@ -2,7 +2,7 @@
 import { Search } from '@element-plus/icons-vue'
 // import dropdownText from '@/components/dropdown-text/index.vue'  
 import {getInvoicePaymentList,updatePayType,setServiceAmount} from '@/api/financialStatistics'
-import {getSellerGroupList,getSellerList} from '@/api/crm'
+import {getSellerGroupList,getSellerTeamList} from '@/api/crm'
 import {getSimpleServiceList} from '@/api/financialMana'
 import {downloadByFlow} from '@/utils/common-methods'
 import elementResizeDetectorMaker from 'element-resize-detector';
@@ -26,7 +26,7 @@ const moment = inject('$moment')
     start_date:moment().startOf('year').format('YYYY-MM-DD') || '',
     end_date:moment(new Date()).format('YYYY-MM-DD') || '',
     // 1-开票日期 2-到款日期 3-开票日期&到款日期
-    time_type:1,
+    time_type:'',
     // 1-已开票
     has_invoice:'',
     // 1-已到款
@@ -137,8 +137,8 @@ const moment = inject('$moment')
     commodityPList()
   }
 
-  const dataExport=(value)=>{
-    getInvoicePaymentList({...searchParams,is_export:1,list_param:value}).then(res=>{
+  const dataExport=()=>{
+    getInvoicePaymentList({...searchParams,is_export:1,list_param:0}).then(res=>{
       downloadByFlow(res,'xlsx','商品到款统计表')
     })
   }
@@ -168,15 +168,14 @@ const moment = inject('$moment')
   // --------------------------销售选择
 
   const sellerArray=ref([])
-  // 销售类型
-  const sellerTypeArray=ref(['','FICC销售','权益销售'])
+
   const sellerChange=(value)=>{
     searchParams.seller_ids = value.join(',')
     searchCommodityP()
   }
   // 获取销售列表
   const getSellerListFun=()=>{
-    getSellerList().then(res=>{
+    getSellerTeamList().then(res=>{
       sellerArray.value = res.data?.all_list || []
       // console.log(res);
     })
@@ -374,10 +373,10 @@ const moment = inject('$moment')
                     业务收入金额<el-icon color="white" size="16" style="margin: 0 4px;"><svg-Icon name="svgIcon-financial-info"></svg-Icon></el-icon> :
                   </div>
                   <template #content>
-                    <div style="text-align: center;">
-                      当前销售和日期筛选条件下所有已开票金额(包括已开票已到款
+                    <div>
+                      业务收入金额=已开票已到款金额+已开票未到款金额+未开票已到款金额
                       <br />
-                      和已开票未到款)和已到款金额(未开票已到款)的总和
+                      【日期类型、开票状态、到款状态为空时】
                     </div>
                   </template>
                 </el-tooltip>
@@ -428,16 +427,7 @@ const moment = inject('$moment')
             </div>
           </div>
         </div>
-        <el-dropdown trigger="click" popper-class="classifyFandQ" size="large"  @command="dataExport">
-          <el-button style="margin-bottom: 10px;" size="large" class="element-common-button">导出</el-button>
-          <template #dropdown>
-            <el-dropdown-menu>
-              <el-dropdown-item :command="0">FICC&权益</el-dropdown-item>
-              <el-dropdown-item :command="1">FICC</el-dropdown-item>
-              <el-dropdown-item :command="2">权益</el-dropdown-item>
-            </el-dropdown-menu>
-          </template>
-        </el-dropdown>
+        <el-button style="margin-bottom: 10px;" size="large" class="element-common-button" @click="dataExport">导出</el-button>
         
       </div>
       <div class="table-zone">
@@ -445,10 +435,14 @@ const moment = inject('$moment')
         max-height="600" :row-class-name="tableRowClassName" @sort-change="sortChange" >
           <el-table-column label="序号" align="center" prop="serialNumber" >
           </el-table-column>
-          <el-table-column label="客户名称" prop="company_name" align="center" show-overflow-tooltip ></el-table-column>
-          <el-table-column label="是否新客户" prop="new_company" align="center">
+          <el-table-column label="客户名称" prop="company_name" align="center" show-overflow-tooltip >
+            <template #default="{row}">
+              {{row.company_name}}{{ row.actual_pay_companies&&`(代付方:${row.actual_pay_companies})`}}{{  }}
+            </template>
+          </el-table-column>
+          <el-table-column label="是否新客户" prop="contract_type" align="center">
             <template #default="{row}">
-              {{ row.new_company==1?'是':'否' }}
+              {{ row.contract_type==0?'/':row.contract_type==1?'是':'否' }}
             </template>
           </el-table-column>
           <el-table-column label="合同有效期" prop="date" align="center" show-overflow-tooltip ></el-table-column>
@@ -469,11 +463,7 @@ const moment = inject('$moment')
           </el-table-column>
           <el-table-column label="销售" prop="seller_name" align="center"></el-table-column>
           <el-table-column label="销售组别" prop="seller_group_name" align="center"></el-table-column>
-          <el-table-column label="销售类型" prop="seller_type" align="center">
-            <template #default="{row}">
-              {{ sellerTypeArray[row.seller_type] }}
-            </template>
-          </el-table-column>
+          <el-table-column label="销售类型" prop="seller_type" align="center"></el-table-column>
           <el-table-column label="套餐信息" prop="services_name" align="center">
             <template #default="{row}">
               <span v-if="row.payment_amount&&row.payment_amount!=0" @click="setServiceInfo(row)"

+ 64 - 0
src/views/financialStatistics/components/currencyAmountBox.vue

@@ -0,0 +1,64 @@
+<script setup>
+  const props=defineProps({
+    currnecyData:{
+      type:Object,
+      required:true,
+      default:()=>[]
+    }
+  })
+</script>
+
+<template>
+    <div class="iandP-top-amout" v-if="currnecyData">
+      <div class="iandP-amout-box">
+        <div class="iandP-amout-box-text">
+          <span><slot></slot></span>
+          <span>{{ currnecyData.currencyTotal }}(CNY)</span>
+        </div>
+        <svg-Icon name="svgIcon-financial-calculation" size="40" style="min-width: 40px;" />
+      </div>
+      <div class="iandP-amout-box" v-for="item in currnecyData.currencyList" :key="item.code">
+        <div class="iandP-amout-box-text">
+          <span>{{ item.name }}({{ item.code }})</span>
+          <span>{{ item.amount }}</span>
+        </div>
+        <img :src="item.flag_img" style="height: 40px;width: 40px;" />
+      </div>
+    </div>
+</template>
+  
+<style lang="scss" scoped>
+.iandP-top-amout{
+  display: flex;
+  flex-wrap: wrap;
+  .iandP-amout-box{
+    display: flex;
+    justify-content: space-between;
+    height: 88px;
+    width: 274px;
+    background: #FFFFFF;
+    border: 1px solid #DCDFE6;
+    box-shadow: 0px 4px 12px rgba(153, 153, 153, 0.08);
+    border-radius: 8px;
+    padding: 14px 20px 20px;
+    box-sizing: border-box;
+    margin-right: 30px;
+    margin-bottom: 10px;
+    .iandP-amout-box-text{
+      display: flex;
+      flex-direction: column;
+      justify-content: space-between;
+      span{
+        font-size: 18px;
+        font-weight: 700;
+        color: $mainTextColor;
+        &:first-child{
+          font-size: 14px;
+          font-weight: 400;
+          color: $secondaryTextColor;
+        }
+      }
+    }
+  }
+}
+</style>

+ 1 - 1
src/views/financialStatistics/salesStatistics.vue

@@ -182,7 +182,7 @@
             <template #header>
               <el-tooltip content="收入金额为开票金额换算后的人民币金额" placement="top">
                 <span style="display: inline-flex;align-items: center;">收入金额(元)
-                  <svg-Icon name="svgIcon-financial-info" size="18" style="margin-left: 5px;color: white;" />
+                  <svg-Icon name="svgIcon-financial-info" size="18" color="#C0C4CC" style="margin-left: 5px;color: white;" />
                 </span>
               </el-tooltip>
             </template>

+ 224 - 0
src/views/financialStatistics/waitInvoice.vue

@@ -0,0 +1,224 @@
+<script setup>
+  import {getSellerTeamList} from '@/api/crm'
+  import {getWaitInvoiceList} from '@/api/financialStatistics'
+
+  import currencyAmountBox from './components/currencyAmountBox.vue';
+  import {downloadByFlow} from '@/utils/common-methods'
+
+  const searchParams=reactive({
+    keyword:'',
+    list_param:'',
+    seller_ids:'',
+    current:1,
+    page_size:10,
+    sort_param:'',
+    sort_type:'',
+    is_export:0
+  })
+  
+  const tableData=reactive({
+    list:[],
+    total:0,
+    rowMergeArray:[],
+    currencyList:[],
+    currencyTotal:0,
+  })
+  // ---------------------------------销售模块 
+  const sellerArray=ref([])
+  const sellerChange=(value)=>{
+    searchParams.seller_ids = value.join(',')
+    searchList()
+  }
+  // 获取销售列表
+  const getSellerListFun=()=>{
+    getSellerTeamList().then(res=>{
+      sellerArray.value = res.data?.all_list || []
+    })
+  }
+
+  const searchList=()=>{
+    searchParams.current=1
+    getList()
+  }
+
+  const sortChange=({prop,order})=>{
+    // console.log({prop,order});
+    searchParams.sort_param = order?prop:''
+    searchParams.sort_type=order=='descending'?'desc':order=='ascending'?'asc':''
+    getList()
+  }
+
+  const getList=()=>{
+    getWaitInvoiceList(searchParams).then(res=>{
+      // console.log(res);
+      tableData.total = res.data.page?.total || 0
+      let dataTemp=res.data?.list?.data_list||[]
+      tableData.rowMergeArray=[]
+      tableData.list=[]
+      dataTemp.map((item,index) =>{
+        if(!item.not_invoice_list?.length>0){
+          tableData.rowMergeArray.push(1)
+          tableData.list.push({
+            serial_number:searchParams.page_size*(searchParams.current-1)+index+1,
+            ...item
+          })
+        }else{
+          tableData.rowMergeArray.push(item.not_invoice_list.length)
+          item.not_invoice_list.map((it,ind) =>{
+            if(ind>0){
+              tableData.rowMergeArray.push(0)
+            }
+            tableData.list.push({
+              serial_number:searchParams.page_size*(searchParams.current-1)+index+1,
+              ...item,
+              ...{not_invoiced_amount_total:it.not_invoiced_amount_total,
+                service_product_id:it.service_product_id,
+                seller_name:it.seller_name,
+                rai_seller_name:it.rai_seller_name,
+                seller_group_name:it.seller_group_name,
+                rai_seller_group_name:it.rai_seller_group_name,
+                seller_type:it.seller_type}
+            })
+          })
+        }
+      })
+
+      tableData.currencyList = res.data?.list?.not_invoice_currency_total || []
+      tableData.currencyTotal = res.data?.list?.not_invoice_total||0
+      
+    })
+  }
+  const changePageSize=(pageSize)=>{
+    searchParams.page_size = pageSize
+    getList()
+  }
+  const changePageNo = (pageNo)=>{
+    searchParams.current = pageNo
+    getList()
+  }
+  // 合并单元格
+  const cellMerge=({ row,column,rowIndex,columnIndex})=>{
+    if([0,1,2,3,4,5,6].includes(columnIndex)){
+      const _row = tableData.rowMergeArray[rowIndex];
+      return {
+        rowspan: _row,
+        colspan: 1
+      };
+    }
+  }
+
+  // 导出
+  const watiInvoiceExport=()=>{
+    getWaitInvoiceList({...searchParams,is_export:1}).then(res=>{
+      downloadByFlow(res,'xlsx',`未开票统计表`)
+    })
+  }
+
+// --------------------------------created
+  getSellerListFun()
+  getList()
+</script>
+
+<template>
+    <div class="wait-invoice-container" id="wait-invoice-container">
+      <div class="wait-invoice-searchZone">
+        <el-input v-model="searchParams.keyword" placeholder="请输入客户名称/合同编号" 
+        clearable  @input="searchList" class="statistics-search-item" style="width: 308px;"></el-input>
+        <el-cascader :options="sellerArray" style="margin-left: 30px;margin-bottom: 8px;z-index: 100;min-width: 308px;" filterable collapse-tags-tooltip
+          @change="sellerChange" placeholder="请选择销售" clearable collapse-tags :show-all-levels="false"
+          :props="{multiple:true,label:'seller_name',value:'seller_id',children:'child',emitPath:false}" key="seller" >
+        </el-cascader>
+        <el-select v-model="searchParams.list_param" placeholder="请选择套餐类型" style="width: 308px;"
+          @change="searchList" class="statistics-search-item" clearable >
+          <el-option label="FICC套餐" :value="1"></el-option>
+          <el-option label="权益套餐" :value="2"></el-option>
+        </el-select>
+      </div>
+      <div class="iandP-table-top">
+        <currencyAmountBox :currnecyData="{currencyList:tableData.currencyList,currencyTotal:tableData.currencyTotal}">
+          未开票合计金额(换算后)
+        </currencyAmountBox>
+        <el-button class="element-common-button" style="margin-bottom: 10px;width: 118px;" size="large" @click="watiInvoiceExport">导出</el-button>
+      </div>
+      <el-table :data="tableData.list" border max-height="579px" @sort-change="sortChange" :span-method="cellMerge">
+        <el-table-column label="序号" prop="serial_number" width="70px" align="center"></el-table-column>
+        <el-table-column label="客户名称" align="center" prop="company_name" show-overflow-tooltip></el-table-column>
+        <el-table-column label="合同编号" align="center" prop="contract_code" show-overflow-tooltip></el-table-column>
+        <el-table-column label="合同开始时间" align="center" prop="start_date" sortable="custom"></el-table-column>
+        <el-table-column label="合同结束时间" align="center" prop="end_date" sortable="custom"></el-table-column>
+        <el-table-column label="合同金额" align="center" prop="contract_amount"></el-table-column>
+        <el-table-column label="金额单位" align="center" prop="unit_name"></el-table-column>
+        <el-table-column label="未开票金额" align="center" prop="not_invoiced_amount_total">
+          <template #header>
+            <el-tooltip content="未开票未到款金额" placement="top">
+              <span style="display: inline-flex;align-items: center;">未开票金额
+                <svg-Icon name="svgIcon-financial-info" size="18" style="margin-left: 5px;color: white;" />
+              </span>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+        <el-table-column label="套餐类型" align="center" prop="service_type">
+          <template #header>
+            <el-tooltip content="合同套餐类型" placement="top">
+              <span style="display: inline-flex;align-items: center;">套餐类型
+                <svg-Icon name="svgIcon-financial-info" size="18" style="margin-left: 5px;color: white;" />
+              </span>
+            </el-tooltip>
+          </template>
+          <template #default="{row}">
+            {{ row.service_product_id==1?'FICC套餐':row.service_product_id==2?'权益套餐':'--' }}
+          </template>
+        </el-table-column>
+        <el-table-column label="销售" align="center" prop="seller_name" >
+          <template #header>
+            <el-tooltip content="合同销售" placement="top">
+              <span style="display: inline-flex;align-items: center;">销售
+                <svg-Icon name="svgIcon-financial-info" size="18" style="margin-left: 5px;color: white;" />
+              </span>
+            </el-tooltip>
+          </template>
+          <template #default="{row}">
+            {{ (row.seller_type=='FICC销售'?row.seller_name:row.rai_seller_name) || '--' }}
+          </template>
+        </el-table-column>
+        <el-table-column label="销售组别" align="center" prop="seller_group_name" >
+          <template #default="{row}">
+            {{ (row.seller_type=='FICC销售'?row.seller_group_name:row.rai_seller_group_name) || '--' }}
+          </template>
+        </el-table-column>
+        <el-table-column label="销售类型" align="center" prop="seller_type" ></el-table-column>
+        <template #empty>
+          <div class="table-no-data">
+            <img src="@/assets/img/icon/empty-data.png" />
+            <span>暂无数据</span>
+          </div>
+        </template>
+      </el-table>
+      <!-- 分页 -->
+      <m-page :pageSize="searchParams.page_size" :page_no="searchParams.current" 
+      style="display: flex;justify-content: flex-end;margin-top: 20px;" 
+      :total="tableData.total" @handleCurrentChange="changePageNo" @handleSizeChange="changePageSize"/>
+    </div>
+</template>
+  
+<style lang="scss" scoped>
+  .wait-invoice-container{
+    min-height: 100%;
+    .wait-invoice-searchZone{
+      display: flex;
+      flex-wrap: wrap;
+      margin-left: -30px;
+      margin-bottom: 20px;
+      .statistics-search-item{
+        margin-bottom: 8px;
+        margin-left: 30px;
+      }
+    }
+    .iandP-table-top{
+      display: flex;
+      align-items: flex-end;
+      justify-content: space-between;
+      margin-bottom: 20px;
+    }
+  }
+</style>

+ 182 - 0
src/views/financialStatistics/waitPayment.vue

@@ -0,0 +1,182 @@
+<script setup>
+import { getSellerTeamList } from '@/api/crm'
+import {getWaitPaymentList} from '@/api/financialStatistics'
+
+import currencyAmountBox from './components/currencyAmountBox.vue'
+import {downloadByFlow} from '@/utils/common-methods'
+
+const searchParams = reactive({
+    keyword: '',
+    list_param: '',
+    seller_ids: '',
+    current: 1,
+    page_size: 10,
+    sort_type: '',
+    is_export:0
+})
+
+const tableData = reactive({
+    list: [],
+    total: 0,
+    currencyList: [],
+    currencyTotal: 0,
+})
+// ---------------------------------销售模块 
+const sellerArray = ref([])
+const sellerChange = (value) => {
+    searchParams.seller_ids = value.join(',')
+    searchList()
+}
+// 获取销售列表
+const getSellerListFun=()=>{
+    getSellerTeamList().then(res=>{
+      sellerArray.value = res.data?.all_list || []
+    })
+}
+
+const searchList = () => {
+    searchParams.current=1
+    getList()
+}
+
+const sortChange = ({ prop, order }) => {
+    // console.log({prop,order});
+    // searchParams.sort_param = order ? prop : ''
+    searchParams.sort_type = order == 'descending' ? 'desc' : order == 'ascending' ? 'asc' : ''
+    getList()
+}
+
+const getList = () => {
+    getWaitPaymentList(searchParams).then(res=>{
+      // console.log(res);
+      tableData.total = res.data.page?.total || 0
+      let dataTemp=res.data?.list?.data_list||[]
+      tableData.list=[]
+      dataTemp.map((item,index) =>{
+        tableData.list.push({
+        serial_number:searchParams.page_size*(searchParams.current-1)+index+1,
+        ...item,...(item.invoice_payment_list?item.invoice_payment_list[0]:{})
+        })
+      })
+      tableData.currencyList = res.data?.list?.not_payment_currency_total || []
+      tableData.currencyTotal = res.data?.list?.not_payment_total||0 
+    })
+}
+const changePageSize = (pageSize) => {
+    searchParams.page_size = pageSize
+    getList()
+}
+const changePageNo = (pageNo) => {
+    searchParams.current = pageNo
+    getList()
+}
+
+// 导出
+const watiPlacementExport = () => {
+    getWaitPaymentList({...searchParams,is_export:1}).then(res=>{
+      downloadByFlow(res,'xlsx',`开票未到款统计表`)
+    })
+}
+
+// --------------------------------created
+getSellerListFun()
+getList()
+</script>
+
+<template>
+    <div class="wait-placement-container" id="wait-placement-container">
+        <div class="wait-placement-searchZone">
+            <el-input v-model="searchParams.keyword" placeholder="请输入客户名称/合同编号" clearable @input="searchList"
+                class="statistics-search-item" style="width: 308px;"></el-input>
+            <el-cascader :options="sellerArray" style="margin-left: 30px;margin-bottom: 8px;z-index: 100;width: 308px;" filterable collapse-tags-tooltip
+            @change="sellerChange" placeholder="请选择销售" clearable collapse-tags :show-all-levels="false"
+            :props="{ multiple: true, label: 'seller_name', value: 'seller_id', children: 'child', emitPath: false }" key="seller">
+            </el-cascader>
+            <el-select v-model="searchParams.list_param" placeholder="请选择套餐类型" @change="searchList"
+                class="statistics-search-item" clearable style="width: 308px;">
+                <el-option label="FICC套餐" :value="1"></el-option>
+                <el-option label="权益套餐" :value="2"></el-option>
+            </el-select>
+        </div>
+        <div class="iandP-table-top">
+            <currencyAmountBox :currnecyData="{currencyList:tableData.currencyList,currencyTotal:tableData.currencyTotal}">
+                开票未到款统计(换算后)
+            </currencyAmountBox>
+            <el-button class="element-common-button" style="margin-bottom: 10px;" size="large"
+                @click="watiPlacementExport">导出</el-button>
+        </div>
+        <el-table :data="tableData.list" border max-height="579px" @sort-change="sortChange">
+            <el-table-column label="序号" prop="serial_number" width="70px" align="center"></el-table-column>
+            <el-table-column label="客户名称" align="center" prop="company_name" show-overflow-tooltip></el-table-column>
+            <el-table-column label="合同编号" align="center" prop="contract_code" show-overflow-tooltip></el-table-column>
+            <el-table-column label="合同有效期" align="center" prop="start_date">
+                <template #default="{ row }">
+                    {{ (row.start_date + ' 至 ' + row.end_date) }}
+                </template>
+            </el-table-column>
+            <el-table-column label="套餐类型" align="center" prop="service_type">
+                <template #header>
+                    <el-tooltip content="开票套餐类型" placement="top">
+                        <span style="display: inline-flex;align-items: center;">套餐类型
+                            <svg-Icon name="svgIcon-financial-info" size="18" style="margin-left: 5px;color: white;" />
+                        </span>
+                    </el-tooltip>
+                </template>
+                <template #default="{row}">
+                    {{ row.service_product_id==1?'FICC套餐':row.service_product_id==2?'权益套餐':'--' }}
+                </template>
+            </el-table-column>
+            <el-table-column label="开票金额" align="center" prop="not_payment_amount">
+                <template #header>
+                    <el-tooltip content="开票未到款金额" placement="top">
+                        <span style="display: inline-flex;align-items: center;">开票金额
+                            <svg-Icon name="svgIcon-financial-info" size="18" style="margin-left: 5px;color: white;" />
+                        </span>
+                    </el-tooltip>
+                </template>
+            </el-table-column>
+            <el-table-column label="金额单位" align="center" prop="unit_name"></el-table-column>
+            <el-table-column label="开票日" align="center" prop="invoice_time" sortable="custom"></el-table-column>
+            <el-table-column label="开票销售" align="center" prop="seller_name"></el-table-column>
+            <el-table-column label="销售组别" align="center" prop="seller_group_name"></el-table-column>
+            <el-table-column label="销售类型" align="center" prop="seller_type">
+                <template #default="{row}">
+                    {{ row.seller_type==1?'FICC销售':row.seller_type==2?'权益销售':'--' }}
+                </template>
+            </el-table-column>
+            <template #empty>
+                <div class="table-no-data">
+                    <img src="@/assets/img/icon/empty-data.png" />
+                    <span>暂无数据</span>
+                </div>
+            </template>
+        </el-table>
+        <!-- 分页 -->
+        <m-page :pageSize="searchParams.page_size" :page_no="searchParams.current"
+            style="display: flex;justify-content: flex-end;margin-top: 20px;" :total="tableData.total"
+            @handleCurrentChange="changePageNo" @handleSizeChange="changePageSize" />
+    </div>
+</template>
+  
+<style lang="scss" scoped>.wait-placement-container {
+    min-height: 100%;
+
+    .wait-placement-searchZone {
+        display: flex;
+        flex-wrap: wrap;
+        margin-left: -30px;
+        margin-bottom: 20px;
+
+        .statistics-search-item {
+            margin-bottom: 8px;
+            margin-left: 30px;
+        }
+    }
+
+    .iandP-table-top {
+        display: flex;
+        align-items: flex-end;
+        justify-content: space-between;
+        margin-bottom: 20px;
+    }
+}</style>