Răsfoiți Sursa

数据报表功能开发

caiyuqin 11 luni în urmă
părinte
comite
31d1d23e0f
19 a modificat fișierele cu 4743 adăugiri și 1858 ștergeri
  1. 28 3
      src/api/modules/consoleManage.ts
  2. 269 97
      src/views/consoleManage/businessDataManage/channelDataManage/channelDataManageDetail.vue
  3. 386 139
      src/views/consoleManage/businessDataManage/channelDataManage/index.vue
  4. 88 41
      src/views/consoleManage/businessDataManage/companyDataManage/companyDataManageDetail.vue
  5. 8 1
      src/views/consoleManage/businessDataManage/companyDataManage/index.vue
  6. 275 97
      src/views/consoleManage/businessDataManage/contactPersonDataManage/contactPersonDataManageDetail.vue
  7. 275 140
      src/views/consoleManage/businessDataManage/contactPersonDataManage/index.vue
  8. 281 140
      src/views/consoleManage/businessDataManage/riskDataManage/index.vue
  9. 261 97
      src/views/consoleManage/businessDataManage/riskDataManage/riskDataManageDetail.vue
  10. 206 67
      src/views/consoleManage/businessDataManage/salesmanDataManage/index.vue
  11. 269 97
      src/views/consoleManage/businessDataManage/salesmanDataManage/salesmanDataManageDetail.vue
  12. 386 139
      src/views/consoleManage/businessDataManage/telemarketingDataManage/index.vue
  13. 269 97
      src/views/consoleManage/businessDataManage/telemarketingDataManage/telemarketingDataManageDetail.vue
  14. 26 3
      src/views/consoleManage/components/queryForm.vue
  15. 350 140
      src/views/consoleManage/quotationDataManage/channelQuotationData/index.vue
  16. 350 140
      src/views/consoleManage/quotationDataManage/companyQuotationData/index.vue
  17. 316 140
      src/views/consoleManage/quotationDataManage/quotationOrderData/index.vue
  18. 350 140
      src/views/consoleManage/quotationDataManage/salesmanQuotationData/index.vue
  19. 350 140
      src/views/consoleManage/quotationDataManage/telemarketingQuotationData/index.vue

+ 28 - 3
src/api/modules/consoleManage.ts

@@ -11,11 +11,36 @@ const manageApi = (axiosInstance: ApiInstance) => ({
     getDeptListByUserId: (params: any) => axiosInstance.get('/console/searchConfiguration/getDeptListByUserId',{params}),//通过用户id查询机构树
     getUserManageListByUserId: (params: any) => axiosInstance.get('/console/searchConfiguration/getUserManageListByUserId',{params}),//通过用户id查询管理人树
     downTaskFile: (params: any) => axiosInstance.get('/console/task/downTaskFile',{params}),//下载导出的excel文件
-
+     //保险公司
     companyDataManagePageList: (params: any) => axiosInstance.post('/console/businessDataManage/companyDataManagePageList',params),//列表接口
     companyDataManageToTask: (params: any) => axiosInstance.post('/console/businessDataManage/companyDataManageToTask',params),//列表导出接口
-
-
+    companyDataManageDetailPageList: (params: any) => axiosInstance.post('/console/businessDataManage/companyDataManageDetailPageList',params),//明细接口
+    companyDataManageDetailToTask: (params: any) => axiosInstance.post('/console/businessDataManage/companyDataManageDetailToTask',params),//明细出接口
+    //险种报表
+    riskDataManagePageList: (params: any) => axiosInstance.post('/console/businessDataManage/riskDataManagePageList',params),//列表接口
+    riskDataManageToTask: (params: any) => axiosInstance.post('/console/businessDataManage/riskDataManageToTask',params),//列表导出接口
+    riskDataManageDetailPageList: (params: any) => axiosInstance.post('/console/businessDataManage/riskDataManageDetailPageList',params),//明细接口
+    riskDataManageDetailToPage: (params: any) => axiosInstance.post('/console/businessDataManage/riskDataManageDetailToPage',params),//明细出接口
+    //对接人
+    contactPersonDataManagePageList: (params: any) => axiosInstance.post('/console/businessDataManage/contactPersonDataManagePageList',params),//列表接口
+    contactPersonDataManageToTask: (params: any) => axiosInstance.post('/console/businessDataManage/contactPersonDataManageToTask',params),//列表导出接口
+    contactPersonDataManageDetailPageList: (params: any) => axiosInstance.post('/console/businessDataManage/contactPersonDataManageDetailPageList',params),//明细接口
+    contactPersonDataManageDetailToTask: (params: any) => axiosInstance.post('/console/businessDataManage/contactPersonDataManageDetailToTask',params),//明细出接口
+    //业务员
+    salesmanDataManagePageList: (params: any) => axiosInstance.post('/console/businessDataManage/salesmanDataManagePageList',params),//列表接口
+    salesmanDataManageToTask: (params: any) => axiosInstance.post('/console/businessDataManage/salesmanDataManageToTask',params),//列表导出接口
+    salesmanDataManageDetailPageList: (params: any) => axiosInstance.post('/console/businessDataManage/salesmanDataManageDetailPageList',params),//明细接口
+    salesmanDataManageDetailToTask: (params: any) => axiosInstance.post('/console/businessDataManage/salesmanDataManageDetailToTask',params),//明细出接口
+    //渠道
+    channelDataManagePageList: (params: any) => axiosInstance.post('/console/businessDataManage/channelDataManagePageList',params),//列表接口
+    channelDataManageToTask: (params: any) => axiosInstance.post('/console/businessDataManage/channelDataManageToTask',params),//列表导出接口
+    channelDataManageDetailPageList: (params: any) => axiosInstance.post('/console/businessDataManage/channelDataManageDetailPageList',params),//明细接口
+    channelDataManageDetailToTask: (params: any) => axiosInstance.post('/console/businessDataManage/channelDataManageDetailToTask',params),//明细出接口
+    //电销
+    telemarketingDataManagePageList: (params: any) => axiosInstance.post('/console/businessDataManage/telemarketingDataManagePageList',params),//列表接口
+    telemarketingDataManageToTask: (params: any) => axiosInstance.post('/console/businessDataManage/telemarketingDataManageToTask',params),//列表导出接口
+    telemarketingDataManageDetailPageList: (params: any) => axiosInstance.post('/console/businessDataManage/telemarketingDataManageDetailPageList',params),//明细接口
+    telemarketingDataManageDetailToTask: (params: any) => axiosInstance.post('/console/businessDataManage/telemarketingDataManageDetailToTask',params),//明细出接口
   })
 
 export default manageApi

+ 269 - 97
src/views/consoleManage/businessDataManage/channelDataManage/channelDataManageDetail.vue

@@ -1,117 +1,289 @@
 <template>
-  <div class="logDetail">
-    <el-descriptions :column="2">
-      <template #title>
-        <div class="title">
-          <div class="icon">
-            <el-icon><List /></el-icon>
-          </div>
-          <p>{{ detailData?.operationContent }}</p>
-        </div>
+  <div class="log">
+    <div class='btn-box'>
+      <el-button type="primary" plain class='query-btn'
+        @click='dialogShow'>{{selectedKeys.length?`已选${selectedKeys.length}项`:'筛选条件'}}</el-button>
+      <div class='query-btn'>
+        <DowButton @endAnim='downloadFile'></DowButton>
+      </div>
+    </div>
+    <QueryForm :option="listOption" @query='query' @delSelect='delSelect' ref='queryFormRef'></QueryForm>
+
+    <!-- 表格 -->
+    <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
+      :columnwidth="120" :pageInfo="pageInfo" @getList="getList" :showOperation='false'>
+
+      <template v-slot:search="scope">
+        <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+          @update:sort="handleSortUpdate"></Sort>
       </template>
-      <el-descriptions-item label="操作功能:" label-align="right" align="left" label-width="100">{{ detailData?.moduleName }}</el-descriptions-item>
-      <el-descriptions-item label="操作类型:" label-align="right" align="left" label-width="100">{{ detailData?.operatorName }}</el-descriptions-item>
-      <el-descriptions-item label="操作人:" label-align="right" align="left" label-width="100">{{ detailData?.createBy }}</el-descriptions-item>
-      <el-descriptions-item label="操作时间:" label-align="right" align="left" label-width="100">{{ detailData?.createTime }}</el-descriptions-item>
-    </el-descriptions>
-    <el-row :gutter="20" class="content">
-      <el-col :span="11">
-        <p>变更前</p>
-        <div class="list">
-          <el-row class="list-item" :gutter="20" v-for="item in detailData?.compareResultList" :key="item">
-            <el-col :span="6">{{ item.name }}</el-col>
-            <el-col :span="18" style="color: #606266">{{ item.fieldContent }}</el-col>
-          </el-row>
-        </div>
-      </el-col>
-      <el-divider direction="vertical" style="height: 100%"></el-divider>
-      <el-col :span="11">
-        <p>变更后</p>
-        <div class="list">
-          <el-row class="list-item" :gutter="20" v-for="item in detailData?.compareResultList" :key="item">
-            <el-col :span="6">{{ item.name }}</el-col>
-            <el-col :span="18" style="color: #606266">{{ item.newFieldContent }}</el-col>
-          </el-row>
-        </div>
-      </el-col>
-    </el-row>
+
+    </ComplexTable>
+
+    <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
+      routerKey='routerKey'>
+    </FilterDialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import api from '@/api'
-import { useRoute, useRouter } from 'vue-router'
+import { useRouter } from "vue-router";
+import api from "@/api";
+import QueryForm from "../../components/queryForm.vue";
+import FilterDialog from "../../components/filterDialog.vue";
+import DowButton from "../../components/button.vue";
+import Sort from "../../components/sort.vue";
+import useUserStore from "@/store/modules/message";
+import PageInfo from "@/api/types/agreementTypes";
 import { ElMessage } from "element-plus";
 
-const myRoute = useRoute()
-const myRouter = useRouter()
-
-let detailData = ref(undefined)
-
-const initDetail = () => {
-  api.logApi.selectById(myRoute.query.id).then((res: any) => {
-    if(res.code == 200) {
-      detailData.value = res.data
-    } else {
-      ElMessage({
-        message: res.msg,
-        type: 'warning'
-      })
-    }
-  })
+const router = useRouter();
+const userStore = useUserStore();
+const isShow = ref(false);
+
+const isSort = ref();
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const listOption = reactive({
+  rowKey: "channelDelId",
+  //查询
+  queryFormFields: [],
+  // 表格列
+  columns: [
+    {
+      prop: "salesmanName",
+      label: "业务员",
+      width: "200",
+    },
+    {
+      prop: "salesmanPhone",
+      label: "手机号",
+      width: "120",
+    },
+    {
+      prop: "companyId",
+      label: "保险公司",
+      width: "200",
+    },
+    {
+      prop: "companyName",
+      label: "合作保险公司",
+      width: "300",
+    },
+    {
+      prop: "orderNo",
+      label: "订单号",
+      width: "180",
+    },
+    {
+      prop: "licenseNo",
+      label: "车牌号",
+      width: "180",
+    },
+    {
+      prop: "orderTypeName",
+      label: "订单类型",
+      width: "180",
+    },
+    {
+      prop: "riskName",
+      label: "险种",
+      width: "180",
+    },
+    {
+      prop: "quoteCountNum",
+      label: "报价次数",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "sumPremium",
+      label: "保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "createTime",
+      label: "录单时间",
+      width: "180",
+    },
+    {
+      prop: "recordTime",
+      label: "签单时间",
+      width: "180",
+    },
+    {
+      prop: "manegerName",
+      label: "管理人",
+      width: "180",
+    },
+  ],
+});
+
+const selectedKeys = ref([]);
+const selected = function (val) {
+  selectedKeys.value = val;
+};
+
+//查询数据
+const phone = JSON.parse(localStorage.getItem("userInfo")).username;
+
+//获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("channelDataManageDetail");
+const defaultList = ref();
+const pageHiddenList = ref([]); //页面不显示的数据
+const initDefaultList = async () => {
+  const { data } = await api.manageApi.getSearchDefaultList({
+    routerKey: routerKey.value,
+    userId: phone,
+  });
+  listOption.queryFormFields = data.filter((e) => e.showFlag);
+
+  pageHiddenList.value = data.filter((e) => !e.showFlag);
+  defaultList.value = data.map((e) => e.id);
+  selectedKeys.value = defaultList.value;
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
+};
+
+//删除
+const filterDialogRef = ref();
+const delSelect = (id) => {
+  listOption.queryFormFields = listOption.queryFormFields.filter(
+    (item) => item.id != id
+  );
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//打开dialogShow
+const dialogShow = function () {
+  isShow.value = true;
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//确定
+const queryFormRef = ref();
+const filterSure = (item, index) => {
+  isShow.value = false;
+  const secondGroupIds = item.list.map((item) => item.id);
+  const oldList = listOption.queryFormFields.filter((item) =>
+    secondGroupIds.includes(item.id)
+  );
+  const firstGroupIds = listOption.queryFormFields.map((item) => item.id);
+  let newList = item.list.filter((item) => !firstGroupIds.includes(item.id));
+
+  //过滤掉默认不显示的数据
+  const hiddenList = new Set(pageHiddenList.value.map((item) => item.id));
+  const filterList = newList.filter((item) => !hiddenList.has(item.id));
+
+  listOption.queryFormFields = [...oldList, ...filterList];
+  queryFormRef.value?.initDefaultSaveForm();
+  selectedKeys.value = item.list.filter((item) => item.id);
+};
+
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
+
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
+
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.channelDataManageDetailPageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
+};
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
-onMounted(() => {
-  initDetail()
-})
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.channelDataManageDetailToTask({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
 
+onMounted(() => {
+  initDefaultList();
+});
 </script>
 
 <style scoped lang="scss">
-.logDetail{
-  padding: 24px;
-  background: #FFFFFF;
+.log {
   width: 100%;
   height: calc(100vh - 120px);
-  .title{
-    display: flex;
-    align-items: center;
-    justify-content: flex-start;
-    .icon{
-      width: 30px;
-      height: 30px;
-      border-radius: 50%;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      background: #1A85FA;
-      color: #FFFFFF;
-      font-size: 20px;
-      margin-right: 10px;
-    }
-  }
-  .content{
-    height: calc(100% - 120px);
-    overflow: hidden;
-    p{
-      text-align: center;
-      background: #F0F0F0;
-      margin: 0;
-      padding: 16px 0;
-    }
-    .list{
-      height: calc(100% - 80px);
-      overflow-y: auto;
-      overflow-x: hidden;
-      .list-item{
-        margin: 14px 0;
-        padding: 0 20px;
-        display: flex;
-      }
-    }
+  background: #ffffff;
+  padding: 24px;
+  overflow-y: auto;
+  .query-btn {
+    margin-left: 20px;
   }
-  :deep(.el-descriptions) {
-    width: 50%;
+  .btn-box {
+    padding-bottom: 15px;
+    margin-bottom: 24px;
+    border-bottom: 1px solid #eeeeee;
+    display: flex;
+    justify-content: flex-end;
   }
 }
+:deep(.caret-wrapper) {
+  display: none !important;
+}
 </style>

+ 386 - 139
src/views/consoleManage/businessDataManage/channelDataManage/index.vue

@@ -1,170 +1,417 @@
 <template>
   <div class="log">
-    <el-form label-width="100" label-position="left" :model="form">
-      <el-row :gutter="20">
-        <el-col :span="8">
-          <el-form-item label="操作人">
-            <el-input v-model="form.operator" placeholder="请输入操作人姓名查找"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作时间">
-            <el-date-picker
-              v-model="form.operatingTime"
-              type="daterange"
-              range-separator="至"
-              start-placeholder="开始时间"
-              end-placeholder="结束时间"
-              format="YYYY-MM-DD"
-              value-format="YYYY-MM-DD"
-              @change="timeChange"
-            />
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作功能">
-            <el-select v-model="form.function" placeholder="请选择">
-              <el-option label="工能1" value="1" key="1"></el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作内容">
-            <el-input v-model="form.content" placeholder="请输入"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="16" style="display: flex; align-items: center; justify-content: flex-end">
-          <el-button type="primary" @click="search">查询</el-button>
-          <el-button plain type="primary" @click="reset">重置</el-button>
-        </el-col>
-      </el-row>
-    </el-form>
-    <el-table
-      :data="tableData"
-      height="600"
-      style="margin-top: 24px"
-    >
-      <el-table-column label="操作人" prop="createBy" width="200"></el-table-column  >
-      <el-table-column label="操作时间" prop="createTime" width="240"></el-table-column>
-      <el-table-column label="操作功能" prop="moduleName"></el-table-column>
-      <el-table-column label="操作内容" prop="operationContent"></el-table-column>
-      <el-table-column label="类型" prop="operatorName" width="150"></el-table-column>
-      <el-table-column label="操作" width="150">
-        <template #default="scope">
-          <el-button link type="primary" @click="detail(scope.row)">查看详情</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <div class="pagination">
-      <el-pagination
-        v-model:current-page="pages"
-        v-model:page-size="size"
-        :page-sizes="[10, 20, 30, 40]"
-        layout="total, sizes, prev, pager, next, jumper"
-        :total="total"
-        @size-change="handleSizeChange"
-        @current-change="handleCurrentChange"
-      ></el-pagination>
+    <div class='btn-box'>
+      <el-button type="primary" plain class='query-btn'
+        @click='dialogShow'>{{selectedKeys.length?`已选${selectedKeys.length}项`:'筛选条件'}}</el-button>
+      <div class='query-btn'>
+        <DowButton @endAnim='downloadFile'></DowButton>
+      </div>
     </div>
+    <QueryForm :option="listOption" @query='query' @delSelect='delSelect' ref='queryFormRef'></QueryForm>
+    <div class='flex content-box'>
+      <!-- tree -->
+      <div>
+        <div class='content-l'>
+          <div class='item' v-for='(item,index) in tabList' :key="index" :class="{'active':index==tabIndex}"
+            @click='tabClick(item,index)'>
+            {{item.name}}
+          </div>
+        </div>
+        <Tree ref='treeRef'></Tree>
+      </div>
+
+      <div class='flex-1 content-r'>
+        <!-- 表格 -->
+        <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
+          :columnwidth="120" :pageInfo="pageInfo" @getList="getList">
+          <template v-slot:operation="scope">
+            <el-button type="primary" link @click='agreementEdit(scope.operationData.id)'>明细</el-button>
+          </template>
+
+          <template v-slot:search="scope">
+            <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+              @update:sort="handleSortUpdate"></Sort>
+          </template>
+
+          <template #customSlot="{  bodyCell: { scope, column } }">
+            <template v-if="column.prop == 'underwriteOrderNum'">
+              {{ scope.row.underwriteOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'djOrderNum'">
+              {{ scope.row.djOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dsyOrderNum'">
+              {{ scope.row.dsyOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dszOrderNum'">
+              {{ scope.row.dszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jszOrderNum'">
+              {{ scope.row.jszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jsyOrderNum'">
+              {{ scope.row.jsyOrderNum }} 笔
+            </template>
+          </template>
+        </ComplexTable>
+      </div>
+    </div>
+
+    <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
+      routerKey='routerKey'>
+    </FilterDialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import { useRouter } from 'vue-router'
-import api from '@/api'
-import {ElMessage} from "element-plus";
+import { useRouter } from "vue-router";
+import api from "@/api";
+import QueryForm from "../../components/queryForm.vue";
+import FilterDialog from "../../components/filterDialog.vue";
+import DowButton from "../../components/button.vue";
+import Sort from "../../components/sort.vue";
+import useUserStore from "@/store/modules/message";
+import PageInfo from "@/api/types/agreementTypes";
+import Tree from "../../components/tree.vue";
+import { ElMessage } from "element-plus";
 
-const myRouter = useRouter()
+const router = useRouter();
+const userStore = useUserStore();
+const isShow = ref(false);
 
-let activeName = ref('first')
-const handleClick = () => {
+const isSort = ref();
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const listOption = reactive({
+  rowKey: "channelId",
+  //查询
+  queryFormFields: [],
+  // 表格列
+  columns: [
+    {
+      prop: "salesmanName",
+      label: "姓名",
+      width: "100",
+    },
+    {
+      prop: "salesmanPhone",
+      label: "手机号",
+      width: "120",
+    },
+    {
+      prop: "deptName",
+      label: "所属机构",
+      width: "300",
+    },
+    {
+      prop: "underwriteOrderNum",
+      label: "承保订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "sumPremium",
+      label: "保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "jqPremium",
+      label: "交强保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "taxPremium",
+      label: "车船税",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "syPremium",
+      label: "商业保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "jyPremium",
+      label: "驾意保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "单交订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "dsyOrderNum",
+      label: "单商订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "dszOrderNum",
+      label: "单三订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "jszOrderNum",
+      label: "交三订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "jsyOrderNum",
+      label: "交商订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "manegerName",
+      label: "管理人",
+      width: "180",
+    },
+  ],
+});
 
-}
+const selectedKeys = ref([]);
+const selected = function (val) {
+  selectedKeys.value = val;
+};
 
-let form = ref({})
-const tableProps = ref({
-  value: "id",
-  label: "name",
-  children: "children",
-  checkStrictly: true,
-});
-let option = ref([])
-const timeChange = (val) => {
+//查询数据
+const phone = JSON.parse(localStorage.getItem("userInfo")).username;
 
-}
-// 搜索
-const search = () => {
-  pages.value = 1
-  size.value = 10
-  initData()
-}
-const reset = () => {
-  form.value = {}
-  pages.value = 1
-  size.value = 10
-  initData()
+//获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("channelDataManage");
+const defaultList = ref();
+const pageHiddenList = ref([]); //页面不显示的数据
+const initDefaultList = async () => {
+  const { data } = await api.manageApi.getSearchDefaultList({
+    routerKey: routerKey.value,
+    userId: phone,
+  });
+  listOption.queryFormFields = data.filter((e) => e.showFlag);
+
+  pageHiddenList.value = data.filter((e) => !e.showFlag);
+  defaultList.value = data.map((e) => e.id);
+  selectedKeys.value = defaultList.value;
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
+};
+
+//删除
+const filterDialogRef = ref();
+const delSelect = (id) => {
+  listOption.queryFormFields = listOption.queryFormFields.filter(
+    (item) => item.id != id
+  );
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//打开dialogShow
+const dialogShow = function () {
+  isShow.value = true;
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//确定
+const queryFormRef = ref();
+const filterSure = (item, index) => {
+  isShow.value = false;
+  const secondGroupIds = item.list.map((item) => item.id);
+  const oldList = listOption.queryFormFields.filter((item) =>
+    secondGroupIds.includes(item.id)
+  );
+  const firstGroupIds = listOption.queryFormFields.map((item) => item.id);
+  let newList = item.list.filter((item) => !firstGroupIds.includes(item.id));
+
+  //过滤掉默认不显示的数据
+  const hiddenList = new Set(pageHiddenList.value.map((item) => item.id));
+  const filterList = newList.filter((item) => !hiddenList.has(item.id));
+
+  listOption.queryFormFields = [...oldList, ...filterList];
+  queryFormRef.value?.initDefaultSaveForm();
+  selectedKeys.value = item.list.filter((item) => item.id);
+};
+
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
+
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
+
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.channelDataManagePageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
+};
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
-// 列表
-let tableData = ref([])
-const detail = (row) => {
-  myRouter.push({
-    path: '/consoleManage/businessDataManage/channelDataManage/channelDataManageDetail',
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.channelDataManageToTask({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
+
+const agreementEdit = (id) => {
+  router.push({
+    name: "channelDataManageDetail",
     query: {
-      id: row.id
-    }
-  })
-}
+      id: id,
+    },
+  });
+};
 
-// 分页
-let pages = ref(1)
-let size = ref(10)
-let total = ref(0)
-const handleSizeChange = (size) => {
-  size.value = size
-  initData()
-}
-const handleCurrentChange = (page) => {
-  pages.value = page
-  initData()
-}
+//tabClick
+const treeRef = ref();
+const tabIndex = ref(0);
+const tabClick = (item, index) => {
+  tabIndex.value = index;
+  treeRef.value?.getTree(item.api);
+};
 
-const initData = () => {
-  api.logApi.list({
-    pages: pages.value,
-    size: size.value,
-    ...form.value
-  }).then((res: any) => {
-    if(res.code === 200) {
-      tableData.value = res.data.records
-      total.value = res.data.total
-    } else {
-      ElMessage({
-        message: res.msg,
-        type: 'warning'
-      })
-    }
-  })
-}
+const tabList = ref([
+  {
+    name: "机构",
+    value: 1,
+    api: api.manageApi.getDeptListByUserId,
+  },
+  {
+    name: "人员",
+    value: 2,
+    api: api.manageApi.getUserManageListByUserId,
+  },
+]);
 
 onMounted(() => {
-  initData()
-})
-
+  initDefaultList();
+  treeRef.value?.getTree(tabList.value[0].api);
+});
 </script>
 
 <style scoped lang="scss">
-.log{
+.log {
   width: 100%;
   height: calc(100vh - 120px);
-  background: #FFFFFF;
+  background: #ffffff;
   padding: 24px;
   overflow-y: auto;
-  .pagination{
-    margin-top: 24px;
+  .query-btn {
+    margin-left: 20px;
+  }
+  .btn-box {
+    padding-bottom: 15px;
+    margin-bottom: 24px;
+    border-bottom: 1px solid #eeeeee;
     display: flex;
-    align-items: center;
     justify-content: flex-end;
   }
+
+  .content-box {
+    justify-content: space-between;
+    .content-l {
+      width: 298px;
+      display: flex;
+      margin: 20px 16px 20px 0;
+      .item {
+        width: 50%;
+        height: 36px;
+        line-height: 36px;
+        background: #f7f7f7;
+        font-size: 16px;
+        text-align: center;
+        border-radius: 2px;
+      }
+      .active {
+        background: #0083ff;
+        color: #fff;
+      }
+    }
+    .content-r {
+      width: 0;
+    }
+  }
+}
+:deep(.caret-wrapper) {
+  display: none !important;
 }
 </style>

+ 88 - 41
src/views/consoleManage/businessDataManage/companyDataManage/companyDataManageDetail.vue

@@ -11,12 +11,15 @@
 
     <!-- 表格 -->
     <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
-      :columnwidth="120" :pageInfo="pageInfo" @getList="getList" :showOperation="false">
-
+      :columnwidth="120" :pageInfo="pageInfo" @getList="getList" :showOperation='false'>
+      <template v-slot:search="scope">
+        <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+          @update:sort="handleSortUpdate"></Sort>
+      </template>
     </ComplexTable>
 
     <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
-      routerKey='companyDataManageDetail'>
+      routerKey='routerKey'>
     </FilterDialog>
   </div>
 </template>
@@ -24,111 +27,97 @@
 <script setup lang="ts">
 import { useRouter } from "vue-router";
 import api from "@/api";
-import { ElMessage } from "element-plus";
 import QueryForm from "../../components/queryForm.vue";
 import FilterDialog from "../../components/filterDialog.vue";
 import DowButton from "../../components/button.vue";
+import Sort from "../../components/sort.vue";
 import useUserStore from "@/store/modules/message";
 import PageInfo from "@/api/types/agreementTypes";
+import { ElMessage } from "element-plus";
 
 const router = useRouter();
 const userStore = useUserStore();
 const isShow = ref(false);
 
+const isSort = ref();
 const pageInfo = ref({
   pageNum: 1,
-  pageSize: 20,
+  pageSize: 10,
   sizes: [10, 20, 30, 40, 50],
   total: 0,
 });
 const listOption = reactive({
-  rowKey: "companyId",
+  rowKey: "companyDelId",
   //查询
   queryFormFields: [],
   // 表格列
   columns: [
     {
-      prop: "date",
+      prop: "companyName",
       label: "保险公司",
       width: "200",
     },
     {
-      prop: "name",
+      prop: "partnerCompanyName",
       label: "合作保险公司",
       width: "300",
     },
     {
-      prop: "address",
+      prop: "orderNo",
       label: "订单",
       width: "120",
     },
     {
-      prop: "tag",
+      prop: "licenseNo",
       label: "车牌号",
       width: "180",
     },
     {
-      prop: "tag1",
+      prop: "orderTypeName",
       label: "订单类型",
       width: "180",
     },
     {
-      prop: "tag2",
+      prop: "riskName",
       label: "险种",
       width: "180",
     },
     {
-      prop: "tag3",
+      prop: "sumPremium",
       label: "保费",
       width: "180",
       align: "right",
-      sortable: "default",
+      sortable: true,
     },
     {
-      prop: "tag4",
+      prop: "createTime",
       label: "录单时间",
       width: "180",
     },
     {
-      prop: "tag5",
+      prop: "recordTime",
       label: "签单时间",
       width: "180",
     },
   ],
 });
-const tableData = ref([
-  {
-    date: "2016-05-02",
-    name: "1222",
-    address: "123.25",
-    tag: "3222",
-  },
-  {
-    date: "2016-05-02",
-    name: "3222",
-    address: "422.352",
-    tag: "2225",
-  },
-]);
+
 const selectedKeys = ref([]);
 const selected = function (val) {
   selectedKeys.value = val;
 };
 
-//查询
-const query = (item) => {
-  console.log(item);
-};
-
 //查询数据
 const phone = JSON.parse(localStorage.getItem("userInfo")).username;
 
 //获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("companyDataManageDetail");
 const defaultList = ref();
 const pageHiddenList = ref([]); //页面不显示的数据
 const initDefaultList = async () => {
   const { data } = await api.manageApi.getSearchDefaultList({
-    routerKey: "companyDataManageDetail",
+    routerKey: routerKey.value,
     userId: phone,
   });
   listOption.queryFormFields = data.filter((e) => e.showFlag);
@@ -136,7 +125,8 @@ const initDefaultList = async () => {
   pageHiddenList.value = data.filter((e) => !e.showFlag);
   defaultList.value = data.map((e) => e.id);
   selectedKeys.value = defaultList.value;
-  queryFormRef.value?.initDefaultSaveForm();
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
 };
 
 //删除
@@ -180,18 +170,72 @@ const filterSure = (item, index) => {
   selectedKeys.value = item.list.filter((item) => item.id);
 };
 
-const isVisible = ref(false);
-const downloadFile = () => {
-  isVisible.value = true;
-  userStore.count++;
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
+
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
+
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.companyDataManageDetailPageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
 };
 
 //分页事件
 function getList(item: PageInfo) {
   pageInfo.value.pageNum = item.pageNum;
   pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.companyDataManageDetailToTask({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
+
 onMounted(() => {
   initDefaultList();
 });
@@ -215,4 +259,7 @@ onMounted(() => {
     justify-content: flex-end;
   }
 }
+:deep(.caret-wrapper) {
+  display: none !important;
+}
 </style>

+ 8 - 1
src/views/consoleManage/businessDataManage/companyDataManage/index.vue

@@ -20,6 +20,12 @@
         <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
           @update:sort="handleSortUpdate"></Sort>
       </template>
+
+      <template #customSlot="{  bodyCell: { scope, column } }">
+        <template v-if="column.prop == 'sumOrderNum'">
+          {{ scope.row.sumOrderNum }} 笔
+        </template>
+      </template>
     </ComplexTable>
 
     <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
@@ -72,6 +78,7 @@ const listOption = reactive({
       width: "120",
       align: "right",
       sortable: true,
+      component: "customSlot",
     },
     {
       prop: "sumPremium",
@@ -262,7 +269,7 @@ const agreementEdit = (id) => {
 };
 
 onMounted(() => {
- 
+  initDefaultList();
 });
 </script>
 

+ 275 - 97
src/views/consoleManage/businessDataManage/contactPersonDataManage/contactPersonDataManageDetail.vue

@@ -1,117 +1,295 @@
 <template>
-  <div class="logDetail">
-    <el-descriptions :column="2">
-      <template #title>
-        <div class="title">
-          <div class="icon">
-            <el-icon><List /></el-icon>
-          </div>
-          <p>{{ detailData?.operationContent }}</p>
-        </div>
+  <div class="log">
+    <div class='btn-box'>
+      <el-button type="primary" plain class='query-btn'
+        @click='dialogShow'>{{selectedKeys.length?`已选${selectedKeys.length}项`:'筛选条件'}}</el-button>
+      <div class='query-btn'>
+        <DowButton @endAnim='downloadFile'></DowButton>
+      </div>
+    </div>
+    <QueryForm :option="listOption" @query='query' @delSelect='delSelect' ref='queryFormRef'></QueryForm>
+
+    <!-- 表格 -->
+    <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
+      :columnwidth="120" :pageInfo="pageInfo" @getList="getList" :showOperation='false'>
+      <template v-slot:search="scope">
+        <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+          @update:sort="handleSortUpdate"></Sort>
       </template>
-      <el-descriptions-item label="操作功能:" label-align="right" align="left" label-width="100">{{ detailData?.moduleName }}</el-descriptions-item>
-      <el-descriptions-item label="操作类型:" label-align="right" align="left" label-width="100">{{ detailData?.operatorName }}</el-descriptions-item>
-      <el-descriptions-item label="操作人:" label-align="right" align="left" label-width="100">{{ detailData?.createBy }}</el-descriptions-item>
-      <el-descriptions-item label="操作时间:" label-align="right" align="left" label-width="100">{{ detailData?.createTime }}</el-descriptions-item>
-    </el-descriptions>
-    <el-row :gutter="20" class="content">
-      <el-col :span="11">
-        <p>变更前</p>
-        <div class="list">
-          <el-row class="list-item" :gutter="20" v-for="item in detailData?.compareResultList" :key="item">
-            <el-col :span="6">{{ item.name }}</el-col>
-            <el-col :span="18" style="color: #606266">{{ item.fieldContent }}</el-col>
-          </el-row>
-        </div>
-      </el-col>
-      <el-divider direction="vertical" style="height: 100%"></el-divider>
-      <el-col :span="11">
-        <p>变更后</p>
-        <div class="list">
-          <el-row class="list-item" :gutter="20" v-for="item in detailData?.compareResultList" :key="item">
-            <el-col :span="6">{{ item.name }}</el-col>
-            <el-col :span="18" style="color: #606266">{{ item.newFieldContent }}</el-col>
-          </el-row>
-        </div>
-      </el-col>
-    </el-row>
+    </ComplexTable>
+
+    <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
+      routerKey='routerKey'>
+    </FilterDialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import api from '@/api'
-import { useRoute, useRouter } from 'vue-router'
+import { useRouter } from "vue-router";
+import api from "@/api";
+import QueryForm from "../../components/queryForm.vue";
+import FilterDialog from "../../components/filterDialog.vue";
+import DowButton from "../../components/button.vue";
+import Sort from "../../components/sort.vue";
+import useUserStore from "@/store/modules/message";
+import PageInfo from "@/api/types/agreementTypes";
 import { ElMessage } from "element-plus";
 
-const myRoute = useRoute()
-const myRouter = useRouter()
-
-let detailData = ref(undefined)
-
-const initDetail = () => {
-  api.logApi.selectById(myRoute.query.id).then((res: any) => {
-    if(res.code == 200) {
-      detailData.value = res.data
-    } else {
-      ElMessage({
-        message: res.msg,
-        type: 'warning'
-      })
-    }
-  })
+const router = useRouter();
+const userStore = useUserStore();
+const isShow = ref(false);
+
+const isSort = ref();
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const listOption = reactive({
+  rowKey: "contactPersonDelId",
+  //查询
+  queryFormFields: [],
+  // 表格列
+  columns: [
+    {
+      prop: "contactPersonName",
+      label: "对接人",
+      width: "120",
+    },
+    {
+      prop: "contactPersonPhone",
+      label: "对接人手机号",
+      width: "120",
+    },
+    {
+      prop: "companyName",
+      label: "保险公司",
+      width: "120",
+    },
+    {
+      prop: "partnerCompanyName",
+      label: "合作保险公司",
+      width: "180",
+    },
+    {
+      prop: "orderNo",
+      label: "订单号",
+      width: "180",
+    },
+    {
+      prop: "licenseNo",
+      label: "车牌号",
+      width: "180",
+    },
+    {
+      prop: "orderTypeName",
+      label: "订单类型",
+      width: "120",
+    },
+    {
+      prop: "riskName",
+      label: "险种",
+      width: "100",
+    },
+    {
+      prop: "sumPremium",
+      label: "保费",
+      width: "120",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "createTime",
+      label: "录单时间",
+      width: "200",
+    },
+    {
+      prop: "recordTime",
+      label: "签单时间",
+      width: "200",
+    },
+    {
+      prop: "salesmanName",
+      label: "业务员",
+      width: "180",
+    },
+    {
+      prop: "salesmanPhone",
+      label: "手机号",
+      width: "180",
+    },
+    {
+      prop: "agreeId",
+      label: "协议编号",
+      width: "180",
+    },
+    {
+      prop: "agreeName",
+      label: "协议名称",
+      width: "180",
+    },
+  ],
+});
+
+const selectedKeys = ref([]);
+const selected = function (val) {
+  selectedKeys.value = val;
+};
+
+//查询数据
+const phone = JSON.parse(localStorage.getItem("userInfo")).username;
+
+//获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("contactPersonDataManageDetail");
+const defaultList = ref();
+const pageHiddenList = ref([]); //页面不显示的数据
+const initDefaultList = async () => {
+  const { data } = await api.manageApi.getSearchDefaultList({
+    routerKey: routerKey.value,
+    userId: phone,
+  });
+  listOption.queryFormFields = data.filter((e) => e.showFlag);
+
+  pageHiddenList.value = data.filter((e) => !e.showFlag);
+  defaultList.value = data.map((e) => e.id);
+  selectedKeys.value = defaultList.value;
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
+};
+
+//删除
+const filterDialogRef = ref();
+const delSelect = (id) => {
+  listOption.queryFormFields = listOption.queryFormFields.filter(
+    (item) => item.id != id
+  );
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//打开dialogShow
+const dialogShow = function () {
+  isShow.value = true;
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//确定
+const queryFormRef = ref();
+const filterSure = (item, index) => {
+  isShow.value = false;
+  const secondGroupIds = item.list.map((item) => item.id);
+  const oldList = listOption.queryFormFields.filter((item) =>
+    secondGroupIds.includes(item.id)
+  );
+  const firstGroupIds = listOption.queryFormFields.map((item) => item.id);
+  let newList = item.list.filter((item) => !firstGroupIds.includes(item.id));
+
+  //过滤掉默认不显示的数据
+  const hiddenList = new Set(pageHiddenList.value.map((item) => item.id));
+  const filterList = newList.filter((item) => !hiddenList.has(item.id));
+
+  listOption.queryFormFields = [...oldList, ...filterList];
+  queryFormRef.value?.initDefaultSaveForm();
+  selectedKeys.value = item.list.filter((item) => item.id);
+};
+
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
+
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
+
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.contactPersonDataManageDetailPageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
+};
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
-onMounted(() => {
-  initDetail()
-})
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.contactPersonDataManageDetailToTask({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
 
+onMounted(() => {
+  initDefaultList();
+});
 </script>
 
 <style scoped lang="scss">
-.logDetail{
-  padding: 24px;
-  background: #FFFFFF;
+.log {
   width: 100%;
   height: calc(100vh - 120px);
-  .title{
-    display: flex;
-    align-items: center;
-    justify-content: flex-start;
-    .icon{
-      width: 30px;
-      height: 30px;
-      border-radius: 50%;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      background: #1A85FA;
-      color: #FFFFFF;
-      font-size: 20px;
-      margin-right: 10px;
-    }
-  }
-  .content{
-    height: calc(100% - 120px);
-    overflow: hidden;
-    p{
-      text-align: center;
-      background: #F0F0F0;
-      margin: 0;
-      padding: 16px 0;
-    }
-    .list{
-      height: calc(100% - 80px);
-      overflow-y: auto;
-      overflow-x: hidden;
-      .list-item{
-        margin: 14px 0;
-        padding: 0 20px;
-        display: flex;
-      }
-    }
+  background: #ffffff;
+  padding: 24px;
+  overflow-y: auto;
+  .query-btn {
+    margin-left: 20px;
   }
-  :deep(.el-descriptions) {
-    width: 50%;
+  .btn-box {
+    padding-bottom: 15px;
+    margin-bottom: 24px;
+    border-bottom: 1px solid #eeeeee;
+    display: flex;
+    justify-content: flex-end;
   }
 }
+:deep(.caret-wrapper) {
+  display: none !important;
+}
 </style>

+ 275 - 140
src/views/consoleManage/businessDataManage/contactPersonDataManage/index.vue

@@ -1,170 +1,305 @@
 <template>
   <div class="log">
-    <el-form label-width="100" label-position="left" :model="form">
-      <el-row :gutter="20">
-        <el-col :span="8">
-          <el-form-item label="操作人">
-            <el-input v-model="form.operator" placeholder="请输入操作人姓名查找"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作时间">
-            <el-date-picker
-              v-model="form.operatingTime"
-              type="daterange"
-              range-separator="至"
-              start-placeholder="开始时间"
-              end-placeholder="结束时间"
-              format="YYYY-MM-DD"
-              value-format="YYYY-MM-DD"
-              @change="timeChange"
-            />
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作功能">
-            <el-select v-model="form.function" placeholder="请选择">
-              <el-option label="工能1" value="1" key="1"></el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作内容">
-            <el-input v-model="form.content" placeholder="请输入"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="16" style="display: flex; align-items: center; justify-content: flex-end">
-          <el-button type="primary" @click="search">查询</el-button>
-          <el-button plain type="primary" @click="reset">重置</el-button>
-        </el-col>
-      </el-row>
-    </el-form>
-    <el-table
-      :data="tableData"
-      height="600"
-      style="margin-top: 24px"
-    >
-      <el-table-column label="操作人" prop="createBy" width="200"></el-table-column  >
-      <el-table-column label="操作时间" prop="createTime" width="240"></el-table-column>
-      <el-table-column label="操作功能" prop="moduleName"></el-table-column>
-      <el-table-column label="操作内容" prop="operationContent"></el-table-column>
-      <el-table-column label="类型" prop="operatorName" width="150"></el-table-column>
-      <el-table-column label="操作" width="150">
-        <template #default="scope">
-          <el-button link type="primary" @click="detail(scope.row)">查看详情</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <div class="pagination">
-      <el-pagination
-        v-model:current-page="pages"
-        v-model:page-size="size"
-        :page-sizes="[10, 20, 30, 40]"
-        layout="total, sizes, prev, pager, next, jumper"
-        :total="total"
-        @size-change="handleSizeChange"
-        @current-change="handleCurrentChange"
-      ></el-pagination>
+    <div class='btn-box'>
+      <el-button type="primary" plain class='query-btn'
+        @click='dialogShow'>{{selectedKeys.length?`已选${selectedKeys.length}项`:'筛选条件'}}</el-button>
+      <div class='query-btn'>
+        <DowButton @endAnim='downloadFile'></DowButton>
+      </div>
     </div>
+    <QueryForm :option="listOption" @query='query' @delSelect='delSelect' ref='queryFormRef'></QueryForm>
+
+    <!-- 表格 -->
+    <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
+      :columnwidth="120" :pageInfo="pageInfo" @getList="getList">
+      <template v-slot:operation="scope">
+        <el-button type="primary" link @click='agreementEdit(scope.operationData.id)'>明细</el-button>
+      </template>
+      <template v-slot:search="scope">
+        <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+          @update:sort="handleSortUpdate"></Sort>
+      </template>
+
+      <template #customSlot="{  bodyCell: { scope, column } }">
+        <template v-if="column.prop == 'sumOrderNum'">
+          {{ scope.row.sumOrderNum }} 笔
+        </template>
+        <template v-if="column.prop == 'sumPersonNum'">
+          {{ scope.row.sumPersonNum }} 人
+        </template>
+        <template v-if="column.prop == 'avgPersonNumPremium'">
+          {{ scope.row.avgPersonNumPremium }} 人
+        </template>
+      </template>
+
+    </ComplexTable>
+
+    <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
+      routerKey='routerKey'>
+    </FilterDialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import { useRouter } from 'vue-router'
-import api from '@/api'
-import {ElMessage} from "element-plus";
+import { useRouter } from "vue-router";
+import api from "@/api";
+import QueryForm from "../../components/queryForm.vue";
+import FilterDialog from "../../components/filterDialog.vue";
+import DowButton from "../../components/button.vue";
+import Sort from "../../components/sort.vue";
+import useUserStore from "@/store/modules/message";
+import PageInfo from "@/api/types/agreementTypes";
+import { ElMessage } from "element-plus";
 
-const myRouter = useRouter()
+const router = useRouter();
+const userStore = useUserStore();
+const isShow = ref(false);
 
-let activeName = ref('first')
-const handleClick = () => {
+const isSort = ref();
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const listOption = reactive({
+  rowKey: "contactPersonId",
+  //查询
+  queryFormFields: [],
+  // 表格列
+  columns: [
+    {
+      prop: "contactPersonName",
+      label: "对接人",
+      width: "120",
+    },
+    {
+      prop: "contactPersonPhone",
+      label: "对接人手机号",
+      width: "120",
+    },
+    {
+      prop: "companyName",
+      label: "保险公司",
+      width: "120",
+    },
+    {
+      prop: "partnerCompanyName",
+      label: "合作保险公司",
+      width: "180",
+    },
+    {
+      prop: "agreeTypeName",
+      label: "协议类型",
+      width: "100",
+    },
+    {
+      prop: "sumOrderNum",
+      label: "订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "sumPremium",
+      label: "保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "avgOrderNumPremium",
+      label: "单均保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "sumPersonNum",
+      label: "出单人数",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "avgPersonNumPremium",
+      label: "人均保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+  ],
+});
 
-}
+const selectedKeys = ref([]);
+const selected = function (val) {
+  selectedKeys.value = val;
+};
 
-let form = ref({})
-const tableProps = ref({
-  value: "id",
-  label: "name",
-  children: "children",
-  checkStrictly: true,
-});
-let option = ref([])
-const timeChange = (val) => {
+//查询数据
+const phone = JSON.parse(localStorage.getItem("userInfo")).username;
 
-}
-// 搜索
-const search = () => {
-  pages.value = 1
-  size.value = 10
-  initData()
-}
-const reset = () => {
-  form.value = {}
-  pages.value = 1
-  size.value = 10
-  initData()
-}
+//获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("contactPersonDataManage");
+const defaultList = ref();
+const pageHiddenList = ref([]); //页面不显示的数据
+const initDefaultList = async () => {
+  const { data } = await api.manageApi.getSearchDefaultList({
+    routerKey: routerKey.value,
+    userId: phone,
+  });
+  listOption.queryFormFields = data.filter((e) => e.showFlag);
 
-// 列表
-let tableData = ref([])
-const detail = (row) => {
-  myRouter.push({
-    path: '/consoleManage/businessDataManage/contactPersonDataManage/contactPersonDataManageDetail',
-    query: {
-      id: row.id
-    }
-  })
-}
+  pageHiddenList.value = data.filter((e) => !e.showFlag);
+  defaultList.value = data.map((e) => e.id);
+  selectedKeys.value = defaultList.value;
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
+};
 
-// 分页
-let pages = ref(1)
-let size = ref(10)
-let total = ref(0)
-const handleSizeChange = (size) => {
-  size.value = size
-  initData()
-}
-const handleCurrentChange = (page) => {
-  pages.value = page
-  initData()
-}
+//删除
+const filterDialogRef = ref();
+const delSelect = (id) => {
+  listOption.queryFormFields = listOption.queryFormFields.filter(
+    (item) => item.id != id
+  );
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//打开dialogShow
+const dialogShow = function () {
+  isShow.value = true;
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//确定
+const queryFormRef = ref();
+const filterSure = (item, index) => {
+  isShow.value = false;
+  const secondGroupIds = item.list.map((item) => item.id);
+  const oldList = listOption.queryFormFields.filter((item) =>
+    secondGroupIds.includes(item.id)
+  );
+  const firstGroupIds = listOption.queryFormFields.map((item) => item.id);
+  let newList = item.list.filter((item) => !firstGroupIds.includes(item.id));
+
+  //过滤掉默认不显示的数据
+  const hiddenList = new Set(pageHiddenList.value.map((item) => item.id));
+  const filterList = newList.filter((item) => !hiddenList.has(item.id));
+
+  listOption.queryFormFields = [...oldList, ...filterList];
+  queryFormRef.value?.initDefaultSaveForm();
+  selectedKeys.value = item.list.filter((item) => item.id);
+};
+
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
 
-const initData = () => {
-  api.logApi.list({
-    pages: pages.value,
-    size: size.value,
-    ...form.value
-  }).then((res: any) => {
-    if(res.code === 200) {
-      tableData.value = res.data.records
-      total.value = res.data.total
-    } else {
-      ElMessage({
-        message: res.msg,
-        type: 'warning'
-      })
-    }
-  })
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
+
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.contactPersonDataManagePageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
+};
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
-onMounted(() => {
-  initData()
-})
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.contactPersonDataManageToTask({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
+const agreementEdit = (id) => {
+  router.push({
+    name: "contactPersonDataManageDetail",
+    query: {
+      id: id,
+    },
+  });
+};
 
+onMounted(() => {
+  initDefaultList();
+});
 </script>
 
 <style scoped lang="scss">
-.log{
+.log {
   width: 100%;
   height: calc(100vh - 120px);
-  background: #FFFFFF;
+  background: #ffffff;
   padding: 24px;
   overflow-y: auto;
-  .pagination{
-    margin-top: 24px;
+  .query-btn {
+    margin-left: 20px;
+  }
+  .btn-box {
+    padding-bottom: 15px;
+    margin-bottom: 24px;
+    border-bottom: 1px solid #eeeeee;
     display: flex;
-    align-items: center;
     justify-content: flex-end;
   }
 }
+:deep(.caret-wrapper) {
+  display: none !important;
+}
 </style>

+ 281 - 140
src/views/consoleManage/businessDataManage/riskDataManage/index.vue

@@ -1,170 +1,311 @@
 <template>
   <div class="log">
-    <el-form label-width="100" label-position="left" :model="form">
-      <el-row :gutter="20">
-        <el-col :span="8">
-          <el-form-item label="操作人">
-            <el-input v-model="form.operator" placeholder="请输入操作人姓名查找"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作时间">
-            <el-date-picker
-              v-model="form.operatingTime"
-              type="daterange"
-              range-separator="至"
-              start-placeholder="开始时间"
-              end-placeholder="结束时间"
-              format="YYYY-MM-DD"
-              value-format="YYYY-MM-DD"
-              @change="timeChange"
-            />
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作功能">
-            <el-select v-model="form.function" placeholder="请选择">
-              <el-option label="工能1" value="1" key="1"></el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作内容">
-            <el-input v-model="form.content" placeholder="请输入"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="16" style="display: flex; align-items: center; justify-content: flex-end">
-          <el-button type="primary" @click="search">查询</el-button>
-          <el-button plain type="primary" @click="reset">重置</el-button>
-        </el-col>
-      </el-row>
-    </el-form>
-    <el-table
-      :data="tableData"
-      height="600"
-      style="margin-top: 24px"
-    >
-      <el-table-column label="操作人" prop="createBy" width="200"></el-table-column  >
-      <el-table-column label="操作时间" prop="createTime" width="240"></el-table-column>
-      <el-table-column label="操作功能" prop="moduleName"></el-table-column>
-      <el-table-column label="操作内容" prop="operationContent"></el-table-column>
-      <el-table-column label="类型" prop="operatorName" width="150"></el-table-column>
-      <el-table-column label="操作" width="150">
-        <template #default="scope">
-          <el-button link type="primary" @click="detail(scope.row)">查看详情</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <div class="pagination">
-      <el-pagination
-        v-model:current-page="pages"
-        v-model:page-size="size"
-        :page-sizes="[10, 20, 30, 40]"
-        layout="total, sizes, prev, pager, next, jumper"
-        :total="total"
-        @size-change="handleSizeChange"
-        @current-change="handleCurrentChange"
-      ></el-pagination>
+    <div class='btn-box'>
+      <el-button type="primary" plain class='query-btn'
+        @click='dialogShow'>{{selectedKeys.length?`已选${selectedKeys.length}项`:'筛选条件'}}</el-button>
+      <div class='query-btn'>
+        <DowButton @endAnim='downloadFile'></DowButton>
+      </div>
     </div>
+    <QueryForm :option="listOption" @query='query' @delSelect='delSelect' ref='queryFormRef'></QueryForm>
+
+    <!-- 表格 -->
+    <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
+      :columnwidth="120" :pageInfo="pageInfo" @getList="getList">
+      <template v-slot:operation="scope">
+        <el-button type="primary" link @click='agreementEdit(scope.operationData.id)'>明细</el-button>
+      </template>
+
+      <template v-slot:search="scope">
+        <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+          @update:sort="handleSortUpdate"></Sort>
+      </template>
+
+      <template #customSlot="{  bodyCell: { scope, column } }">
+        <template v-if="column.prop == 'quoteCountNum'">
+          {{ scope.row.quoteCountNum }} 次
+        </template>
+        <template v-if="column.prop == 'quoteOrderNum'">
+          {{ scope.row.quoteOrderNum }} 笔
+        </template>
+        <template v-if="column.prop == 'underwriteOrderNum'">
+          {{ scope.row.underwriteOrderNum }} 笔
+        </template>
+        <template v-if="column.prop == 'penetrationRate'">
+          {{ scope.row.penetrationRate }} %
+        </template>
+        <template v-if="column.prop == 'underwriteRate'">
+          {{ scope.row.underwriteRate }} %
+        </template>
+      </template>
+    </ComplexTable>
+
+    <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
+      routerKey='routerKey'>
+    </FilterDialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import { useRouter } from 'vue-router'
-import api from '@/api'
-import {ElMessage} from "element-plus";
+import { useRouter } from "vue-router";
+import api from "@/api";
+import QueryForm from "../../components/queryForm.vue";
+import FilterDialog from "../../components/filterDialog.vue";
+import DowButton from "../../components/button.vue";
+import Sort from "../../components/sort.vue";
+import useUserStore from "@/store/modules/message";
+import PageInfo from "@/api/types/agreementTypes";
+import { ElMessage } from "element-plus";
 
-const myRouter = useRouter()
+const router = useRouter();
+const userStore = useUserStore();
+const isShow = ref(false);
 
-let activeName = ref('first')
-const handleClick = () => {
+const isSort = ref();
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const listOption = reactive({
+  rowKey: "riskId",
+  //查询
+  queryFormFields: [],
+  // 表格列
+  columns: [
+    {
+      prop: "companyName",
+      label: "保险公司",
+      width: "200",
+    },
+    {
+      prop: "partnerCompanyName",
+      label: "合作保险公司",
+      width: "300",
+    },
+    {
+      prop: "riskName",
+      label: "险种",
+      width: "120",
+    },
+    {
+      prop: "quoteCountNum",
+      label: "报价次数",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "quoteOrderNum",
+      label: "报价单数",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "underwriteOrderNum",
+      label: "承保订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "underwritePremium",
+      label: "承保保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "penetrationRate",
+      label: "渗透率",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "underwriteRate",
+      label: "承保率",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+  ],
+});
 
-}
+const selectedKeys = ref([]);
+const selected = function (val) {
+  selectedKeys.value = val;
+};
 
-let form = ref({})
-const tableProps = ref({
-  value: "id",
-  label: "name",
-  children: "children",
-  checkStrictly: true,
-});
-let option = ref([])
-const timeChange = (val) => {
+//查询数据
+const phone = JSON.parse(localStorage.getItem("userInfo")).username;
 
-}
-// 搜索
-const search = () => {
-  pages.value = 1
-  size.value = 10
-  initData()
-}
-const reset = () => {
-  form.value = {}
-  pages.value = 1
-  size.value = 10
-  initData()
-}
+//获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("riskDataManage");
+const defaultList = ref();
+const pageHiddenList = ref([]); //页面不显示的数据
+const initDefaultList = async () => {
+  const { data } = await api.manageApi.getSearchDefaultList({
+    routerKey: routerKey.value,
+    userId: phone,
+  });
+  listOption.queryFormFields = data.filter((e) => e.showFlag);
 
-// 列表
-let tableData = ref([])
-const detail = (row) => {
-  myRouter.push({
-    path: '/consoleManage/businessDataManage/riskDataManage/riskDataManageDetail',
-    query: {
-      id: row.id
-    }
-  })
-}
+  pageHiddenList.value = data.filter((e) => !e.showFlag);
+  defaultList.value = data.map((e) => e.id);
+  selectedKeys.value = defaultList.value;
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
+};
 
-// 分页
-let pages = ref(1)
-let size = ref(10)
-let total = ref(0)
-const handleSizeChange = (size) => {
-  size.value = size
-  initData()
-}
-const handleCurrentChange = (page) => {
-  pages.value = page
-  initData()
-}
+//删除
+const filterDialogRef = ref();
+const delSelect = (id) => {
+  listOption.queryFormFields = listOption.queryFormFields.filter(
+    (item) => item.id != id
+  );
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//打开dialogShow
+const dialogShow = function () {
+  isShow.value = true;
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//确定
+const queryFormRef = ref();
+const filterSure = (item, index) => {
+  isShow.value = false;
+  const secondGroupIds = item.list.map((item) => item.id);
+  const oldList = listOption.queryFormFields.filter((item) =>
+    secondGroupIds.includes(item.id)
+  );
+  const firstGroupIds = listOption.queryFormFields.map((item) => item.id);
+  let newList = item.list.filter((item) => !firstGroupIds.includes(item.id));
+
+  //过滤掉默认不显示的数据
+  const hiddenList = new Set(pageHiddenList.value.map((item) => item.id));
+  const filterList = newList.filter((item) => !hiddenList.has(item.id));
+
+  listOption.queryFormFields = [...oldList, ...filterList];
+  queryFormRef.value?.initDefaultSaveForm();
+  selectedKeys.value = item.list.filter((item) => item.id);
+};
+
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
+
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
 
-const initData = () => {
-  api.logApi.list({
-    pages: pages.value,
-    size: size.value,
-    ...form.value
-  }).then((res: any) => {
-    if(res.code === 200) {
-      tableData.value = res.data.records
-      total.value = res.data.total
-    } else {
-      ElMessage({
-        message: res.msg,
-        type: 'warning'
-      })
-    }
-  })
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.riskDataManagePageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
+};
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
-onMounted(() => {
-  initData()
-})
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.riskDataManageToTask({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
+
+const agreementEdit = (id) => {
+  router.push({
+    name: "riskDataManageDetail",
+    query: {
+      id: id,
+    },
+  });
+};
 
+onMounted(() => {
+  initDefaultList();
+});
 </script>
 
 <style scoped lang="scss">
-.log{
+.log {
   width: 100%;
   height: calc(100vh - 120px);
-  background: #FFFFFF;
+  background: #ffffff;
   padding: 24px;
   overflow-y: auto;
-  .pagination{
-    margin-top: 24px;
+  .query-btn {
+    margin-left: 20px;
+  }
+  .btn-box {
+    padding-bottom: 15px;
+    margin-bottom: 24px;
+    border-bottom: 1px solid #eeeeee;
     display: flex;
-    align-items: center;
     justify-content: flex-end;
   }
 }
+:deep(.caret-wrapper) {
+  display: none !important;
+}
 </style>

+ 261 - 97
src/views/consoleManage/businessDataManage/riskDataManage/riskDataManageDetail.vue

@@ -1,117 +1,281 @@
 <template>
-  <div class="logDetail">
-    <el-descriptions :column="2">
-      <template #title>
-        <div class="title">
-          <div class="icon">
-            <el-icon><List /></el-icon>
-          </div>
-          <p>{{ detailData?.operationContent }}</p>
-        </div>
+  <div class="log">
+    <div class='btn-box'>
+      <el-button type="primary" plain class='query-btn'
+        @click='dialogShow'>{{selectedKeys.length?`已选${selectedKeys.length}项`:'筛选条件'}}</el-button>
+      <div class='query-btn'>
+        <DowButton @endAnim='downloadFile'></DowButton>
+      </div>
+    </div>
+    <QueryForm :option="listOption" @query='query' @delSelect='delSelect' ref='queryFormRef'></QueryForm>
+
+    <!-- 表格 -->
+    <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
+      :columnwidth="120" :pageInfo="pageInfo" @getList="getList" :showOperation='false'>
+
+      <template v-slot:search="scope">
+        <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+          @update:sort="handleSortUpdate"></Sort>
       </template>
-      <el-descriptions-item label="操作功能:" label-align="right" align="left" label-width="100">{{ detailData?.moduleName }}</el-descriptions-item>
-      <el-descriptions-item label="操作类型:" label-align="right" align="left" label-width="100">{{ detailData?.operatorName }}</el-descriptions-item>
-      <el-descriptions-item label="操作人:" label-align="right" align="left" label-width="100">{{ detailData?.createBy }}</el-descriptions-item>
-      <el-descriptions-item label="操作时间:" label-align="right" align="left" label-width="100">{{ detailData?.createTime }}</el-descriptions-item>
-    </el-descriptions>
-    <el-row :gutter="20" class="content">
-      <el-col :span="11">
-        <p>变更前</p>
-        <div class="list">
-          <el-row class="list-item" :gutter="20" v-for="item in detailData?.compareResultList" :key="item">
-            <el-col :span="6">{{ item.name }}</el-col>
-            <el-col :span="18" style="color: #606266">{{ item.fieldContent }}</el-col>
-          </el-row>
-        </div>
-      </el-col>
-      <el-divider direction="vertical" style="height: 100%"></el-divider>
-      <el-col :span="11">
-        <p>变更后</p>
-        <div class="list">
-          <el-row class="list-item" :gutter="20" v-for="item in detailData?.compareResultList" :key="item">
-            <el-col :span="6">{{ item.name }}</el-col>
-            <el-col :span="18" style="color: #606266">{{ item.newFieldContent }}</el-col>
-          </el-row>
-        </div>
-      </el-col>
-    </el-row>
+
+    </ComplexTable>
+
+    <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
+      routerKey='routerKey'>
+    </FilterDialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import api from '@/api'
-import { useRoute, useRouter } from 'vue-router'
+import { useRouter } from "vue-router";
+import api from "@/api";
+import QueryForm from "../../components/queryForm.vue";
+import FilterDialog from "../../components/filterDialog.vue";
+import DowButton from "../../components/button.vue";
+import Sort from "../../components/sort.vue";
+import useUserStore from "@/store/modules/message";
+import PageInfo from "@/api/types/agreementTypes";
 import { ElMessage } from "element-plus";
 
-const myRoute = useRoute()
-const myRouter = useRouter()
-
-let detailData = ref(undefined)
-
-const initDetail = () => {
-  api.logApi.selectById(myRoute.query.id).then((res: any) => {
-    if(res.code == 200) {
-      detailData.value = res.data
-    } else {
-      ElMessage({
-        message: res.msg,
-        type: 'warning'
-      })
-    }
-  })
+const router = useRouter();
+const userStore = useUserStore();
+const isShow = ref(false);
+
+const isSort = ref();
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const listOption = reactive({
+  rowKey: "riskDelId",
+  //查询
+  queryFormFields: [],
+  // 表格列
+  columns: [
+    {
+      prop: "companyName",
+      label: "保险公司",
+      width: "200",
+    },
+    {
+      prop: "partnerCompanyName",
+      label: "合作保险公司",
+      width: "300",
+    },
+    {
+      prop: "orderNo",
+      label: "订单号",
+      width: "120",
+    },
+    {
+      prop: "licenseNo",
+      label: "车牌号",
+      width: "180",
+    },
+    {
+      prop: "orderTypeName",
+      label: "订单类型",
+      width: "180",
+    },
+    {
+      prop: "riskName",
+      label: "险种",
+      width: "180",
+    },
+    {
+      prop: "quoteCountNum",
+      label: "报价次数",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "sumPremium",
+      label: "保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "orderStatusName",
+      label: "状态",
+      width: "180",
+    },
+    {
+      prop: "createTime",
+      label: "录单时间",
+      width: "180",
+    },
+    {
+      prop: "recordTime",
+      label: "签单时间",
+      width: "180",
+    },
+  ],
+});
+
+const selectedKeys = ref([]);
+const selected = function (val) {
+  selectedKeys.value = val;
+};
+
+//查询数据
+const phone = JSON.parse(localStorage.getItem("userInfo")).username;
+
+//获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("riskDataManageDetail");
+const defaultList = ref();
+const pageHiddenList = ref([]); //页面不显示的数据
+const initDefaultList = async () => {
+  const { data } = await api.manageApi.getSearchDefaultList({
+    routerKey: routerKey.value,
+    userId: phone,
+  });
+  listOption.queryFormFields = data.filter((e) => e.showFlag);
+
+  pageHiddenList.value = data.filter((e) => !e.showFlag);
+  defaultList.value = data.map((e) => e.id);
+  selectedKeys.value = defaultList.value;
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
+};
+
+//删除
+const filterDialogRef = ref();
+const delSelect = (id) => {
+  listOption.queryFormFields = listOption.queryFormFields.filter(
+    (item) => item.id != id
+  );
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//打开dialogShow
+const dialogShow = function () {
+  isShow.value = true;
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//确定
+const queryFormRef = ref();
+const filterSure = (item, index) => {
+  isShow.value = false;
+  const secondGroupIds = item.list.map((item) => item.id);
+  const oldList = listOption.queryFormFields.filter((item) =>
+    secondGroupIds.includes(item.id)
+  );
+  const firstGroupIds = listOption.queryFormFields.map((item) => item.id);
+  let newList = item.list.filter((item) => !firstGroupIds.includes(item.id));
+
+  //过滤掉默认不显示的数据
+  const hiddenList = new Set(pageHiddenList.value.map((item) => item.id));
+  const filterList = newList.filter((item) => !hiddenList.has(item.id));
+
+  listOption.queryFormFields = [...oldList, ...filterList];
+  queryFormRef.value?.initDefaultSaveForm();
+  selectedKeys.value = item.list.filter((item) => item.id);
+};
+
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
+
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
+
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.riskDataManageDetailPageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
+};
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
-onMounted(() => {
-  initDetail()
-})
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.riskDataManageDetailToPage({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
+
+
 
+onMounted(() => {
+  initDefaultList();
+});
 </script>
 
 <style scoped lang="scss">
-.logDetail{
-  padding: 24px;
-  background: #FFFFFF;
+.log {
   width: 100%;
   height: calc(100vh - 120px);
-  .title{
-    display: flex;
-    align-items: center;
-    justify-content: flex-start;
-    .icon{
-      width: 30px;
-      height: 30px;
-      border-radius: 50%;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      background: #1A85FA;
-      color: #FFFFFF;
-      font-size: 20px;
-      margin-right: 10px;
-    }
-  }
-  .content{
-    height: calc(100% - 120px);
-    overflow: hidden;
-    p{
-      text-align: center;
-      background: #F0F0F0;
-      margin: 0;
-      padding: 16px 0;
-    }
-    .list{
-      height: calc(100% - 80px);
-      overflow-y: auto;
-      overflow-x: hidden;
-      .list-item{
-        margin: 14px 0;
-        padding: 0 20px;
-        display: flex;
-      }
-    }
+  background: #ffffff;
+  padding: 24px;
+  overflow-y: auto;
+  .query-btn {
+    margin-left: 20px;
   }
-  :deep(.el-descriptions) {
-    width: 50%;
+  .btn-box {
+    padding-bottom: 15px;
+    margin-bottom: 24px;
+    border-bottom: 1px solid #eeeeee;
+    display: flex;
+    justify-content: flex-end;
   }
 }
+:deep(.caret-wrapper) {
+  display: none !important;
+}
 </style>

+ 206 - 67
src/views/consoleManage/businessDataManage/salesmanDataManage/index.vue

@@ -8,7 +8,6 @@
       </div>
     </div>
     <QueryForm :option="listOption" @query='query' @delSelect='delSelect' ref='queryFormRef'></QueryForm>
-
     <div class='flex content-box'>
       <!-- tree -->
       <div>
@@ -21,16 +20,45 @@
         <Tree ref='treeRef'></Tree>
       </div>
 
-      <!-- 表格 -->
       <div class='flex-1 content-r'>
+        <!-- 表格 -->
         <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
-          :columnwidth="120" :pageInfo="pageInfo" @getList="getList" :showOperation="false">
+          :columnwidth="120" :pageInfo="pageInfo" @getList="getList">
+          <template v-slot:operation="scope">
+            <el-button type="primary" link @click='agreementEdit(scope.operationData.id)'>明细</el-button>
+          </template>
+
+          <template v-slot:search="scope">
+            <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+              @update:sort="handleSortUpdate"></Sort>
+          </template>
+
+          <template #customSlot="{  bodyCell: { scope, column } }">
+            <template v-if="column.prop == 'underwriteOrderNum'">
+              {{ scope.row.underwriteOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'djOrderNum'">
+              {{ scope.row.djOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dsyOrderNum'">
+              {{ scope.row.dsyOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dszOrderNum'">
+              {{ scope.row.dszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jszOrderNum'">
+              {{ scope.row.jszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jsyOrderNum'">
+              {{ scope.row.jsyOrderNum }} 笔
+            </template>
+          </template>
         </ComplexTable>
       </div>
     </div>
 
     <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
-      routerKey='salesmanDataManage'>
+      routerKey='routerKey'>
     </FilterDialog>
   </div>
 </template>
@@ -38,132 +66,163 @@
 <script setup lang="ts">
 import { useRouter } from "vue-router";
 import api from "@/api";
-import { ElMessage } from "element-plus";
 import QueryForm from "../../components/queryForm.vue";
 import FilterDialog from "../../components/filterDialog.vue";
 import DowButton from "../../components/button.vue";
-import Tree from "../../components/tree.vue";
+import Sort from "../../components/sort.vue";
 import useUserStore from "@/store/modules/message";
 import PageInfo from "@/api/types/agreementTypes";
+import Tree from "../../components/tree.vue";
+import { ElMessage } from "element-plus";
 
-const tabList = ref([
-  {
-    name: "机构",
-    value: 1,
-    api: api.manageApi.getDeptListByUserId,
-  },
-  {
-    name: "人员",
-    value: 2,
-    api: api.manageApi.getUserManageListByUserId,
-  },
-]);
-const tabIndex = ref(0);
 const router = useRouter();
 const userStore = useUserStore();
 const isShow = ref(false);
 
+const isSort = ref();
 const pageInfo = ref({
   pageNum: 1,
-  pageSize: 20,
+  pageSize: 10,
   sizes: [10, 20, 30, 40, 50],
   total: 0,
 });
 const listOption = reactive({
-  rowKey: "salesId",
+  rowKey: "salesmanId",
   //查询
   queryFormFields: [],
   // 表格列
   columns: [
     {
-      prop: "date",
-      label: "保险公司",
-      width: "200",
+      prop: "salesmanName",
+      label: "姓名",
+      width: "100",
+    },
+    {
+      prop: "salesmanPhone",
+      label: "手机号",
+      width: "120",
     },
     {
-      prop: "name",
-      label: "合作保险公司",
+      prop: "deptName",
+      label: "所属机构",
       width: "300",
     },
     {
-      prop: "address",
-      label: "订单",
-      width: "120",
+      prop: "underwriteOrderNum",
+      label: "承保订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
     },
     {
-      prop: "tag",
-      label: "车牌号",
+      prop: "sumPremium",
+      label: "保费",
       width: "180",
+      align: "right",
+      sortable: true,
     },
     {
-      prop: "tag",
-      label: "订单类型",
+      prop: "jqPremium",
+      label: "交强保费",
       width: "180",
+      align: "right",
+      sortable: true,
     },
     {
-      prop: "tag",
-      label: "险种",
+      prop: "taxPremium",
+      label: "车船税",
       width: "180",
+      align: "right",
+      sortable: true,
     },
     {
-      prop: "tag",
-      label: "保费",
+      prop: "syPremium",
+      label: "商业保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "jyPremium",
+      label: "驾意保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "单交订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "dsyOrderNum",
+      label: "单商订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "dszOrderNum",
+      label: "单三订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "jszOrderNum",
+      label: "交三订单",
       width: "180",
       align: "right",
-      sortable: "default",
+      sortable: true,
+      component: "customSlot",
     },
     {
-      prop: "tag",
-      label: "录单时间",
+      prop: "jsyOrderNum",
+      label: "交商订单",
       width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
     },
     {
-      prop: "tag",
-      label: "签单时间",
+      prop: "manegerName",
+      label: "管理人",
       width: "180",
     },
   ],
 });
-const tableData = ref([
-  {
-    date: "2016-05-02",
-    name: "1222",
-    address: "123.25",
-    tag: "3222",
-  },
-  {
-    date: "2016-05-02",
-    name: "3222",
-    address: "422.352",
-    tag: "2225",
-  },
-]);
+
 const selectedKeys = ref([]);
 const selected = function (val) {
   selectedKeys.value = val;
 };
 
-//查询
-const query = (item) => {
-  console.log(item);
-};
-
 //查询数据
 const phone = JSON.parse(localStorage.getItem("userInfo")).username;
 
 //获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("salesmanDataManage");
 const defaultList = ref();
 const pageHiddenList = ref([]); //页面不显示的数据
 const initDefaultList = async () => {
   const { data } = await api.manageApi.getSearchDefaultList({
-    routerKey: "salesmanDataManage",
+    routerKey: routerKey.value,
     userId: phone,
   });
   listOption.queryFormFields = data.filter((e) => e.showFlag);
+
   pageHiddenList.value = data.filter((e) => !e.showFlag);
   defaultList.value = data.map((e) => e.id);
   selectedKeys.value = defaultList.value;
-  queryFormRef.value?.initDefaultSaveForm();
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
 };
 
 //删除
@@ -207,25 +266,102 @@ const filterSure = (item, index) => {
   selectedKeys.value = item.list.filter((item) => item.id);
 };
 
-const isVisible = ref(false);
-const downloadFile = () => {
-  isVisible.value = true;
-  userStore.count++;
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
+
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
+
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.salesmanDataManagePageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
 };
 
 //分页事件
 function getList(item: PageInfo) {
   pageInfo.value.pageNum = item.pageNum;
   pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.salesmanDataManageToTask({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
+
+const agreementEdit = (id) => {
+  router.push({
+    name: "salesmanDataManageDetail",
+    query: {
+      id: id,
+    },
+  });
+};
+
 //tabClick
 const treeRef = ref();
+const tabIndex = ref(0);
 const tabClick = (item, index) => {
   tabIndex.value = index;
   treeRef.value?.getTree(item.api);
 };
 
+const tabList = ref([
+  {
+    name: "机构",
+    value: 1,
+    api: api.manageApi.getDeptListByUserId,
+  },
+  {
+    name: "人员",
+    value: 2,
+    api: api.manageApi.getUserManageListByUserId,
+  },
+]);
+
 onMounted(() => {
   initDefaultList();
   treeRef.value?.getTree(tabList.value[0].api);
@@ -275,4 +411,7 @@ onMounted(() => {
     }
   }
 }
+:deep(.caret-wrapper) {
+  display: none !important;
+}
 </style>

+ 269 - 97
src/views/consoleManage/businessDataManage/salesmanDataManage/salesmanDataManageDetail.vue

@@ -1,117 +1,289 @@
 <template>
-  <div class="logDetail">
-    <el-descriptions :column="2">
-      <template #title>
-        <div class="title">
-          <div class="icon">
-            <el-icon><List /></el-icon>
-          </div>
-          <p>{{ detailData?.operationContent }}</p>
-        </div>
+  <div class="log">
+    <div class='btn-box'>
+      <el-button type="primary" plain class='query-btn'
+        @click='dialogShow'>{{selectedKeys.length?`已选${selectedKeys.length}项`:'筛选条件'}}</el-button>
+      <div class='query-btn'>
+        <DowButton @endAnim='downloadFile'></DowButton>
+      </div>
+    </div>
+    <QueryForm :option="listOption" @query='query' @delSelect='delSelect' ref='queryFormRef'></QueryForm>
+
+    <!-- 表格 -->
+    <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
+      :columnwidth="120" :pageInfo="pageInfo" @getList="getList" :showOperation='false'>
+
+      <template v-slot:search="scope">
+        <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+          @update:sort="handleSortUpdate"></Sort>
       </template>
-      <el-descriptions-item label="操作功能:" label-align="right" align="left" label-width="100">{{ detailData?.moduleName }}</el-descriptions-item>
-      <el-descriptions-item label="操作类型:" label-align="right" align="left" label-width="100">{{ detailData?.operatorName }}</el-descriptions-item>
-      <el-descriptions-item label="操作人:" label-align="right" align="left" label-width="100">{{ detailData?.createBy }}</el-descriptions-item>
-      <el-descriptions-item label="操作时间:" label-align="right" align="left" label-width="100">{{ detailData?.createTime }}</el-descriptions-item>
-    </el-descriptions>
-    <el-row :gutter="20" class="content">
-      <el-col :span="11">
-        <p>变更前</p>
-        <div class="list">
-          <el-row class="list-item" :gutter="20" v-for="item in detailData?.compareResultList" :key="item">
-            <el-col :span="6">{{ item.name }}</el-col>
-            <el-col :span="18" style="color: #606266">{{ item.fieldContent }}</el-col>
-          </el-row>
-        </div>
-      </el-col>
-      <el-divider direction="vertical" style="height: 100%"></el-divider>
-      <el-col :span="11">
-        <p>变更后</p>
-        <div class="list">
-          <el-row class="list-item" :gutter="20" v-for="item in detailData?.compareResultList" :key="item">
-            <el-col :span="6">{{ item.name }}</el-col>
-            <el-col :span="18" style="color: #606266">{{ item.newFieldContent }}</el-col>
-          </el-row>
-        </div>
-      </el-col>
-    </el-row>
+
+    </ComplexTable>
+
+    <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
+      routerKey='routerKey'>
+    </FilterDialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import api from '@/api'
-import { useRoute, useRouter } from 'vue-router'
+import { useRouter } from "vue-router";
+import api from "@/api";
+import QueryForm from "../../components/queryForm.vue";
+import FilterDialog from "../../components/filterDialog.vue";
+import DowButton from "../../components/button.vue";
+import Sort from "../../components/sort.vue";
+import useUserStore from "@/store/modules/message";
+import PageInfo from "@/api/types/agreementTypes";
 import { ElMessage } from "element-plus";
 
-const myRoute = useRoute()
-const myRouter = useRouter()
-
-let detailData = ref(undefined)
-
-const initDetail = () => {
-  api.logApi.selectById(myRoute.query.id).then((res: any) => {
-    if(res.code == 200) {
-      detailData.value = res.data
-    } else {
-      ElMessage({
-        message: res.msg,
-        type: 'warning'
-      })
-    }
-  })
+const router = useRouter();
+const userStore = useUserStore();
+const isShow = ref(false);
+
+const isSort = ref();
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const listOption = reactive({
+  rowKey: "salesmanDelId",
+  //查询
+  queryFormFields: [],
+  // 表格列
+  columns: [
+    {
+      prop: "salesmanName",
+      label: "业务员",
+      width: "200",
+    },
+    {
+      prop: "salesmanPhone",
+      label: "手机号",
+      width: "120",
+    },
+    {
+      prop: "companyId",
+      label: "保险公司",
+      width: "200",
+    },
+    {
+      prop: "companyName",
+      label: "合作保险公司",
+      width: "300",
+    },
+    {
+      prop: "orderNo",
+      label: "订单号",
+      width: "180",
+    },
+    {
+      prop: "licenseNo",
+      label: "车牌号",
+      width: "180",
+    },
+    {
+      prop: "orderTypeName",
+      label: "订单类型",
+      width: "180",
+    },
+    {
+      prop: "riskName",
+      label: "险种",
+      width: "180",
+    },
+    {
+      prop: "quoteCountNum",
+      label: "报价次数",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "sumPremium",
+      label: "保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "createTime",
+      label: "录单时间",
+      width: "180",
+    },
+    {
+      prop: "recordTime",
+      label: "签单时间",
+      width: "180",
+    },
+    {
+      prop: "manegerName",
+      label: "管理人",
+      width: "180",
+    },
+  ],
+});
+
+const selectedKeys = ref([]);
+const selected = function (val) {
+  selectedKeys.value = val;
+};
+
+//查询数据
+const phone = JSON.parse(localStorage.getItem("userInfo")).username;
+
+//获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("salesmanDataManageDetail");
+const defaultList = ref();
+const pageHiddenList = ref([]); //页面不显示的数据
+const initDefaultList = async () => {
+  const { data } = await api.manageApi.getSearchDefaultList({
+    routerKey: routerKey.value,
+    userId: phone,
+  });
+  listOption.queryFormFields = data.filter((e) => e.showFlag);
+
+  pageHiddenList.value = data.filter((e) => !e.showFlag);
+  defaultList.value = data.map((e) => e.id);
+  selectedKeys.value = defaultList.value;
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
+};
+
+//删除
+const filterDialogRef = ref();
+const delSelect = (id) => {
+  listOption.queryFormFields = listOption.queryFormFields.filter(
+    (item) => item.id != id
+  );
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//打开dialogShow
+const dialogShow = function () {
+  isShow.value = true;
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//确定
+const queryFormRef = ref();
+const filterSure = (item, index) => {
+  isShow.value = false;
+  const secondGroupIds = item.list.map((item) => item.id);
+  const oldList = listOption.queryFormFields.filter((item) =>
+    secondGroupIds.includes(item.id)
+  );
+  const firstGroupIds = listOption.queryFormFields.map((item) => item.id);
+  let newList = item.list.filter((item) => !firstGroupIds.includes(item.id));
+
+  //过滤掉默认不显示的数据
+  const hiddenList = new Set(pageHiddenList.value.map((item) => item.id));
+  const filterList = newList.filter((item) => !hiddenList.has(item.id));
+
+  listOption.queryFormFields = [...oldList, ...filterList];
+  queryFormRef.value?.initDefaultSaveForm();
+  selectedKeys.value = item.list.filter((item) => item.id);
+};
+
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
+
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
+
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.salesmanDataManageDetailPageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
+};
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
-onMounted(() => {
-  initDetail()
-})
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.salesmanDataManageDetailToTask({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
 
+onMounted(() => {
+  initDefaultList();
+});
 </script>
 
 <style scoped lang="scss">
-.logDetail{
-  padding: 24px;
-  background: #FFFFFF;
+.log {
   width: 100%;
   height: calc(100vh - 120px);
-  .title{
-    display: flex;
-    align-items: center;
-    justify-content: flex-start;
-    .icon{
-      width: 30px;
-      height: 30px;
-      border-radius: 50%;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      background: #1A85FA;
-      color: #FFFFFF;
-      font-size: 20px;
-      margin-right: 10px;
-    }
-  }
-  .content{
-    height: calc(100% - 120px);
-    overflow: hidden;
-    p{
-      text-align: center;
-      background: #F0F0F0;
-      margin: 0;
-      padding: 16px 0;
-    }
-    .list{
-      height: calc(100% - 80px);
-      overflow-y: auto;
-      overflow-x: hidden;
-      .list-item{
-        margin: 14px 0;
-        padding: 0 20px;
-        display: flex;
-      }
-    }
+  background: #ffffff;
+  padding: 24px;
+  overflow-y: auto;
+  .query-btn {
+    margin-left: 20px;
   }
-  :deep(.el-descriptions) {
-    width: 50%;
+  .btn-box {
+    padding-bottom: 15px;
+    margin-bottom: 24px;
+    border-bottom: 1px solid #eeeeee;
+    display: flex;
+    justify-content: flex-end;
   }
 }
+:deep(.caret-wrapper) {
+  display: none !important;
+}
 </style>

+ 386 - 139
src/views/consoleManage/businessDataManage/telemarketingDataManage/index.vue

@@ -1,170 +1,417 @@
 <template>
   <div class="log">
-    <el-form label-width="100" label-position="left" :model="form">
-      <el-row :gutter="20">
-        <el-col :span="8">
-          <el-form-item label="操作人">
-            <el-input v-model="form.operator" placeholder="请输入操作人姓名查找"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作时间">
-            <el-date-picker
-              v-model="form.operatingTime"
-              type="daterange"
-              range-separator="至"
-              start-placeholder="开始时间"
-              end-placeholder="结束时间"
-              format="YYYY-MM-DD"
-              value-format="YYYY-MM-DD"
-              @change="timeChange"
-            />
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作功能">
-            <el-select v-model="form.function" placeholder="请选择">
-              <el-option label="工能1" value="1" key="1"></el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作内容">
-            <el-input v-model="form.content" placeholder="请输入"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="16" style="display: flex; align-items: center; justify-content: flex-end">
-          <el-button type="primary" @click="search">查询</el-button>
-          <el-button plain type="primary" @click="reset">重置</el-button>
-        </el-col>
-      </el-row>
-    </el-form>
-    <el-table
-      :data="tableData"
-      height="600"
-      style="margin-top: 24px"
-    >
-      <el-table-column label="操作人" prop="createBy" width="200"></el-table-column  >
-      <el-table-column label="操作时间" prop="createTime" width="240"></el-table-column>
-      <el-table-column label="操作功能" prop="moduleName"></el-table-column>
-      <el-table-column label="操作内容" prop="operationContent"></el-table-column>
-      <el-table-column label="类型" prop="operatorName" width="150"></el-table-column>
-      <el-table-column label="操作" width="150">
-        <template #default="scope">
-          <el-button link type="primary" @click="detail(scope.row)">查看详情</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <div class="pagination">
-      <el-pagination
-        v-model:current-page="pages"
-        v-model:page-size="size"
-        :page-sizes="[10, 20, 30, 40]"
-        layout="total, sizes, prev, pager, next, jumper"
-        :total="total"
-        @size-change="handleSizeChange"
-        @current-change="handleCurrentChange"
-      ></el-pagination>
+    <div class='btn-box'>
+      <el-button type="primary" plain class='query-btn'
+        @click='dialogShow'>{{selectedKeys.length?`已选${selectedKeys.length}项`:'筛选条件'}}</el-button>
+      <div class='query-btn'>
+        <DowButton @endAnim='downloadFile'></DowButton>
+      </div>
     </div>
+    <QueryForm :option="listOption" @query='query' @delSelect='delSelect' ref='queryFormRef'></QueryForm>
+    <div class='flex content-box'>
+      <!-- tree -->
+      <div>
+        <div class='content-l'>
+          <div class='item' v-for='(item,index) in tabList' :key="index" :class="{'active':index==tabIndex}"
+            @click='tabClick(item,index)'>
+            {{item.name}}
+          </div>
+        </div>
+        <Tree ref='treeRef'></Tree>
+      </div>
+
+      <div class='flex-1 content-r'>
+        <!-- 表格 -->
+        <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
+          :columnwidth="120" :pageInfo="pageInfo" @getList="getList">
+          <template v-slot:operation="scope">
+            <el-button type="primary" link @click='agreementEdit(scope.operationData.id)'>明细</el-button>
+          </template>
+
+          <template v-slot:search="scope">
+            <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+              @update:sort="handleSortUpdate"></Sort>
+          </template>
+
+          <template #customSlot="{  bodyCell: { scope, column } }">
+            <template v-if="column.prop == 'underwriteOrderNum'">
+              {{ scope.row.underwriteOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'djOrderNum'">
+              {{ scope.row.djOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dsyOrderNum'">
+              {{ scope.row.dsyOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dszOrderNum'">
+              {{ scope.row.dszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jszOrderNum'">
+              {{ scope.row.jszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jsyOrderNum'">
+              {{ scope.row.jsyOrderNum }} 笔
+            </template>
+          </template>
+        </ComplexTable>
+      </div>
+    </div>
+
+    <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
+      routerKey='routerKey'>
+    </FilterDialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import { useRouter } from 'vue-router'
-import api from '@/api'
-import {ElMessage} from "element-plus";
+import { useRouter } from "vue-router";
+import api from "@/api";
+import QueryForm from "../../components/queryForm.vue";
+import FilterDialog from "../../components/filterDialog.vue";
+import DowButton from "../../components/button.vue";
+import Sort from "../../components/sort.vue";
+import useUserStore from "@/store/modules/message";
+import PageInfo from "@/api/types/agreementTypes";
+import Tree from "../../components/tree.vue";
+import { ElMessage } from "element-plus";
 
-const myRouter = useRouter()
+const router = useRouter();
+const userStore = useUserStore();
+const isShow = ref(false);
 
-let activeName = ref('first')
-const handleClick = () => {
+const isSort = ref();
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const listOption = reactive({
+  rowKey: "telemarketingId",
+  //查询
+  queryFormFields: [],
+  // 表格列
+  columns: [
+    {
+      prop: "salesmanName",
+      label: "姓名",
+      width: "100",
+    },
+    {
+      prop: "salesmanPhone",
+      label: "手机号",
+      width: "120",
+    },
+    {
+      prop: "deptName",
+      label: "所属机构",
+      width: "300",
+    },
+    {
+      prop: "underwriteOrderNum",
+      label: "承保订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "sumPremium",
+      label: "保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "jqPremium",
+      label: "交强保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "taxPremium",
+      label: "车船税",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "syPremium",
+      label: "商业保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "jyPremium",
+      label: "驾意保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "单交订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "dsyOrderNum",
+      label: "单商订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "dszOrderNum",
+      label: "单三订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "jszOrderNum",
+      label: "交三订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "jsyOrderNum",
+      label: "交商订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "manegerName",
+      label: "管理人",
+      width: "180",
+    },
+  ],
+});
 
-}
+const selectedKeys = ref([]);
+const selected = function (val) {
+  selectedKeys.value = val;
+};
 
-let form = ref({})
-const tableProps = ref({
-  value: "id",
-  label: "name",
-  children: "children",
-  checkStrictly: true,
-});
-let option = ref([])
-const timeChange = (val) => {
+//查询数据
+const phone = JSON.parse(localStorage.getItem("userInfo")).username;
 
-}
-// 搜索
-const search = () => {
-  pages.value = 1
-  size.value = 10
-  initData()
-}
-const reset = () => {
-  form.value = {}
-  pages.value = 1
-  size.value = 10
-  initData()
+//获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("telemarketingDataManage");
+const defaultList = ref();
+const pageHiddenList = ref([]); //页面不显示的数据
+const initDefaultList = async () => {
+  const { data } = await api.manageApi.getSearchDefaultList({
+    routerKey: routerKey.value,
+    userId: phone,
+  });
+  listOption.queryFormFields = data.filter((e) => e.showFlag);
+
+  pageHiddenList.value = data.filter((e) => !e.showFlag);
+  defaultList.value = data.map((e) => e.id);
+  selectedKeys.value = defaultList.value;
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
+};
+
+//删除
+const filterDialogRef = ref();
+const delSelect = (id) => {
+  listOption.queryFormFields = listOption.queryFormFields.filter(
+    (item) => item.id != id
+  );
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//打开dialogShow
+const dialogShow = function () {
+  isShow.value = true;
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//确定
+const queryFormRef = ref();
+const filterSure = (item, index) => {
+  isShow.value = false;
+  const secondGroupIds = item.list.map((item) => item.id);
+  const oldList = listOption.queryFormFields.filter((item) =>
+    secondGroupIds.includes(item.id)
+  );
+  const firstGroupIds = listOption.queryFormFields.map((item) => item.id);
+  let newList = item.list.filter((item) => !firstGroupIds.includes(item.id));
+
+  //过滤掉默认不显示的数据
+  const hiddenList = new Set(pageHiddenList.value.map((item) => item.id));
+  const filterList = newList.filter((item) => !hiddenList.has(item.id));
+
+  listOption.queryFormFields = [...oldList, ...filterList];
+  queryFormRef.value?.initDefaultSaveForm();
+  selectedKeys.value = item.list.filter((item) => item.id);
+};
+
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
+
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
+
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.telemarketingDataManagePageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
+};
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
-// 列表
-let tableData = ref([])
-const detail = (row) => {
-  myRouter.push({
-    path: '/consoleManage/businessDataManage/telemarketingDataManage/telemarketingDataManageDetail',
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.telemarketingDataManageToTask({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
+
+const agreementEdit = (id) => {
+  router.push({
+    name: "telemarketingDataManageDetail",
     query: {
-      id: row.id
-    }
-  })
-}
+      id: id,
+    },
+  });
+};
 
-// 分页
-let pages = ref(1)
-let size = ref(10)
-let total = ref(0)
-const handleSizeChange = (size) => {
-  size.value = size
-  initData()
-}
-const handleCurrentChange = (page) => {
-  pages.value = page
-  initData()
-}
+//tabClick
+const treeRef = ref();
+const tabIndex = ref(0);
+const tabClick = (item, index) => {
+  tabIndex.value = index;
+  treeRef.value?.getTree(item.api);
+};
 
-const initData = () => {
-  api.logApi.list({
-    pages: pages.value,
-    size: size.value,
-    ...form.value
-  }).then((res: any) => {
-    if(res.code === 200) {
-      tableData.value = res.data.records
-      total.value = res.data.total
-    } else {
-      ElMessage({
-        message: res.msg,
-        type: 'warning'
-      })
-    }
-  })
-}
+const tabList = ref([
+  {
+    name: "机构",
+    value: 1,
+    api: api.manageApi.getDeptListByUserId,
+  },
+  {
+    name: "人员",
+    value: 2,
+    api: api.manageApi.getUserManageListByUserId,
+  },
+]);
 
 onMounted(() => {
-  initData()
-})
-
+  initDefaultList();
+  treeRef.value?.getTree(tabList.value[0].api);
+});
 </script>
 
 <style scoped lang="scss">
-.log{
+.log {
   width: 100%;
   height: calc(100vh - 120px);
-  background: #FFFFFF;
+  background: #ffffff;
   padding: 24px;
   overflow-y: auto;
-  .pagination{
-    margin-top: 24px;
+  .query-btn {
+    margin-left: 20px;
+  }
+  .btn-box {
+    padding-bottom: 15px;
+    margin-bottom: 24px;
+    border-bottom: 1px solid #eeeeee;
     display: flex;
-    align-items: center;
     justify-content: flex-end;
   }
+
+  .content-box {
+    justify-content: space-between;
+    .content-l {
+      width: 298px;
+      display: flex;
+      margin: 20px 16px 20px 0;
+      .item {
+        width: 50%;
+        height: 36px;
+        line-height: 36px;
+        background: #f7f7f7;
+        font-size: 16px;
+        text-align: center;
+        border-radius: 2px;
+      }
+      .active {
+        background: #0083ff;
+        color: #fff;
+      }
+    }
+    .content-r {
+      width: 0;
+    }
+  }
+}
+:deep(.caret-wrapper) {
+  display: none !important;
 }
 </style>

+ 269 - 97
src/views/consoleManage/businessDataManage/telemarketingDataManage/telemarketingDataManageDetail.vue

@@ -1,117 +1,289 @@
 <template>
-  <div class="logDetail">
-    <el-descriptions :column="2">
-      <template #title>
-        <div class="title">
-          <div class="icon">
-            <el-icon><List /></el-icon>
-          </div>
-          <p>{{ detailData?.operationContent }}</p>
-        </div>
+  <div class="log">
+    <div class='btn-box'>
+      <el-button type="primary" plain class='query-btn'
+        @click='dialogShow'>{{selectedKeys.length?`已选${selectedKeys.length}项`:'筛选条件'}}</el-button>
+      <div class='query-btn'>
+        <DowButton @endAnim='downloadFile'></DowButton>
+      </div>
+    </div>
+    <QueryForm :option="listOption" @query='query' @delSelect='delSelect' ref='queryFormRef'></QueryForm>
+
+    <!-- 表格 -->
+    <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
+      :columnwidth="120" :pageInfo="pageInfo" @getList="getList" :showOperation='false'>
+
+      <template v-slot:search="scope">
+        <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+          @update:sort="handleSortUpdate"></Sort>
       </template>
-      <el-descriptions-item label="操作功能:" label-align="right" align="left" label-width="100">{{ detailData?.moduleName }}</el-descriptions-item>
-      <el-descriptions-item label="操作类型:" label-align="right" align="left" label-width="100">{{ detailData?.operatorName }}</el-descriptions-item>
-      <el-descriptions-item label="操作人:" label-align="right" align="left" label-width="100">{{ detailData?.createBy }}</el-descriptions-item>
-      <el-descriptions-item label="操作时间:" label-align="right" align="left" label-width="100">{{ detailData?.createTime }}</el-descriptions-item>
-    </el-descriptions>
-    <el-row :gutter="20" class="content">
-      <el-col :span="11">
-        <p>变更前</p>
-        <div class="list">
-          <el-row class="list-item" :gutter="20" v-for="item in detailData?.compareResultList" :key="item">
-            <el-col :span="6">{{ item.name }}</el-col>
-            <el-col :span="18" style="color: #606266">{{ item.fieldContent }}</el-col>
-          </el-row>
-        </div>
-      </el-col>
-      <el-divider direction="vertical" style="height: 100%"></el-divider>
-      <el-col :span="11">
-        <p>变更后</p>
-        <div class="list">
-          <el-row class="list-item" :gutter="20" v-for="item in detailData?.compareResultList" :key="item">
-            <el-col :span="6">{{ item.name }}</el-col>
-            <el-col :span="18" style="color: #606266">{{ item.newFieldContent }}</el-col>
-          </el-row>
-        </div>
-      </el-col>
-    </el-row>
+
+    </ComplexTable>
+
+    <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
+      routerKey='routerKey'>
+    </FilterDialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import api from '@/api'
-import { useRoute, useRouter } from 'vue-router'
+import { useRouter } from "vue-router";
+import api from "@/api";
+import QueryForm from "../../components/queryForm.vue";
+import FilterDialog from "../../components/filterDialog.vue";
+import DowButton from "../../components/button.vue";
+import Sort from "../../components/sort.vue";
+import useUserStore from "@/store/modules/message";
+import PageInfo from "@/api/types/agreementTypes";
 import { ElMessage } from "element-plus";
 
-const myRoute = useRoute()
-const myRouter = useRouter()
-
-let detailData = ref(undefined)
-
-const initDetail = () => {
-  api.logApi.selectById(myRoute.query.id).then((res: any) => {
-    if(res.code == 200) {
-      detailData.value = res.data
-    } else {
-      ElMessage({
-        message: res.msg,
-        type: 'warning'
-      })
-    }
-  })
+const router = useRouter();
+const userStore = useUserStore();
+const isShow = ref(false);
+
+const isSort = ref();
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const listOption = reactive({
+  rowKey: "telemarketingDelId",
+  //查询
+  queryFormFields: [],
+  // 表格列
+  columns: [
+    {
+      prop: "salesmanName",
+      label: "业务员",
+      width: "200",
+    },
+    {
+      prop: "salesmanPhone",
+      label: "手机号",
+      width: "120",
+    },
+    {
+      prop: "companyId",
+      label: "保险公司",
+      width: "200",
+    },
+    {
+      prop: "companyName",
+      label: "合作保险公司",
+      width: "300",
+    },
+    {
+      prop: "orderNo",
+      label: "订单号",
+      width: "180",
+    },
+    {
+      prop: "licenseNo",
+      label: "车牌号",
+      width: "180",
+    },
+    {
+      prop: "orderTypeName",
+      label: "订单类型",
+      width: "180",
+    },
+    {
+      prop: "riskName",
+      label: "险种",
+      width: "180",
+    },
+    {
+      prop: "quoteCountNum",
+      label: "报价次数",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "sumPremium",
+      label: "保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "createTime",
+      label: "录单时间",
+      width: "180",
+    },
+    {
+      prop: "recordTime",
+      label: "签单时间",
+      width: "180",
+    },
+    {
+      prop: "manegerName",
+      label: "管理人",
+      width: "180",
+    },
+  ],
+});
+
+const selectedKeys = ref([]);
+const selected = function (val) {
+  selectedKeys.value = val;
+};
+
+//查询数据
+const phone = JSON.parse(localStorage.getItem("userInfo")).username;
+
+//获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("telemarketingDataManageDetail");
+const defaultList = ref();
+const pageHiddenList = ref([]); //页面不显示的数据
+const initDefaultList = async () => {
+  const { data } = await api.manageApi.getSearchDefaultList({
+    routerKey: routerKey.value,
+    userId: phone,
+  });
+  listOption.queryFormFields = data.filter((e) => e.showFlag);
+
+  pageHiddenList.value = data.filter((e) => !e.showFlag);
+  defaultList.value = data.map((e) => e.id);
+  selectedKeys.value = defaultList.value;
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
+};
+
+//删除
+const filterDialogRef = ref();
+const delSelect = (id) => {
+  listOption.queryFormFields = listOption.queryFormFields.filter(
+    (item) => item.id != id
+  );
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//打开dialogShow
+const dialogShow = function () {
+  isShow.value = true;
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//确定
+const queryFormRef = ref();
+const filterSure = (item, index) => {
+  isShow.value = false;
+  const secondGroupIds = item.list.map((item) => item.id);
+  const oldList = listOption.queryFormFields.filter((item) =>
+    secondGroupIds.includes(item.id)
+  );
+  const firstGroupIds = listOption.queryFormFields.map((item) => item.id);
+  let newList = item.list.filter((item) => !firstGroupIds.includes(item.id));
+
+  //过滤掉默认不显示的数据
+  const hiddenList = new Set(pageHiddenList.value.map((item) => item.id));
+  const filterList = newList.filter((item) => !hiddenList.has(item.id));
+
+  listOption.queryFormFields = [...oldList, ...filterList];
+  queryFormRef.value?.initDefaultSaveForm();
+  selectedKeys.value = item.list.filter((item) => item.id);
+};
+
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
+
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
+
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.telemarketingDataManageDetailPageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
+};
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
-onMounted(() => {
-  initDetail()
-})
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.telemarketingDataManageDetailToTask({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
 
+onMounted(() => {
+  initDefaultList();
+});
 </script>
 
 <style scoped lang="scss">
-.logDetail{
-  padding: 24px;
-  background: #FFFFFF;
+.log {
   width: 100%;
   height: calc(100vh - 120px);
-  .title{
-    display: flex;
-    align-items: center;
-    justify-content: flex-start;
-    .icon{
-      width: 30px;
-      height: 30px;
-      border-radius: 50%;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      background: #1A85FA;
-      color: #FFFFFF;
-      font-size: 20px;
-      margin-right: 10px;
-    }
-  }
-  .content{
-    height: calc(100% - 120px);
-    overflow: hidden;
-    p{
-      text-align: center;
-      background: #F0F0F0;
-      margin: 0;
-      padding: 16px 0;
-    }
-    .list{
-      height: calc(100% - 80px);
-      overflow-y: auto;
-      overflow-x: hidden;
-      .list-item{
-        margin: 14px 0;
-        padding: 0 20px;
-        display: flex;
-      }
-    }
+  background: #ffffff;
+  padding: 24px;
+  overflow-y: auto;
+  .query-btn {
+    margin-left: 20px;
   }
-  :deep(.el-descriptions) {
-    width: 50%;
+  .btn-box {
+    padding-bottom: 15px;
+    margin-bottom: 24px;
+    border-bottom: 1px solid #eeeeee;
+    display: flex;
+    justify-content: flex-end;
   }
 }
+:deep(.caret-wrapper) {
+  display: none !important;
+}
 </style>

+ 26 - 3
src/views/consoleManage/components/queryForm.vue

@@ -238,7 +238,7 @@ const initDefaultSaveForm = () => {
       return [formatTime(currentTimestamp, "YYYY")];
     },
     "select-multiple": (item, baseValue) => {
-      const value = item.listOption ? baseValue : "";
+      const value = item.listOption ? baseValue : "0";
       return value === "0" ? ["0"] : value;
     },
     "select-single": (item, baseValue) => {
@@ -248,6 +248,9 @@ const initDefaultSaveForm = () => {
       }
       return value;
     },
+    "date-tree": (item, baseValue) => {
+      return item.selectValue ? baseValue : [];
+    },
     default: (_, baseValue) => baseValue,
   };
 
@@ -262,7 +265,23 @@ const initDefaultSaveForm = () => {
 
   // 更新表单数据并返回
   queryForm.data = { ...defaultSaveForm };
-  return queryForm.data;
+
+  // 处理单选框返回值格式
+  const processedForm = { ...defaultSaveForm };
+  queryFormFields
+    .filter((item) => item.inputType == "select-single")
+    .forEach((item) => {
+      const { key } = item;
+      const value = processedForm[key] ?? item.defaultValue;
+      processedForm[key] =
+        item.key === "companyId"
+          ? value
+          : Array.isArray(value)
+          ? value
+          : [value];
+    });
+
+  return processedForm;
 };
 
 //多选中发生变化
@@ -314,7 +333,11 @@ const query = () => {
   const typeHandlers = {
     "select-single": (item, value) => {
       // 特殊处理companyId,其他单选转换为数组格式
-      return item.key === "companyId" ? value : [value || "0"];
+      return item.key === "companyId"
+        ? value
+        : Array.isArray(value)
+        ? value
+        : [value];
     },
     "date-tree": (item, value) => {
       // 日期树选择器:无默认值时转换为空数组

+ 350 - 140
src/views/consoleManage/quotationDataManage/channelQuotationData/index.vue

@@ -1,170 +1,380 @@
 <template>
   <div class="log">
-    <el-form label-width="100" label-position="left" :model="form">
-      <el-row :gutter="20">
-        <el-col :span="8">
-          <el-form-item label="操作人">
-            <el-input v-model="form.operator" placeholder="请输入操作人姓名查找"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作时间">
-            <el-date-picker
-              v-model="form.operatingTime"
-              type="daterange"
-              range-separator="至"
-              start-placeholder="开始时间"
-              end-placeholder="结束时间"
-              format="YYYY-MM-DD"
-              value-format="YYYY-MM-DD"
-              @change="timeChange"
-            />
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作功能">
-            <el-select v-model="form.function" placeholder="请选择">
-              <el-option label="工能1" value="1" key="1"></el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作内容">
-            <el-input v-model="form.content" placeholder="请输入"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="16" style="display: flex; align-items: center; justify-content: flex-end">
-          <el-button type="primary" @click="search">查询</el-button>
-          <el-button plain type="primary" @click="reset">重置</el-button>
-        </el-col>
-      </el-row>
-    </el-form>
-    <el-table
-      :data="tableData"
-      height="600"
-      style="margin-top: 24px"
-    >
-      <el-table-column label="操作人" prop="createBy" width="200"></el-table-column  >
-      <el-table-column label="操作时间" prop="createTime" width="240"></el-table-column>
-      <el-table-column label="操作功能" prop="moduleName"></el-table-column>
-      <el-table-column label="操作内容" prop="operationContent"></el-table-column>
-      <el-table-column label="类型" prop="operatorName" width="150"></el-table-column>
-      <el-table-column label="操作" width="150">
-        <template #default="scope">
-          <el-button link type="primary" @click="detail(scope.row)">查看详情</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <div class="pagination">
-      <el-pagination
-        v-model:current-page="pages"
-        v-model:page-size="size"
-        :page-sizes="[10, 20, 30, 40]"
-        layout="total, sizes, prev, pager, next, jumper"
-        :total="total"
-        @size-change="handleSizeChange"
-        @current-change="handleCurrentChange"
-      ></el-pagination>
+    <div class='btn-box'>
+      <el-button type="primary" plain class='query-btn'
+        @click='dialogShow'>{{selectedKeys.length?`已选${selectedKeys.length}项`:'筛选条件'}}</el-button>
+      <div class='query-btn'>
+        <DowButton @endAnim='downloadFile'></DowButton>
+      </div>
     </div>
+    <QueryForm :option="listOption" @query='query' @delSelect='delSelect' ref='queryFormRef'></QueryForm>
+    <div class='flex content-box'>
+      <!-- tree -->
+      <div class='content-l'>
+        <Tree ref='treeRef'></Tree>
+      </div>
+
+      <div class='flex-1 content-r'>
+        <!-- 表格 -->
+        <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
+          :columnwidth="120" :pageInfo="pageInfo" @getList="getList" :showOperation='false'>
+
+          <template v-slot:search="scope">
+            <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+              @update:sort="handleSortUpdate"></Sort>
+          </template>
+
+          <template #customSlot="{  bodyCell: { scope, column } }">
+            <template v-if="column.prop == 'underwriteOrderNum'">
+              {{ scope.row.underwriteOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'djOrderNum'">
+              {{ scope.row.djOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dsyOrderNum'">
+              {{ scope.row.dsyOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dszOrderNum'">
+              {{ scope.row.dszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jszOrderNum'">
+              {{ scope.row.jszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jsyOrderNum'">
+              {{ scope.row.jsyOrderNum }} 笔
+            </template>
+          </template>
+        </ComplexTable>
+      </div>
+    </div>
+
+    <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
+      routerKey='routerKey'>
+    </FilterDialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import { useRouter } from 'vue-router'
-import api from '@/api'
-import {ElMessage} from "element-plus";
+import { useRouter } from "vue-router";
+import api from "@/api";
+import QueryForm from "../../components/queryForm.vue";
+import FilterDialog from "../../components/filterDialog.vue";
+import DowButton from "../../components/button.vue";
+import Sort from "../../components/sort.vue";
+import useUserStore from "@/store/modules/message";
+import PageInfo from "@/api/types/agreementTypes";
+import Tree from "../../components/tree.vue";
+import { ElMessage } from "element-plus";
 
-const myRouter = useRouter()
+const router = useRouter();
+const userStore = useUserStore();
+const isShow = ref(false);
 
-let activeName = ref('first')
-const handleClick = () => {
+const isSort = ref();
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const listOption = reactive({
+  rowKey: "channelQuotationId",
+  //查询
+  queryFormFields: [],
+  // 表格列
+  columns: [
+    {
+      prop: "salesmanName",
+      label: "保险公司",
+      width: "100",
+    },
+    {
+      prop: "salesmanPhone",
+      label: "合作保险公司",
+      width: "120",
+    },
+    {
+      prop: "deptName",
+      label: "报价数量",
+      width: "300",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "underwriteOrderNum",
+      label: "报价量占比",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "sumPremium",
+      label: "报价成功",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "jqPremium",
+      label: "报价失败",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "taxPremium",
+      label: "平均报价响应时间",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "syPremium",
+      label: "提交核保",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "jyPremium",
+      label: "人工核保数",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "核保通过",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "核保不通过",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "核保通过率",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "成交单数",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "转化率",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+  ],
+});
 
-}
+const selectedKeys = ref([]);
+const selected = function (val) {
+  selectedKeys.value = val;
+};
 
-let form = ref({})
-const tableProps = ref({
-  value: "id",
-  label: "name",
-  children: "children",
-  checkStrictly: true,
-});
-let option = ref([])
-const timeChange = (val) => {
+//查询数据
+const phone = JSON.parse(localStorage.getItem("userInfo")).username;
 
-}
-// 搜索
-const search = () => {
-  pages.value = 1
-  size.value = 10
-  initData()
-}
-const reset = () => {
-  form.value = {}
-  pages.value = 1
-  size.value = 10
-  initData()
-}
+//获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("channelQuotationData");
+const defaultList = ref();
+const pageHiddenList = ref([]); //页面不显示的数据
+const initDefaultList = async () => {
+  const { data } = await api.manageApi.getSearchDefaultList({
+    routerKey: routerKey.value,
+    userId: phone,
+  });
+  listOption.queryFormFields = data.filter((e) => e.showFlag);
 
-// 列表
-let tableData = ref([])
-const detail = (row) => {
-  myRouter.push({
-    path: '/systemManage/logManage/logDetail',
-    query: {
-      id: row.id
-    }
-  })
-}
+  pageHiddenList.value = data.filter((e) => !e.showFlag);
+  defaultList.value = data.map((e) => e.id);
+  selectedKeys.value = defaultList.value;
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
+};
 
-// 分页
-let pages = ref(1)
-let size = ref(10)
-let total = ref(0)
-const handleSizeChange = (size) => {
-  size.value = size
-  initData()
-}
-const handleCurrentChange = (page) => {
-  pages.value = page
-  initData()
-}
+//删除
+const filterDialogRef = ref();
+const delSelect = (id) => {
+  listOption.queryFormFields = listOption.queryFormFields.filter(
+    (item) => item.id != id
+  );
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
 
-const initData = () => {
-  api.logApi.list({
-    pages: pages.value,
-    size: size.value,
-    ...form.value
-  }).then((res: any) => {
-    if(res.code === 200) {
-      tableData.value = res.data.records
-      total.value = res.data.total
-    } else {
-      ElMessage({
-        message: res.msg,
-        type: 'warning'
-      })
-    }
-  })
+//打开dialogShow
+const dialogShow = function () {
+  isShow.value = true;
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//确定
+const queryFormRef = ref();
+const filterSure = (item, index) => {
+  isShow.value = false;
+  const secondGroupIds = item.list.map((item) => item.id);
+  const oldList = listOption.queryFormFields.filter((item) =>
+    secondGroupIds.includes(item.id)
+  );
+  const firstGroupIds = listOption.queryFormFields.map((item) => item.id);
+  let newList = item.list.filter((item) => !firstGroupIds.includes(item.id));
+
+  //过滤掉默认不显示的数据
+  const hiddenList = new Set(pageHiddenList.value.map((item) => item.id));
+  const filterList = newList.filter((item) => !hiddenList.has(item.id));
+
+  listOption.queryFormFields = [...oldList, ...filterList];
+  queryFormRef.value?.initDefaultSaveForm();
+  selectedKeys.value = item.list.filter((item) => item.id);
+};
+
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
+
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
+
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.telemarketingDataManagePageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
+};
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
-onMounted(() => {
-  initData()
-})
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.telemarketingDataManageToTask({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
+
+//tabClick
+const treeRef = ref();
+const tabIndex = ref(0);
+const tabClick = (item, index) => {
+  tabIndex.value = index;
+  treeRef.value?.getTree(item.api);
+};
 
+onMounted(() => {
+  initDefaultList();
+  treeRef.value?.getTree(api.manageApi.getDeptListByUserId);
+});
 </script>
 
 <style scoped lang="scss">
-.log{
+.log {
   width: 100%;
   height: calc(100vh - 120px);
-  background: #FFFFFF;
+  background: #ffffff;
   padding: 24px;
   overflow-y: auto;
-  .pagination{
-    margin-top: 24px;
+  .query-btn {
+    margin-left: 20px;
+  }
+  .btn-box {
+    padding-bottom: 15px;
+    margin-bottom: 24px;
+    border-bottom: 1px solid #eeeeee;
     display: flex;
-    align-items: center;
     justify-content: flex-end;
   }
+
+  .content-box {
+    justify-content: space-between;
+    .content-l {
+      width: 298px;
+      display: flex;
+      margin: 20px 16px 20px 0;
+      .item {
+        width: 50%;
+        height: 36px;
+        line-height: 36px;
+        background: #f7f7f7;
+        font-size: 16px;
+        text-align: center;
+        border-radius: 2px;
+      }
+      .active {
+        background: #0083ff;
+        color: #fff;
+      }
+    }
+    .content-r {
+      width: 0;
+    }
+  }
+}
+:deep(.caret-wrapper) {
+  display: none !important;
 }
 </style>

+ 350 - 140
src/views/consoleManage/quotationDataManage/companyQuotationData/index.vue

@@ -1,170 +1,380 @@
 <template>
   <div class="log">
-    <el-form label-width="100" label-position="left" :model="form">
-      <el-row :gutter="20">
-        <el-col :span="8">
-          <el-form-item label="操作人">
-            <el-input v-model="form.operator" placeholder="请输入操作人姓名查找"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作时间">
-            <el-date-picker
-              v-model="form.operatingTime"
-              type="daterange"
-              range-separator="至"
-              start-placeholder="开始时间"
-              end-placeholder="结束时间"
-              format="YYYY-MM-DD"
-              value-format="YYYY-MM-DD"
-              @change="timeChange"
-            />
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作功能">
-            <el-select v-model="form.function" placeholder="请选择">
-              <el-option label="工能1" value="1" key="1"></el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作内容">
-            <el-input v-model="form.content" placeholder="请输入"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="16" style="display: flex; align-items: center; justify-content: flex-end">
-          <el-button type="primary" @click="search">查询</el-button>
-          <el-button plain type="primary" @click="reset">重置</el-button>
-        </el-col>
-      </el-row>
-    </el-form>
-    <el-table
-      :data="tableData"
-      height="600"
-      style="margin-top: 24px"
-    >
-      <el-table-column label="操作人" prop="createBy" width="200"></el-table-column  >
-      <el-table-column label="操作时间" prop="createTime" width="240"></el-table-column>
-      <el-table-column label="操作功能" prop="moduleName"></el-table-column>
-      <el-table-column label="操作内容" prop="operationContent"></el-table-column>
-      <el-table-column label="类型" prop="operatorName" width="150"></el-table-column>
-      <el-table-column label="操作" width="150">
-        <template #default="scope">
-          <el-button link type="primary" @click="detail(scope.row)">查看详情</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <div class="pagination">
-      <el-pagination
-        v-model:current-page="pages"
-        v-model:page-size="size"
-        :page-sizes="[10, 20, 30, 40]"
-        layout="total, sizes, prev, pager, next, jumper"
-        :total="total"
-        @size-change="handleSizeChange"
-        @current-change="handleCurrentChange"
-      ></el-pagination>
+    <div class='btn-box'>
+      <el-button type="primary" plain class='query-btn'
+        @click='dialogShow'>{{selectedKeys.length?`已选${selectedKeys.length}项`:'筛选条件'}}</el-button>
+      <div class='query-btn'>
+        <DowButton @endAnim='downloadFile'></DowButton>
+      </div>
     </div>
+    <QueryForm :option="listOption" @query='query' @delSelect='delSelect' ref='queryFormRef'></QueryForm>
+    <div class='flex content-box'>
+      <!-- tree -->
+      <div class='content-l'>
+        <Tree ref='treeRef'></Tree>
+      </div>
+
+      <div class='flex-1 content-r'>
+        <!-- 表格 -->
+        <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
+          :columnwidth="120" :pageInfo="pageInfo" @getList="getList" :showOperation='false'>
+
+          <template v-slot:search="scope">
+            <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+              @update:sort="handleSortUpdate"></Sort>
+          </template>
+
+          <template #customSlot="{  bodyCell: { scope, column } }">
+            <template v-if="column.prop == 'underwriteOrderNum'">
+              {{ scope.row.underwriteOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'djOrderNum'">
+              {{ scope.row.djOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dsyOrderNum'">
+              {{ scope.row.dsyOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dszOrderNum'">
+              {{ scope.row.dszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jszOrderNum'">
+              {{ scope.row.jszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jsyOrderNum'">
+              {{ scope.row.jsyOrderNum }} 笔
+            </template>
+          </template>
+        </ComplexTable>
+      </div>
+    </div>
+
+    <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
+      routerKey='routerKey'>
+    </FilterDialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import { useRouter } from 'vue-router'
-import api from '@/api'
-import {ElMessage} from "element-plus";
+import { useRouter } from "vue-router";
+import api from "@/api";
+import QueryForm from "../../components/queryForm.vue";
+import FilterDialog from "../../components/filterDialog.vue";
+import DowButton from "../../components/button.vue";
+import Sort from "../../components/sort.vue";
+import useUserStore from "@/store/modules/message";
+import PageInfo from "@/api/types/agreementTypes";
+import Tree from "../../components/tree.vue";
+import { ElMessage } from "element-plus";
 
-const myRouter = useRouter()
+const router = useRouter();
+const userStore = useUserStore();
+const isShow = ref(false);
 
-let activeName = ref('first')
-const handleClick = () => {
+const isSort = ref();
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const listOption = reactive({
+  rowKey: "companyQuotationId",
+  //查询
+  queryFormFields: [],
+  // 表格列
+  columns: [
+    {
+      prop: "salesmanName",
+      label: "保险公司",
+      width: "100",
+    },
+    {
+      prop: "salesmanPhone",
+      label: "合作保险公司",
+      width: "120",
+    },
+    {
+      prop: "deptName",
+      label: "报价数量",
+      width: "300",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "underwriteOrderNum",
+      label: "报价量占比",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "sumPremium",
+      label: "报价成功",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "jqPremium",
+      label: "报价失败",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "taxPremium",
+      label: "平均报价响应时间",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "syPremium",
+      label: "提交核保",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "jyPremium",
+      label: "人工核保数",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "核保通过",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "核保不通过",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "核保通过率",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "成交单数",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "转化率",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+  ],
+});
 
-}
+const selectedKeys = ref([]);
+const selected = function (val) {
+  selectedKeys.value = val;
+};
 
-let form = ref({})
-const tableProps = ref({
-  value: "id",
-  label: "name",
-  children: "children",
-  checkStrictly: true,
-});
-let option = ref([])
-const timeChange = (val) => {
+//查询数据
+const phone = JSON.parse(localStorage.getItem("userInfo")).username;
 
-}
-// 搜索
-const search = () => {
-  pages.value = 1
-  size.value = 10
-  initData()
-}
-const reset = () => {
-  form.value = {}
-  pages.value = 1
-  size.value = 10
-  initData()
-}
+//获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("companyQuotationData");
+const defaultList = ref();
+const pageHiddenList = ref([]); //页面不显示的数据
+const initDefaultList = async () => {
+  const { data } = await api.manageApi.getSearchDefaultList({
+    routerKey: routerKey.value,
+    userId: phone,
+  });
+  listOption.queryFormFields = data.filter((e) => e.showFlag);
 
-// 列表
-let tableData = ref([])
-const detail = (row) => {
-  myRouter.push({
-    path: '/systemManage/logManage/logDetail',
-    query: {
-      id: row.id
-    }
-  })
-}
+  pageHiddenList.value = data.filter((e) => !e.showFlag);
+  defaultList.value = data.map((e) => e.id);
+  selectedKeys.value = defaultList.value;
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
+};
 
-// 分页
-let pages = ref(1)
-let size = ref(10)
-let total = ref(0)
-const handleSizeChange = (size) => {
-  size.value = size
-  initData()
-}
-const handleCurrentChange = (page) => {
-  pages.value = page
-  initData()
-}
+//删除
+const filterDialogRef = ref();
+const delSelect = (id) => {
+  listOption.queryFormFields = listOption.queryFormFields.filter(
+    (item) => item.id != id
+  );
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
 
-const initData = () => {
-  api.logApi.list({
-    pages: pages.value,
-    size: size.value,
-    ...form.value
-  }).then((res: any) => {
-    if(res.code === 200) {
-      tableData.value = res.data.records
-      total.value = res.data.total
-    } else {
-      ElMessage({
-        message: res.msg,
-        type: 'warning'
-      })
-    }
-  })
+//打开dialogShow
+const dialogShow = function () {
+  isShow.value = true;
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//确定
+const queryFormRef = ref();
+const filterSure = (item, index) => {
+  isShow.value = false;
+  const secondGroupIds = item.list.map((item) => item.id);
+  const oldList = listOption.queryFormFields.filter((item) =>
+    secondGroupIds.includes(item.id)
+  );
+  const firstGroupIds = listOption.queryFormFields.map((item) => item.id);
+  let newList = item.list.filter((item) => !firstGroupIds.includes(item.id));
+
+  //过滤掉默认不显示的数据
+  const hiddenList = new Set(pageHiddenList.value.map((item) => item.id));
+  const filterList = newList.filter((item) => !hiddenList.has(item.id));
+
+  listOption.queryFormFields = [...oldList, ...filterList];
+  queryFormRef.value?.initDefaultSaveForm();
+  selectedKeys.value = item.list.filter((item) => item.id);
+};
+
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
+
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
+
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.telemarketingDataManagePageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
+};
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
-onMounted(() => {
-  initData()
-})
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.telemarketingDataManageToTask({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
+
+//tabClick
+const treeRef = ref();
+const tabIndex = ref(0);
+const tabClick = (item, index) => {
+  tabIndex.value = index;
+  treeRef.value?.getTree(item.api);
+};
 
+onMounted(() => {
+  initDefaultList();
+  treeRef.value?.getTree(api.manageApi.getDeptListByUserId);
+});
 </script>
 
 <style scoped lang="scss">
-.log{
+.log {
   width: 100%;
   height: calc(100vh - 120px);
-  background: #FFFFFF;
+  background: #ffffff;
   padding: 24px;
   overflow-y: auto;
-  .pagination{
-    margin-top: 24px;
+  .query-btn {
+    margin-left: 20px;
+  }
+  .btn-box {
+    padding-bottom: 15px;
+    margin-bottom: 24px;
+    border-bottom: 1px solid #eeeeee;
     display: flex;
-    align-items: center;
     justify-content: flex-end;
   }
+
+  .content-box {
+    justify-content: space-between;
+    .content-l {
+      width: 298px;
+      display: flex;
+      margin: 20px 16px 20px 0;
+      .item {
+        width: 50%;
+        height: 36px;
+        line-height: 36px;
+        background: #f7f7f7;
+        font-size: 16px;
+        text-align: center;
+        border-radius: 2px;
+      }
+      .active {
+        background: #0083ff;
+        color: #fff;
+      }
+    }
+    .content-r {
+      width: 0;
+    }
+  }
+}
+:deep(.caret-wrapper) {
+  display: none !important;
 }
 </style>

+ 316 - 140
src/views/consoleManage/quotationDataManage/quotationOrderData/index.vue

@@ -1,170 +1,346 @@
 <template>
   <div class="log">
-    <el-form label-width="100" label-position="left" :model="form">
-      <el-row :gutter="20">
-        <el-col :span="8">
-          <el-form-item label="操作人">
-            <el-input v-model="form.operator" placeholder="请输入操作人姓名查找"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作时间">
-            <el-date-picker
-              v-model="form.operatingTime"
-              type="daterange"
-              range-separator="至"
-              start-placeholder="开始时间"
-              end-placeholder="结束时间"
-              format="YYYY-MM-DD"
-              value-format="YYYY-MM-DD"
-              @change="timeChange"
-            />
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作功能">
-            <el-select v-model="form.function" placeholder="请选择">
-              <el-option label="工能1" value="1" key="1"></el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作内容">
-            <el-input v-model="form.content" placeholder="请输入"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="16" style="display: flex; align-items: center; justify-content: flex-end">
-          <el-button type="primary" @click="search">查询</el-button>
-          <el-button plain type="primary" @click="reset">重置</el-button>
-        </el-col>
-      </el-row>
-    </el-form>
-    <el-table
-      :data="tableData"
-      height="600"
-      style="margin-top: 24px"
-    >
-      <el-table-column label="操作人" prop="createBy" width="200"></el-table-column  >
-      <el-table-column label="操作时间" prop="createTime" width="240"></el-table-column>
-      <el-table-column label="操作功能" prop="moduleName"></el-table-column>
-      <el-table-column label="操作内容" prop="operationContent"></el-table-column>
-      <el-table-column label="类型" prop="operatorName" width="150"></el-table-column>
-      <el-table-column label="操作" width="150">
-        <template #default="scope">
-          <el-button link type="primary" @click="detail(scope.row)">查看详情</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <div class="pagination">
-      <el-pagination
-        v-model:current-page="pages"
-        v-model:page-size="size"
-        :page-sizes="[10, 20, 30, 40]"
-        layout="total, sizes, prev, pager, next, jumper"
-        :total="total"
-        @size-change="handleSizeChange"
-        @current-change="handleCurrentChange"
-      ></el-pagination>
+    <div class='btn-box'>
+      <el-button type="primary" plain class='query-btn'
+        @click='dialogShow'>{{selectedKeys.length?`已选${selectedKeys.length}项`:'筛选条件'}}</el-button>
+      <div class='query-btn'>
+        <DowButton @endAnim='downloadFile'></DowButton>
+      </div>
     </div>
+    <QueryForm :option="listOption" @query='query' @delSelect='delSelect' ref='queryFormRef'></QueryForm>
+    <div class='flex content-box'>
+      <!-- tree -->
+      <div class='content-l'>
+        <Tree ref='treeRef'></Tree>
+      </div>
+
+      <div class='flex-1 content-r'>
+        <!-- 表格 -->
+        <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
+          :columnwidth="120" :pageInfo="pageInfo" @getList="getList" :showOperation='false'>
+
+          <template v-slot:search="scope">
+            <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+              @update:sort="handleSortUpdate"></Sort>
+          </template>
+
+          <template #customSlot="{  bodyCell: { scope, column } }">
+            <template v-if="column.prop == 'underwriteOrderNum'">
+              {{ scope.row.underwriteOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'djOrderNum'">
+              {{ scope.row.djOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dsyOrderNum'">
+              {{ scope.row.dsyOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dszOrderNum'">
+              {{ scope.row.dszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jszOrderNum'">
+              {{ scope.row.jszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jsyOrderNum'">
+              {{ scope.row.jsyOrderNum }} 笔
+            </template>
+          </template>
+        </ComplexTable>
+      </div>
+    </div>
+
+    <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
+      routerKey='routerKey'>
+    </FilterDialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import { useRouter } from 'vue-router'
-import api from '@/api'
-import {ElMessage} from "element-plus";
+import { useRouter } from "vue-router";
+import api from "@/api";
+import QueryForm from "../../components/queryForm.vue";
+import FilterDialog from "../../components/filterDialog.vue";
+import DowButton from "../../components/button.vue";
+import Sort from "../../components/sort.vue";
+import useUserStore from "@/store/modules/message";
+import PageInfo from "@/api/types/agreementTypes";
+import Tree from "../../components/tree.vue";
+import { ElMessage } from "element-plus";
 
-const myRouter = useRouter()
+const router = useRouter();
+const userStore = useUserStore();
+const isShow = ref(false);
 
-let activeName = ref('first')
-const handleClick = () => {
+const isSort = ref();
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const listOption = reactive({
+  rowKey: "quotationId",
+  //查询
+  queryFormFields: [],
+  // 表格列
+  columns: [
+    {
+      prop: "salesmanName",
+      label: "车牌号",
+      width: "100",
+    },
+    {
+      prop: "salesmanPhone",
+      label: "发动机号",
+      width: "120",
+    },
+    {
+      prop: "deptName",
+      label: "车架号",
+      width: "300",
+    },
+    {
+      prop: "underwriteOrderNum",
+      label: "品牌型号",
+      width: "180",
+    },
+    {
+      prop: "sumPremium",
+      label: "报价订单",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "jqPremium",
+      label: "报价次数",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "taxPremium",
+      label: "最低保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "syPremium",
+      label: "最高保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "jyPremium",
+      label: "成交保险公司",
+      width: "180",
+    },
+    {
+      prop: "djOrderNum",
+      label: "成交保费",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+  ],
+});
 
-}
+const selectedKeys = ref([]);
+const selected = function (val) {
+  selectedKeys.value = val;
+};
 
-let form = ref({})
-const tableProps = ref({
-  value: "id",
-  label: "name",
-  children: "children",
-  checkStrictly: true,
-});
-let option = ref([])
-const timeChange = (val) => {
+//查询数据
+const phone = JSON.parse(localStorage.getItem("userInfo")).username;
 
-}
-// 搜索
-const search = () => {
-  pages.value = 1
-  size.value = 10
-  initData()
-}
-const reset = () => {
-  form.value = {}
-  pages.value = 1
-  size.value = 10
-  initData()
-}
+//获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("quotationOrderData");
+const defaultList = ref();
+const pageHiddenList = ref([]); //页面不显示的数据
+const initDefaultList = async () => {
+  const { data } = await api.manageApi.getSearchDefaultList({
+    routerKey: routerKey.value,
+    userId: phone,
+  });
+  listOption.queryFormFields = data.filter((e) => e.showFlag);
 
-// 列表
-let tableData = ref([])
-const detail = (row) => {
-  myRouter.push({
-    path: '/systemManage/logManage/logDetail',
-    query: {
-      id: row.id
-    }
-  })
-}
+  pageHiddenList.value = data.filter((e) => !e.showFlag);
+  defaultList.value = data.map((e) => e.id);
+  selectedKeys.value = defaultList.value;
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
+};
 
-// 分页
-let pages = ref(1)
-let size = ref(10)
-let total = ref(0)
-const handleSizeChange = (size) => {
-  size.value = size
-  initData()
-}
-const handleCurrentChange = (page) => {
-  pages.value = page
-  initData()
-}
+//删除
+const filterDialogRef = ref();
+const delSelect = (id) => {
+  listOption.queryFormFields = listOption.queryFormFields.filter(
+    (item) => item.id != id
+  );
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
 
-const initData = () => {
-  api.logApi.list({
-    pages: pages.value,
-    size: size.value,
-    ...form.value
-  }).then((res: any) => {
-    if(res.code === 200) {
-      tableData.value = res.data.records
-      total.value = res.data.total
-    } else {
-      ElMessage({
-        message: res.msg,
-        type: 'warning'
-      })
-    }
-  })
+//打开dialogShow
+const dialogShow = function () {
+  isShow.value = true;
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//确定
+const queryFormRef = ref();
+const filterSure = (item, index) => {
+  isShow.value = false;
+  const secondGroupIds = item.list.map((item) => item.id);
+  const oldList = listOption.queryFormFields.filter((item) =>
+    secondGroupIds.includes(item.id)
+  );
+  const firstGroupIds = listOption.queryFormFields.map((item) => item.id);
+  let newList = item.list.filter((item) => !firstGroupIds.includes(item.id));
+
+  //过滤掉默认不显示的数据
+  const hiddenList = new Set(pageHiddenList.value.map((item) => item.id));
+  const filterList = newList.filter((item) => !hiddenList.has(item.id));
+
+  listOption.queryFormFields = [...oldList, ...filterList];
+  queryFormRef.value?.initDefaultSaveForm();
+  selectedKeys.value = item.list.filter((item) => item.id);
+};
+
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
+
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
+
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.telemarketingDataManagePageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
+};
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
-onMounted(() => {
-  initData()
-})
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.telemarketingDataManageToTask({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
+
+
+//tabClick
+const treeRef = ref();
+const tabIndex = ref(0);
+const tabClick = (item, index) => {
+  tabIndex.value = index;
+  treeRef.value?.getTree(item.api);
+};
 
+onMounted(() => {
+  initDefaultList();
+  treeRef.value?.getTree(api.manageApi.getUserManageListByUserId);
+});
 </script>
 
 <style scoped lang="scss">
-.log{
+.log {
   width: 100%;
   height: calc(100vh - 120px);
-  background: #FFFFFF;
+  background: #ffffff;
   padding: 24px;
   overflow-y: auto;
-  .pagination{
-    margin-top: 24px;
+  .query-btn {
+    margin-left: 20px;
+  }
+  .btn-box {
+    padding-bottom: 15px;
+    margin-bottom: 24px;
+    border-bottom: 1px solid #eeeeee;
     display: flex;
-    align-items: center;
     justify-content: flex-end;
   }
+
+  .content-box {
+    justify-content: space-between;
+    .content-l {
+      width: 298px;
+      display: flex;
+      margin: 20px 16px 20px 0;
+      .item {
+        width: 50%;
+        height: 36px;
+        line-height: 36px;
+        background: #f7f7f7;
+        font-size: 16px;
+        text-align: center;
+        border-radius: 2px;
+      }
+      .active {
+        background: #0083ff;
+        color: #fff;
+      }
+    }
+    .content-r {
+      width: 0;
+    }
+  }
+}
+:deep(.caret-wrapper) {
+  display: none !important;
 }
 </style>

+ 350 - 140
src/views/consoleManage/quotationDataManage/salesmanQuotationData/index.vue

@@ -1,170 +1,380 @@
 <template>
   <div class="log">
-    <el-form label-width="100" label-position="left" :model="form">
-      <el-row :gutter="20">
-        <el-col :span="8">
-          <el-form-item label="操作人">
-            <el-input v-model="form.operator" placeholder="请输入操作人姓名查找"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作时间">
-            <el-date-picker
-              v-model="form.operatingTime"
-              type="daterange"
-              range-separator="至"
-              start-placeholder="开始时间"
-              end-placeholder="结束时间"
-              format="YYYY-MM-DD"
-              value-format="YYYY-MM-DD"
-              @change="timeChange"
-            />
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作功能">
-            <el-select v-model="form.function" placeholder="请选择">
-              <el-option label="工能1" value="1" key="1"></el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作内容">
-            <el-input v-model="form.content" placeholder="请输入"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="16" style="display: flex; align-items: center; justify-content: flex-end">
-          <el-button type="primary" @click="search">查询</el-button>
-          <el-button plain type="primary" @click="reset">重置</el-button>
-        </el-col>
-      </el-row>
-    </el-form>
-    <el-table
-      :data="tableData"
-      height="600"
-      style="margin-top: 24px"
-    >
-      <el-table-column label="操作人" prop="createBy" width="200"></el-table-column  >
-      <el-table-column label="操作时间" prop="createTime" width="240"></el-table-column>
-      <el-table-column label="操作功能" prop="moduleName"></el-table-column>
-      <el-table-column label="操作内容" prop="operationContent"></el-table-column>
-      <el-table-column label="类型" prop="operatorName" width="150"></el-table-column>
-      <el-table-column label="操作" width="150">
-        <template #default="scope">
-          <el-button link type="primary" @click="detail(scope.row)">查看详情</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <div class="pagination">
-      <el-pagination
-        v-model:current-page="pages"
-        v-model:page-size="size"
-        :page-sizes="[10, 20, 30, 40]"
-        layout="total, sizes, prev, pager, next, jumper"
-        :total="total"
-        @size-change="handleSizeChange"
-        @current-change="handleCurrentChange"
-      ></el-pagination>
+    <div class='btn-box'>
+      <el-button type="primary" plain class='query-btn'
+        @click='dialogShow'>{{selectedKeys.length?`已选${selectedKeys.length}项`:'筛选条件'}}</el-button>
+      <div class='query-btn'>
+        <DowButton @endAnim='downloadFile'></DowButton>
+      </div>
     </div>
+    <QueryForm :option="listOption" @query='query' @delSelect='delSelect' ref='queryFormRef'></QueryForm>
+    <div class='flex content-box'>
+      <!-- tree -->
+      <div class='content-l'>
+        <Tree ref='treeRef'></Tree>
+      </div>
+
+      <div class='flex-1 content-r'>
+        <!-- 表格 -->
+        <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
+          :columnwidth="120" :pageInfo="pageInfo" @getList="getList" :showOperation='false'>
+
+          <template v-slot:search="scope">
+            <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+              @update:sort="handleSortUpdate"></Sort>
+          </template>
+
+          <template #customSlot="{  bodyCell: { scope, column } }">
+            <template v-if="column.prop == 'underwriteOrderNum'">
+              {{ scope.row.underwriteOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'djOrderNum'">
+              {{ scope.row.djOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dsyOrderNum'">
+              {{ scope.row.dsyOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dszOrderNum'">
+              {{ scope.row.dszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jszOrderNum'">
+              {{ scope.row.jszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jsyOrderNum'">
+              {{ scope.row.jsyOrderNum }} 笔
+            </template>
+          </template>
+        </ComplexTable>
+      </div>
+    </div>
+
+    <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
+      routerKey='routerKey'>
+    </FilterDialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import { useRouter } from 'vue-router'
-import api from '@/api'
-import {ElMessage} from "element-plus";
+import { useRouter } from "vue-router";
+import api from "@/api";
+import QueryForm from "../../components/queryForm.vue";
+import FilterDialog from "../../components/filterDialog.vue";
+import DowButton from "../../components/button.vue";
+import Sort from "../../components/sort.vue";
+import useUserStore from "@/store/modules/message";
+import PageInfo from "@/api/types/agreementTypes";
+import Tree from "../../components/tree.vue";
+import { ElMessage } from "element-plus";
 
-const myRouter = useRouter()
+const router = useRouter();
+const userStore = useUserStore();
+const isShow = ref(false);
 
-let activeName = ref('first')
-const handleClick = () => {
+const isSort = ref();
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const listOption = reactive({
+  rowKey: "salesmanQuotationId",
+  //查询
+  queryFormFields: [],
+  // 表格列
+  columns: [
+    {
+      prop: "salesmanName",
+      label: "保险公司",
+      width: "100",
+    },
+    {
+      prop: "salesmanPhone",
+      label: "合作保险公司",
+      width: "120",
+    },
+    {
+      prop: "deptName",
+      label: "报价数量",
+      width: "300",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "underwriteOrderNum",
+      label: "报价量占比",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "sumPremium",
+      label: "报价成功",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "jqPremium",
+      label: "报价失败",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "taxPremium",
+      label: "平均报价响应时间",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "syPremium",
+      label: "提交核保",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "jyPremium",
+      label: "人工核保数",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "核保通过",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "核保不通过",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "核保通过率",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "成交单数",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "转化率",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+  ],
+});
 
-}
+const selectedKeys = ref([]);
+const selected = function (val) {
+  selectedKeys.value = val;
+};
 
-let form = ref({})
-const tableProps = ref({
-  value: "id",
-  label: "name",
-  children: "children",
-  checkStrictly: true,
-});
-let option = ref([])
-const timeChange = (val) => {
+//查询数据
+const phone = JSON.parse(localStorage.getItem("userInfo")).username;
 
-}
-// 搜索
-const search = () => {
-  pages.value = 1
-  size.value = 10
-  initData()
-}
-const reset = () => {
-  form.value = {}
-  pages.value = 1
-  size.value = 10
-  initData()
-}
+//获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("salesmanQuotationData");
+const defaultList = ref();
+const pageHiddenList = ref([]); //页面不显示的数据
+const initDefaultList = async () => {
+  const { data } = await api.manageApi.getSearchDefaultList({
+    routerKey: routerKey.value,
+    userId: phone,
+  });
+  listOption.queryFormFields = data.filter((e) => e.showFlag);
 
-// 列表
-let tableData = ref([])
-const detail = (row) => {
-  myRouter.push({
-    path: '/systemManage/logManage/logDetail',
-    query: {
-      id: row.id
-    }
-  })
-}
+  pageHiddenList.value = data.filter((e) => !e.showFlag);
+  defaultList.value = data.map((e) => e.id);
+  selectedKeys.value = defaultList.value;
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
+};
 
-// 分页
-let pages = ref(1)
-let size = ref(10)
-let total = ref(0)
-const handleSizeChange = (size) => {
-  size.value = size
-  initData()
-}
-const handleCurrentChange = (page) => {
-  pages.value = page
-  initData()
-}
+//删除
+const filterDialogRef = ref();
+const delSelect = (id) => {
+  listOption.queryFormFields = listOption.queryFormFields.filter(
+    (item) => item.id != id
+  );
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
 
-const initData = () => {
-  api.logApi.list({
-    pages: pages.value,
-    size: size.value,
-    ...form.value
-  }).then((res: any) => {
-    if(res.code === 200) {
-      tableData.value = res.data.records
-      total.value = res.data.total
-    } else {
-      ElMessage({
-        message: res.msg,
-        type: 'warning'
-      })
-    }
-  })
+//打开dialogShow
+const dialogShow = function () {
+  isShow.value = true;
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//确定
+const queryFormRef = ref();
+const filterSure = (item, index) => {
+  isShow.value = false;
+  const secondGroupIds = item.list.map((item) => item.id);
+  const oldList = listOption.queryFormFields.filter((item) =>
+    secondGroupIds.includes(item.id)
+  );
+  const firstGroupIds = listOption.queryFormFields.map((item) => item.id);
+  let newList = item.list.filter((item) => !firstGroupIds.includes(item.id));
+
+  //过滤掉默认不显示的数据
+  const hiddenList = new Set(pageHiddenList.value.map((item) => item.id));
+  const filterList = newList.filter((item) => !hiddenList.has(item.id));
+
+  listOption.queryFormFields = [...oldList, ...filterList];
+  queryFormRef.value?.initDefaultSaveForm();
+  selectedKeys.value = item.list.filter((item) => item.id);
+};
+
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
+
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
+
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.telemarketingDataManagePageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
+};
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
-onMounted(() => {
-  initData()
-})
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.telemarketingDataManageToTask({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
+
+//tabClick
+const treeRef = ref();
+const tabIndex = ref(0);
+const tabClick = (item, index) => {
+  tabIndex.value = index;
+  treeRef.value?.getTree(item.api);
+};
 
+onMounted(() => {
+  initDefaultList();
+  treeRef.value?.getTree(api.manageApi.getDeptListByUserId);
+});
 </script>
 
 <style scoped lang="scss">
-.log{
+.log {
   width: 100%;
   height: calc(100vh - 120px);
-  background: #FFFFFF;
+  background: #ffffff;
   padding: 24px;
   overflow-y: auto;
-  .pagination{
-    margin-top: 24px;
+  .query-btn {
+    margin-left: 20px;
+  }
+  .btn-box {
+    padding-bottom: 15px;
+    margin-bottom: 24px;
+    border-bottom: 1px solid #eeeeee;
     display: flex;
-    align-items: center;
     justify-content: flex-end;
   }
+
+  .content-box {
+    justify-content: space-between;
+    .content-l {
+      width: 298px;
+      display: flex;
+      margin: 20px 16px 20px 0;
+      .item {
+        width: 50%;
+        height: 36px;
+        line-height: 36px;
+        background: #f7f7f7;
+        font-size: 16px;
+        text-align: center;
+        border-radius: 2px;
+      }
+      .active {
+        background: #0083ff;
+        color: #fff;
+      }
+    }
+    .content-r {
+      width: 0;
+    }
+  }
+}
+:deep(.caret-wrapper) {
+  display: none !important;
 }
 </style>

+ 350 - 140
src/views/consoleManage/quotationDataManage/telemarketingQuotationData/index.vue

@@ -1,170 +1,380 @@
 <template>
   <div class="log">
-    <el-form label-width="100" label-position="left" :model="form">
-      <el-row :gutter="20">
-        <el-col :span="8">
-          <el-form-item label="操作人">
-            <el-input v-model="form.operator" placeholder="请输入操作人姓名查找"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作时间">
-            <el-date-picker
-              v-model="form.operatingTime"
-              type="daterange"
-              range-separator="至"
-              start-placeholder="开始时间"
-              end-placeholder="结束时间"
-              format="YYYY-MM-DD"
-              value-format="YYYY-MM-DD"
-              @change="timeChange"
-            />
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作功能">
-            <el-select v-model="form.function" placeholder="请选择">
-              <el-option label="工能1" value="1" key="1"></el-option>
-            </el-select>
-          </el-form-item>
-        </el-col>
-        <el-col :span="8">
-          <el-form-item label="操作内容">
-            <el-input v-model="form.content" placeholder="请输入"></el-input>
-          </el-form-item>
-        </el-col>
-        <el-col :span="16" style="display: flex; align-items: center; justify-content: flex-end">
-          <el-button type="primary" @click="search">查询</el-button>
-          <el-button plain type="primary" @click="reset">重置</el-button>
-        </el-col>
-      </el-row>
-    </el-form>
-    <el-table
-      :data="tableData"
-      height="600"
-      style="margin-top: 24px"
-    >
-      <el-table-column label="操作人" prop="createBy" width="200"></el-table-column  >
-      <el-table-column label="操作时间" prop="createTime" width="240"></el-table-column>
-      <el-table-column label="操作功能" prop="moduleName"></el-table-column>
-      <el-table-column label="操作内容" prop="operationContent"></el-table-column>
-      <el-table-column label="类型" prop="operatorName" width="150"></el-table-column>
-      <el-table-column label="操作" width="150">
-        <template #default="scope">
-          <el-button link type="primary" @click="detail(scope.row)">查看详情</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <div class="pagination">
-      <el-pagination
-        v-model:current-page="pages"
-        v-model:page-size="size"
-        :page-sizes="[10, 20, 30, 40]"
-        layout="total, sizes, prev, pager, next, jumper"
-        :total="total"
-        @size-change="handleSizeChange"
-        @current-change="handleCurrentChange"
-      ></el-pagination>
+    <div class='btn-box'>
+      <el-button type="primary" plain class='query-btn'
+        @click='dialogShow'>{{selectedKeys.length?`已选${selectedKeys.length}项`:'筛选条件'}}</el-button>
+      <div class='query-btn'>
+        <DowButton @endAnim='downloadFile'></DowButton>
+      </div>
     </div>
+    <QueryForm :option="listOption" @query='query' @delSelect='delSelect' ref='queryFormRef'></QueryForm>
+    <div class='flex content-box'>
+      <!-- tree -->
+      <div class='content-l'>
+        <Tree ref='treeRef'></Tree>
+      </div>
+
+      <div class='flex-1 content-r'>
+        <!-- 表格 -->
+        <ComplexTable :tableData="tableData" :showSelect='false' :columns="listOption.columns" :showIndex="false"
+          :columnwidth="120" :pageInfo="pageInfo" @getList="getList" :showOperation='false'>
+
+          <template v-slot:search="scope">
+            <Sort :scope="scope.slotData" :globalSortKey="globalSortKey" :globalSortOrder="globalSortOrder"
+              @update:sort="handleSortUpdate"></Sort>
+          </template>
+
+          <template #customSlot="{  bodyCell: { scope, column } }">
+            <template v-if="column.prop == 'underwriteOrderNum'">
+              {{ scope.row.underwriteOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'djOrderNum'">
+              {{ scope.row.djOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dsyOrderNum'">
+              {{ scope.row.dsyOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'dszOrderNum'">
+              {{ scope.row.dszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jszOrderNum'">
+              {{ scope.row.jszOrderNum }} 笔
+            </template>
+            <template v-if="column.prop == 'jsyOrderNum'">
+              {{ scope.row.jsyOrderNum }} 笔
+            </template>
+          </template>
+        </ComplexTable>
+      </div>
+    </div>
+
+    <FilterDialog :show='isShow' @close='isShow=false' @sure='filterSure' ref='filterDialogRef' @selectedKeys='selected'
+      routerKey='routerKey'>
+    </FilterDialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import { useRouter } from 'vue-router'
-import api from '@/api'
-import {ElMessage} from "element-plus";
+import { useRouter } from "vue-router";
+import api from "@/api";
+import QueryForm from "../../components/queryForm.vue";
+import FilterDialog from "../../components/filterDialog.vue";
+import DowButton from "../../components/button.vue";
+import Sort from "../../components/sort.vue";
+import useUserStore from "@/store/modules/message";
+import PageInfo from "@/api/types/agreementTypes";
+import Tree from "../../components/tree.vue";
+import { ElMessage } from "element-plus";
 
-const myRouter = useRouter()
+const router = useRouter();
+const userStore = useUserStore();
+const isShow = ref(false);
 
-let activeName = ref('first')
-const handleClick = () => {
+const isSort = ref();
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const listOption = reactive({
+  rowKey: "telemarketingQuotationId",
+  //查询
+  queryFormFields: [],
+  // 表格列
+  columns: [
+    {
+      prop: "salesmanName",
+      label: "保险公司",
+      width: "100",
+    },
+    {
+      prop: "salesmanPhone",
+      label: "合作保险公司",
+      width: "120",
+    },
+    {
+      prop: "deptName",
+      label: "报价数量",
+      width: "300",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "underwriteOrderNum",
+      label: "报价量占比",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "sumPremium",
+      label: "报价成功",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "jqPremium",
+      label: "报价失败",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "taxPremium",
+      label: "平均报价响应时间",
+      width: "180",
+      align: "right",
+      sortable: true,
+      component: "customSlot",
+    },
+    {
+      prop: "syPremium",
+      label: "提交核保",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "jyPremium",
+      label: "人工核保数",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "核保通过",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "核保不通过",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "核保通过率",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "成交单数",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+    {
+      prop: "djOrderNum",
+      label: "转化率",
+      width: "180",
+      align: "right",
+      sortable: true,
+    },
+  ],
+});
 
-}
+const selectedKeys = ref([]);
+const selected = function (val) {
+  selectedKeys.value = val;
+};
 
-let form = ref({})
-const tableProps = ref({
-  value: "id",
-  label: "name",
-  children: "children",
-  checkStrictly: true,
-});
-let option = ref([])
-const timeChange = (val) => {
+//查询数据
+const phone = JSON.parse(localStorage.getItem("userInfo")).username;
 
-}
-// 搜索
-const search = () => {
-  pages.value = 1
-  size.value = 10
-  initData()
-}
-const reset = () => {
-  form.value = {}
-  pages.value = 1
-  size.value = 10
-  initData()
-}
+//获取默认选择数据
+const queryFormRes = ref();
+const routerKey = ref("telemarketingQuotationData");
+const defaultList = ref();
+const pageHiddenList = ref([]); //页面不显示的数据
+const initDefaultList = async () => {
+  const { data } = await api.manageApi.getSearchDefaultList({
+    routerKey: routerKey.value,
+    userId: phone,
+  });
+  listOption.queryFormFields = data.filter((e) => e.showFlag);
 
-// 列表
-let tableData = ref([])
-const detail = (row) => {
-  myRouter.push({
-    path: '/systemManage/logManage/logDetail',
-    query: {
-      id: row.id
-    }
-  })
-}
+  pageHiddenList.value = data.filter((e) => !e.showFlag);
+  defaultList.value = data.map((e) => e.id);
+  selectedKeys.value = defaultList.value;
+  queryFormRes.value = queryFormRef.value?.initDefaultSaveForm();
+  queryList();
+};
 
-// 分页
-let pages = ref(1)
-let size = ref(10)
-let total = ref(0)
-const handleSizeChange = (size) => {
-  size.value = size
-  initData()
-}
-const handleCurrentChange = (page) => {
-  pages.value = page
-  initData()
-}
+//删除
+const filterDialogRef = ref();
+const delSelect = (id) => {
+  listOption.queryFormFields = listOption.queryFormFields.filter(
+    (item) => item.id != id
+  );
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
 
-const initData = () => {
-  api.logApi.list({
-    pages: pages.value,
-    size: size.value,
-    ...form.value
-  }).then((res: any) => {
-    if(res.code === 200) {
-      tableData.value = res.data.records
-      total.value = res.data.total
-    } else {
-      ElMessage({
-        message: res.msg,
-        type: 'warning'
-      })
-    }
-  })
+//打开dialogShow
+const dialogShow = function () {
+  isShow.value = true;
+  filterDialogRef.value.initList(
+    [...listOption.queryFormFields, ...pageHiddenList.value],
+    defaultList.value
+  );
+};
+
+//确定
+const queryFormRef = ref();
+const filterSure = (item, index) => {
+  isShow.value = false;
+  const secondGroupIds = item.list.map((item) => item.id);
+  const oldList = listOption.queryFormFields.filter((item) =>
+    secondGroupIds.includes(item.id)
+  );
+  const firstGroupIds = listOption.queryFormFields.map((item) => item.id);
+  let newList = item.list.filter((item) => !firstGroupIds.includes(item.id));
+
+  //过滤掉默认不显示的数据
+  const hiddenList = new Set(pageHiddenList.value.map((item) => item.id));
+  const filterList = newList.filter((item) => !hiddenList.has(item.id));
+
+  listOption.queryFormFields = [...oldList, ...filterList];
+  queryFormRef.value?.initDefaultSaveForm();
+  selectedKeys.value = item.list.filter((item) => item.id);
+};
+
+const globalSortKey = ref("");
+const globalSortOrder = ref<"asc" | "desc">("asc");
+//  处理子组件传递的排序更新
+const handleSortUpdate = (sortInfo: {
+  key: string;
+  order: string;
+  name: string;
+}) => {
+  globalSortKey.value = sortInfo.key;
+  globalSortOrder.value = sortInfo.order;
+  queryList();
+};
+
+//查询
+const query = (item) => {
+  queryFormRes.value = item;
+  queryList();
+};
+
+//数据查询
+const tableData = ref([]);
+const queryList = async () => {
+  let query = { ...queryFormRes.value };
+  const { data } = await api.manageApi.telemarketingDataManagePageList({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  tableData.value = data.records;
+  pageInfo.value.pageNum = data.current;
+  pageInfo.value.pageSize = data.size;
+  pageInfo.value.total = data.total;
+};
+
+//分页事件
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  queryList();
 }
 
-onMounted(() => {
-  initData()
-})
+//导出
+const downloadFile = async () => {
+  let query = { ...queryFormRes.value };
+  const { data, msg } = await api.manageApi.telemarketingDataManageToTask({
+    pageNo: pageInfo.value.pageNum,
+    pageSize: pageInfo.value.pageSize,
+    routerKey: routerKey.value,
+    userId: phone,
+    orderType: globalSortKey.value
+      ? globalSortKey.value + " " + globalSortOrder.value
+      : "",
+    ...query,
+  });
+  ElMessage({
+    message: msg,
+    type: "success",
+  });
+  userStore.count++;
+};
+
+//tabClick
+const treeRef = ref();
+const tabIndex = ref(0);
+const tabClick = (item, index) => {
+  tabIndex.value = index;
+  treeRef.value?.getTree(item.api);
+};
 
+onMounted(() => {
+  initDefaultList();
+  treeRef.value?.getTree(api.manageApi.getDeptListByUserId);
+});
 </script>
 
 <style scoped lang="scss">
-.log{
+.log {
   width: 100%;
   height: calc(100vh - 120px);
-  background: #FFFFFF;
+  background: #ffffff;
   padding: 24px;
   overflow-y: auto;
-  .pagination{
-    margin-top: 24px;
+  .query-btn {
+    margin-left: 20px;
+  }
+  .btn-box {
+    padding-bottom: 15px;
+    margin-bottom: 24px;
+    border-bottom: 1px solid #eeeeee;
     display: flex;
-    align-items: center;
     justify-content: flex-end;
   }
+
+  .content-box {
+    justify-content: space-between;
+    .content-l {
+      width: 298px;
+      display: flex;
+      margin: 20px 16px 20px 0;
+      .item {
+        width: 50%;
+        height: 36px;
+        line-height: 36px;
+        background: #f7f7f7;
+        font-size: 16px;
+        text-align: center;
+        border-radius: 2px;
+      }
+      .active {
+        background: #0083ff;
+        color: #fff;
+      }
+    }
+    .content-r {
+      width: 0;
+    }
+  }
+}
+:deep(.caret-wrapper) {
+  display: none !important;
 }
 </style>