Browse Source

合同派点、研究员派点统计(日期选择组件未替换)

hbchen 1 year ago
parent
commit
37beee62ce

+ 16 - 18
src/router/modules/contractRoutes.js

@@ -140,24 +140,22 @@ export default [
 					title: '代付合同修改重审'
 				}
 			},
-			// {
-			// 	path:"raiAllocationPage",
-			// 	component:()=>import("@/views/contract_manage/raiAllocationPage.vue"),
-			// 	name:"合同派点",
-			// 	hidden:false,
-			// 	meta: {
-			// 		keepAlive: false
-			// 	}
-			// },
-			// {
-			// 	path:"researcherStatistics",
-			// 	component:()=>import("@/views/contract_manage/researcherStatistics.vue"),
-			// 	name:"研究员派点统计",
-			// 	hidden:false,
-			// 	meta: {
-			// 		keepAlive: false
-			// 	}
-			// }
+			{
+				path:"raiAllocationPage",
+				component:()=>import("@/views/contract_manage/raiAllocationPage.vue"),
+				name:"raiAllocationPage",
+				meta: {
+					title: '合同派点'
+				}
+			},
+			{
+				path:"researcherStatistics",
+				component:()=>import("@/views/contract_manage/researcherStatistics.vue"),
+				name:"researcherStatistics",
+				meta: {
+					title: '研究员派点统计'
+				}
+			}
 		]
 	},
 ]

+ 153 - 0
src/views/contract_manage/components/allocationDetail.vue

@@ -0,0 +1,153 @@
+<script setup>
+import { ref,watch } from "vue";
+
+import { contractInterface } from "@/api/api.js";
+
+const props = defineProps({
+  allocationDetailVisible: {
+    type: Boolean,
+    default: true,
+  },
+  allocationDetailForm: {
+    type: Object,
+    default: {},
+  }
+})
+const emits=defineEmits(['update:allocationDetailForm','update:allocationDetailVisible','allocationDetailList'])
+
+const datalist=ref([])
+const IsGray=ref(false)
+const allNum=ref("")
+
+// 关闭弹框
+const handleClose=()=>{
+  datalist.value = [];
+
+  emits("update:allocationDetailForm", {});
+  emits("update:allocationDetailVisible", false);
+}
+
+// 点击修改的事件
+const addAllocationHandler=()=>{
+  if (IsGray.value) return;
+  handleClose();
+  emits("allocationDetailList", props.allocationDetailForm);
+}
+const processingData=()=>{
+  for (let index = 0; index < datalist.value.length; index++) {}
+}
+// 获取数据
+const getList=async()=>{
+  const res = await contractInterface.getAllocationDetail({
+    CompanyContractId: props.allocationDetailForm.CompanyContractId,
+    ShowDetail: true,
+  });
+  if (res.Ret === 200) {
+    IsGray.value = res.Data.IsGray;
+    let maxLength = 0;
+    res.Data.List &&
+      res.Data.List.forEach((item) => {
+        if (maxLength < item.List.length) {
+          maxLength = item.List.length;
+        }
+      });
+    res.Data.List &&
+      res.Data.List.forEach((item) => {
+        for (let index = 0; index < maxLength; index++) {
+          item.List[index] = {
+            name: item.List[index] ? item.List[index].RealName : "",
+            val: item.List[index] ? item.List[index].Money : "",
+          };
+        }
+      });
+    datalist.value = res.Data.List;
+    allNum.value = res.Data.TotalPointsContent;
+  }
+}
+
+watch(()=>props.allocationDetailVisible,(newVal)=>{
+  newVal && getList();
+},
+{deep:true,immediate:true})
+
+</script>
+
+<template>
+  <el-dialog
+    :title="allocationDetailForm.isDlgType == '关联合同' ? '打分详情' : '派点详情'"
+    width="1200px"
+    v-model="props.allocationDetailVisible"
+    v-dialogDrag
+    :close-on-click-modal="false"
+    :modal-append-to-body="false"
+    center
+    @close="handleClose"
+    :append-to-body="true"
+    class="allocation-detail-content_rai"
+  >
+    <p>总点数:{{ allNum }}</p>
+    <div class="content-box-table-detail">
+      <div class="table-cont table-cont-top">
+        <div style="display: flex" v-for="item in datalist" :key="item.ChartPermissionName">
+          <div :class="['head-column', 'head-column-item']" style="font-weight: 800;font-size:16px">
+            {{ item.ChartPermissionName }}
+          </div>
+          <div :class="['head-column', 'head-column-item-Proportion']">
+            {{ item.Money }}
+          </div>
+        </div>
+      </div>
+      <div class="table-cont">
+        <div v-for="(item, index) in datalist" :key="index">
+          <div style="display: flex" v-for="rs in item.List" :key="rs.RealName" class="content-ul">
+            <div style="background-color: #fff" :class="['head-column', 'head-column-item']">{{ rs.name }}</div>
+            <div style="background-color: #fff" :class="['head-column', 'head-column-item-Proportion']">{{ rs.val }}</div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <template #footer>
+      <span  class="dialog-footer">
+        <el-button @click="handleClose" size="large">取 消</el-button>
+        <el-button v-if="allocationDetailForm.isDlgType != '关联合同'" :disabled="IsGray" type="primary" @click="addAllocationHandler"
+        size="large">修 改</el-button>
+      </span>
+    </template>
+
+  </el-dialog>
+</template>
+
+<style lang="scss">
+.allocation-detail-content_rai {
+  .content-box-table-detail {
+    position: relative;
+    margin-top: 20px;
+    .table-cont-top {
+      position: sticky;
+      top: 0;
+      left: 0;
+    }
+    .table-cont {
+      display: flex;
+    }
+    .head-column {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      border: 1px solid #dcdfe6;
+      background-color: #ebeef5;
+      color: #333333;
+      margin-top: -1px;
+      margin-left: -0.5px;
+    }
+    .head-column-item {
+      width: 107px;
+      height: 48px;
+    }
+    .head-column-item-Proportion {
+      width: 73px;
+      height: 48px;
+    }
+  }
+}
+</style>

+ 114 - 0
src/views/contract_manage/components/allocationLable.vue

@@ -0,0 +1,114 @@
+<script setup>
+import { contractInterface } from "@/api/api.js";
+import { useRouter} from 'vue-router';
+import { ElLoading } from 'element-plus'
+
+const $router = useRouter()
+
+const props = defineProps({
+  tableList: {
+    type: Array,
+    default: [],
+  },
+  typeLable: {
+    type: String,
+    default: "",
+  },
+})
+const emits=defineEmits(['isPreviewHistoryDetail','allocationDetail','allocationDetailList'])
+
+// 查看合同
+const lookContractHandler=async(item)=>{
+  if (item.FormalType == "非标") {
+    const loading = ElLoading.service({
+      lock: true,
+      text: "Loading",
+      spinner: "el-icon-loading",
+      background: "rgba(0, 0, 0, 0.7)",
+    });
+    const res = await contractInterface.getHistoryDetail({
+      ContractCode: item.ContractCode,
+    });
+    if (res.Ret === 200) {
+      emits("isPreviewHistoryDetail", res);
+      loading.close();
+    }
+  } else {
+    let { href } = $router.resolve({
+      path: "/contractdtl",
+      query: { contractid: item.ContractId },
+    });
+    window.open(href, "_blank");
+  }
+}
+
+// 查看公司详情
+const lookCompanyNameHandler=(item)=>{
+  const { href } = $router.resolve({
+    path: "/customDetail",
+    query: {
+      id: item.CompanyId,
+    },
+  });
+  window.open(href, "_blank");
+}
+// 派点详情
+const detailsHandler=(item)=>{
+  emits("allocationDetail", item);
+}
+// 派点
+const allocationDetail=(item)=>{
+  if (item.IsGray) return;
+  emits("allocationDetailList", item);
+}
+
+</script>
+
+<template>
+  <div>
+    <el-table border :data="props.tableList" size="large">
+      <el-table-column align="center" prop="ContractCode" label="合同编号" width="160">
+        <template #default="{ row }">
+          <span class="editsty" @click="lookContractHandler(row)">{{ row.ContractCode }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" prop="FormalType" label="转正类型" width="90"> </el-table-column>
+      <el-table-column align="center" prop="ContractType" label="合同类型" width="100"></el-table-column>
+      <el-table-column align="center" prop="CompanyName" label="公司名称">
+        <template #default="{ row }">
+          <span class="editsty" @click="lookCompanyNameHandler(row)">{{ row.CompanyName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" prop="SellerName" label="所属销售" width="90"> </el-table-column>
+      <el-table-column align="center" prop="Money" label="合同金额" width="130"> </el-table-column>
+      <el-table-column align="center" prop="StartDate" label="合同期限" width="200">
+        <template #default="{ row }">
+          <span>{{ `${row.StartDate} - ${row.EndDate}` }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" prop="PermissionName" label="签约套餐" width="200">
+        <template #default="{ row }">
+          <el-tag style="margin: 0 10px 5px 0" v-for="item in row.PermissionName.split(',')" :key="item" size="small">{{ item }}</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" prop="IsAllocation" label="状态" width="90" v-if="!props.typeLable">
+        <template #default="{ row }">
+          <span :style="{ color: row.IsAllocation == 0 ? '#FF8A00' : row.IsAllocation == 1 ? '#67C23A' : '' }">{{ row.IsAllocation == 0 ? "未派点" : row.IsAllocation == 1 ? "已派点" : "" }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" prop="MoneyPoint" label="获得派点" width="90" v-if="props.typeLable"> </el-table-column>
+      <el-table-column align="center" prop="ContractCode" label="操作" v-if="!props.typeLable">
+        <template #default="{ row }">
+          <span v-if="row.IsAllocation == 0" :class="row.IsGray ? '' : 'editsty'" @click="allocationDetail(row)">派点</span>
+          <span v-if="row.IsAllocation == 1" class="editsty" @click="detailsHandler(row)">派点详情</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" prop="ContractCode" width="110" label="派点详情" v-if="props.typeLable">
+        <template #default="{ row }">
+          <span class="editsty" @click="detailsHandler(row)">查看</span>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+<style scoped lang=""></style>

+ 242 - 0
src/views/contract_manage/components/allocationNumber.vue

@@ -0,0 +1,242 @@
+<script setup>
+import { ref,reactive,watch } from "vue";
+import {ElMessage} from "element-plus"
+
+import { contractInterface } from "@/api/api.js";
+
+
+const props = defineProps({
+  allocationVisible: {
+    default: false,
+    type: Boolean,
+  },
+  allocationForm: {
+    type: Object,
+    default: {},
+  }
+})
+const emits=defineEmits(['update:allocationForm','update:allocationVisible','emitGetTableData'])
+
+const listObj=reactive({
+  listArr:[]
+})
+const allNum=ref(0)
+const TotalPointsContent=ref("")
+
+// 取消弹框
+const handleClose=()=>{
+  listObj.listArr = [];
+  emits("update:allocationForm", {});
+  emits("update:allocationVisible", false);
+}
+// 提交弹框
+const addAllocationHandler=async()=>{
+  listObj.listArr.forEach((item,index) => {
+    item.Money = Number(item.Money) || 0;
+    item.Proportion = Number(item.Proportion) || 0;
+    item.List.forEach((_) => {
+      _.Money = Number(_.Money) || 0;
+      _.Proportion = Number(_.Proportion) || 0;
+    });
+  });
+  let arrList = listObj.listArr;
+  const res = await contractInterface.getAllocationDetailUpdate({
+    CompanyContractId: props.allocationForm.CompanyContractId,
+    List: arrList,
+  });
+  if (res.Ret === 200) {
+    ElMessage.success("操作成功");
+    emits('emitGetTableData')
+    handleClose();
+  }
+}
+// 处理百分比
+const roundedResult=(row)=>{
+  let num = row.Proportion >= 0 ? (row.Proportion * 100) / 100 / 100 : row.Proportion / 100;
+  row.Money = Number(row.Proportion ? (allNum.value * num).toFixed(2) : '') || 0
+  return row.Money;
+}
+// 输入框的限制
+const restrictInput=(item)=>{
+  if (item.Proportion > 100) return (item.Proportion = 100);
+  if (item.Proportion < -100) return (item.Proportion = -100);
+}
+
+// 数量的总和
+const allPerCentHandler=(item)=>{
+  let num = 0;
+  item && item.List.forEach((key) => (num = num + +key.Proportion));
+  return num.toFixed(2);
+}
+// 获取数据
+const getList=async()=>{
+  const res = await contractInterface.getAllocationDetail({
+    CompanyContractId: props.allocationForm.CompanyContractId,
+  });
+  if (res.Ret === 200) {
+    allNum.value = res.Data.Money;
+    listObj.listArr = res.Data.List;
+    TotalPointsContent.value = res.Data.TotalPointsContent;
+  }
+}
+// 平均分配
+const averageaAllocation=()=>{
+  let isName = [];
+  listObj.listArr.forEach((item) => {
+    if (!item.ChartPermissionName.includes("研选")) {
+      isName.push(true);
+    }
+  });
+  let num = 100 / isName.length;
+  listObj.listArr.forEach((item) => {
+    if (item.ChartPermissionName != "研选订阅" && item.ChartPermissionName != "研选扣点包") {
+      item.Proportion = num;
+    }
+    let childrenNum = num / item.List.length;
+    item.List.forEach((key) => {
+      if (key.RealName != "研选订阅" && key.RealName != "研选扣点包") {
+        key.Proportion = Math.round(childrenNum*100)/100;
+      }
+    });
+  });
+}
+
+watch(()=>props.allocationVisible,(newVal)=>{
+  newVal && getList();
+},
+{immediate:true})
+
+</script>
+
+<template>
+  <div class="container-allocation-number-rai">
+    <el-dialog title="派点" width="1300px" v-model="props.allocationVisible" v-dialogDrag :close-on-click-modal="false" :modal-append-to-body="false" center @close="handleClose">
+      <div class="top-content">
+        <div>
+          <h5>总点数:{{ TotalPointsContent }}</h5>
+          <el-button style="margin-top: 20px" type="primary" @click="averageaAllocation">平均分配</el-button>
+        </div>
+
+        <p>
+          1)单行业套餐只能在对应行业内部分配研究员贡献百分比<br />
+          2)多行业套餐先在行业间分配百分比(最低不低于平均值的一半),再分配到个人<br />
+          3)允许总额20%以内的负分<br />
+          4)转正后一个季度内可以提交和修改
+          <br />
+        </p>
+      </div>
+      <div class="content-box">
+        <div v-for="item in listObj.listArr" :key="item.ChartPermissionName">
+          <div class="industry-ul">
+            <span :class="['industry-name', item.ChartPermissionId == '31' && 'name-yanxuan', item.ChartPermissionId == '52' && 'points-name']">{{ item.ChartPermissionName }}</span>
+            <template v-if="item.ChartPermissionId != '31' && item.ChartPermissionId != '52'">
+              <el-input :min="-100" :max="100" type="number" v-model="item.Proportion" @input="restrictInput(item)" style="width: 76px; margin: 0 5px 0 8px">
+                <template #suffix>
+                  <div class="per_cent_">%</div>
+                </template>
+              </el-input>
+              <p style="width: 38px">{{ roundedResult(item) }}</p>
+            </template>
+            <p style="width: 38px; height: 32px; line-height: 32px; text-align: center" v-else>{{ item.Money }}</p>
+          </div>
+          <div v-for="study in item.List" :key="study.RealName" class="industry-ul">
+            <span :class="['study-name', item.ChartPermissionId == '31' && 'name-yanxuan', item.ChartPermissionId == '52' && 'points-name']">{{ study.RealName }}</span>
+            <template v-if="!study.RealName.includes('研选')">
+              <el-input :min="-100" :max="100" type="number" v-model="study.Proportion" style="width: 76px; margin: 0 5px 0 8px">
+                <template #suffix>
+                  <div class="per_cent_">%</div>
+                </template>
+              </el-input>
+              <p style="width: 38px">{{ roundedResult(study) }}</p>
+            </template>
+            <p style="width: 38px; height: 32px; line-height: 32px; text-align: center" v-else>{{ study.Money }}</p>
+          </div>
+          <div class="all-item" v-if="item.ChartPermissionId != '31' && item.ChartPermissionId != '52'">
+            <span> {{ allPerCentHandler(item) == 0 ? "" : `总占比:` }}</span>
+            <span> {{ allPerCentHandler(item) == 0 ? "" : `${allPerCentHandler(item)}` }}</span>
+          </div>
+        </div>
+      </div>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="handleClose" size="large">取 消</el-button>
+          <el-button type="primary" @click="addAllocationHandler" size="large">确 定</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<style lang="scss">
+.container-allocation-number-rai {
+  overflow: hidden;
+  .top-content {
+    display: flex;
+    justify-content: space-between;
+  }
+  .content-box {
+    width: 100%;
+    overflow: hidden;
+    overflow-x: auto;
+    display: flex;
+    .industry-ul {
+      display: flex;
+      align-items: center;
+      margin: 30px 0;
+      width: 180px;
+      color: #333;
+      margin-right: 25px;
+      .per_cent_ {
+        line-height: 32px;
+      }
+      .industry-name {
+        width: 58px;
+        flex-shrink: 0;
+        font-weight: 800;
+        font-size: 16px;
+        line-height: 22px;
+      }
+      .study-name {
+        width: 58px;
+        flex-shrink: 0;
+        font-size: 14px;
+        line-height: 22px;
+      }
+      p {
+        color: #9999;
+        font-size: 14px;
+      }
+    }
+  }
+  .all-item {
+    display: flex;
+    padding-right: 15px;
+    align-items: center;
+    // justify-content: center;
+    color: #999;
+    font-size: 14px;
+    span {
+      display: inline-block;
+      width: 80px;
+    }
+  }
+  .name-yanxuan {
+    width: 70px !important;
+  }
+  .points-name {
+    width: 80px !important;
+  }
+  /* 取消[type='number']的input的上下箭头 */
+  input::-webkit-inner-spin-button {
+    -webkit-appearance: none !important;
+  }
+
+  input::-webkit-outer-spin-button {
+    -webkit-appearance: none !important;
+  }
+
+  input[type="number"] {
+    -moz-appearance: textfield;
+  }
+}
+</style>

+ 338 - 0
src/views/contract_manage/components/raiHistoryContract.vue

@@ -0,0 +1,338 @@
+
+<script setup>
+import { ref,watch } from "vue";
+import { useRouter} from 'vue-router';
+import { InfoFilled } from '@element-plus/icons-vue'
+
+import {formatTime} from "@/hooks/mixins/index.js"
+
+const $router=useRouter() 
+
+const props = defineProps({
+  isPreview: {
+    type: Boolean,
+    default: false,
+  },
+  dealList: {
+    type: Array,
+    default: () => {
+      return [];
+    },
+  },
+})
+const emits=defineEmits(['update:isPreview','update:dealList'])
+
+const ficcContractList=ref([])
+const raiContractList=ref([])
+const contractList=ref([])
+const contractType=ref("")
+const showViewer=ref(false)
+const constractFileImgList=ref([])
+
+watch(()=>props.isPreview,(val)=>{
+  console.log(val,'val');
+  if (val) {
+    getContractList();
+  }
+})
+
+const getContractList=()=>{
+  ficcContractList.value = props.dealList.filter((i) => i.ProductId === 1);
+  raiContractList.value = props.dealList.filter((i) => i.ProductId === 2);
+  changeContractType("ficc");
+  if (!ficcContractList.value.length && raiContractList.value.length) {
+    changeContractType("rai");
+  }
+}
+const changeContractType=(type)=>{
+  if (contractType.value === type) return;
+  contractType.value = type;
+  type === "ficc" && (contractList.value = ficcContractList.value);
+  type === "rai" && (contractList.value = raiContractList.value);
+}
+const showContractFiles=(data)=>{
+  constractFileImgList.value = [];
+  const { constractFiles } = data;
+  const imageList = constractFiles.filter((i) => i.type === "img");
+  const wordList = constractFiles.filter((i) => i.type === "word");
+  const pdfList = constractFiles.filter((i) => i.type === "pdf");
+  imageList.forEach((i) => {
+    constractFileImgList.value.push(i.url);
+  });
+  if (constractFileImgList.value.length) {
+    showViewer.value = true;
+  }
+}
+const preViewConstractFile=(data, list = [])=>{
+  constractFileImgList.value = [];
+  if (data.type === "word") {
+    window.open("https://view.officeapps.live.com/op/view.aspx?src=" + data.url, "_blank");
+  }
+  if (data.type === "pdf") {
+    window.open(data.url);
+  }
+  if (data.type === "img") {
+    //改变list的顺序,当前点击的为第一个
+    list
+      .filter((i) => i.type === "img")
+      .map((i) => {
+        constractFileImgList.value.push(i.url);
+      });
+    const index = constractFileImgList.value.findIndex((url) => url === data.url);
+    constractFileImgList.value = [...constractFileImgList.value.slice(index), ...constractFileImgList.value.slice(0, index)];
+    if (constractFileImgList.value.length) {
+      showViewer.value = true;
+    }
+  }
+}
+const showExpand=(index, type = "root")=>{
+  type === "root" && (contractList.value[index].extend = !contractList.value[index].extend);
+  type === "files" && (contractList.value[index].filesExtend = !contractList.value[index].filesExtend);
+  contractList.value.splice(index, 1, contractList.value[index]);
+}
+const toContractDetail=(item)=>{
+  if (!item.ContractId) return;
+  const { href } = $router.resolve({ path: "/contractdetail", query: { contractId: item.ContractId } }) || { href: "" };
+  href && window.open(href, "_blank");
+}
+const closePreview=()=>{
+  emits("update:isPreview", false);
+  emits("update:dealList", []);
+}
+
+</script>
+
+<template>
+  <!-- 历史签约弹窗 -->
+  <div>
+    <el-dialog
+      v-model="props.isPreview"
+      class="history-contract-wrap-content_rai"
+      :append-to-body="true"
+      :modal-append-to-body="false"
+      @close="closePreview"
+      title="历史签约"
+      center
+      top="7vh"
+      v-dialogDrag
+      width="1200px"
+    >
+      <div class="dialog-wrap">
+        <div class="contract-list">
+          <div class="contract-item" v-for="(item, index) in contractList" :key="item.ContractCode">
+            <div class="contract-tag">
+              <el-tag size="large">
+                {{ item.ContractType }}
+                <el-tooltip class="item" effect="dark" v-if="item.ContractType != '补充协议'" placement="top-start">
+                  <template #content v-if="item.ContractType == '新签合同'">
+                    没有正式转试用记录的客户,在申请转正时提交的合同
+                  </template>
+                  <template #content v-if="item.ContractType == '续约合同'">
+                    1、有正式转试用记录的客户,在申请转正时提交的合同<br />
+                    2、所有客户在续约申请时提交的合同
+                  </template>
+                  <el-icon :size="17" style="width: 17px;"><InfoFilled /></el-icon>
+                </el-tooltip>
+              </el-tag>
+              <span :style="{ 'text-decoration-line': item.ContractId ? 'underline' : 'none' }" @click="toContractDetail(item)">合同编号:{{ item.ContractCode }}</span>
+            </div>
+            <div class="line"></div>
+            <!-- 合同基本信息 -->
+            <div class="contract-base">
+              <ul class="base-lise">
+                <li>
+                  <p>合同期限:{{ item.StartDate + "~" + item.EndDate }}</p>
+                  <p>合同金额:{{ item.Money }}</p>
+                </li>
+                <li>
+                  <p>付款方式:{{ item.PayMethod }}</p>
+                  <p>付款渠道:{{ item.PayChannel }}</p>
+                </li>
+                <li>
+                  <p>审批时间:{{ formatTime(item.ModifyTimeStr) }}</p>
+                  <p></p>
+                </li>
+              </ul>
+            </div>
+            <!-- 权限设置和查看附件 -->
+            <div class="contract-info">
+              <div @click="showExpand(index, 'root')">
+                权限设置 <span><i :class="item.extend ? 'el-icon-arrow-down' : 'el-icon-arrow-right'"></i></span>
+              </div>
+            </div>
+            <div class="contract-root" v-show="item.extend">
+              <ul class="menu_lists">
+                <li v-for="auth in item.PermissionList" :key="auth.ClassifyName" class="menu_item">
+                  <el-checkbox :indeterminate="auth.CheckList.length > 0 && auth.CheckList.length < auth.Items.length" v-model="auth.CheckAll" disabled style="margin-right: 30px; font-weight: bold">{{
+                    auth.ClassifyName + ":"
+                  }}</el-checkbox>
+                  <el-checkbox-group v-model="auth.CheckList" disabled>
+                    <el-checkbox v-for="list in auth.Items" :label="list.ChartPermissionId" :key="list.ChartPermissionId" class="list_item">{{ list.PermissionName }}</el-checkbox>
+                  </el-checkbox-group>
+                </li>
+              </ul>
+            </div>
+            <div class="contract-info">
+              <div @click="showExpand(index, 'files')">
+                合同附件 <span><i :class="item.filesExtend ? 'el-icon-arrow-down' : 'el-icon-arrow-right'"></i></span>
+              </div>
+            </div>
+            <div class="contract-files" v-show="item.filesExtend">
+              <ul class="file-list">
+                <li v-for="img in item.constractFiles" :key="img">
+                  <img :src="require('@/assets/img/constract/word-icon.png')" v-if="img.type == 'word'" @click="preViewConstractFile(img)" />
+                  <img :src="require('@/assets/img/constract/pdf.png')" v-else-if="img.type == 'pdf'" @click="preViewConstractFile(img)" />
+                  <img :src="img.url" v-else-if="img.type == 'img'" @click="preViewConstractFile(img, item.constractFiles)" />
+                </li>
+              </ul>
+            </div>
+          </div>
+          <span v-if="!contractList.length" style="font-size: 16px; color: #999">暂无历史合同</span>
+        </div>
+      </div>
+      <el-image-viewer
+        v-if="showViewer"
+        @close="
+          () => {
+            showViewer = false;
+          }
+        "
+        :url-list="constractFileImgList"
+      />
+    </el-dialog>
+  </div>
+</template>
+
+<style lang="scss">
+.history-contract-wrap-content_rai {
+  .dialog-wrap {
+    padding: 5px 60px 30px 60px;
+    .contract-tab {
+      display: flex;
+      margin-bottom: 30px;
+      span {
+        flex: 1;
+        text-align: center;
+        font-size: 16px;
+        padding-bottom: 5px;
+        cursor: pointer;
+        &.active {
+          color: #0052d9;
+          border-bottom: 2px solid #0052d9;
+        }
+      }
+    }
+    .contract-list {
+      max-height: 600px;
+      min-height: 200px;
+      overflow-y: auto;
+      padding-right: 6px;
+      .contract-item {
+        padding: 20px;
+        border: 1px solid #dcdfe6;
+        border-radius: 4px;
+        margin-bottom: 30px;
+        display: flex;
+        flex-direction: column;
+        gap: 20px 0;
+        .contract-tag {
+          span {
+            cursor: pointer;
+            &:last-child {
+              margin-left: 12px;
+            }
+            font-size: 16px;
+            color: #409eff;
+          }
+        }
+        .line {
+          height: 1px;
+          background-color: #dcdfe6;
+          margin: 0 -20px;
+        }
+        .contract-base {
+          li {
+            display: flex;
+            border: 1px solid #dcdfe6;
+            border-bottom: none;
+            &:last-child {
+              border-bottom: 1px solid #dcdfe6;
+            }
+            p {
+              font-size: 16px;
+              flex: 1;
+              min-height: 48px;
+              display: flex;
+              align-items: center;
+              margin-left: 20px;
+              &:first-child {
+                border-right: 1px solid #dcdfe6;
+              }
+            }
+          }
+        }
+        .contract-info {
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
+          div,
+          i::before {
+            font-size: 14px;
+            font-weight: bold;
+            color: #333333;
+            cursor: pointer;
+          }
+        }
+        .contract-root {
+          border: 2px dashed #dcdfe6;
+          border-radius: 4px;
+          padding: 20px;
+          .menu_lists {
+            li {
+              display: flex;
+              margin-bottom: 20px;
+              &:last-child {
+                margin-bottom: 0;
+              }
+            }
+          }
+        }
+        .contract-files {
+          .file-list {
+            display: flex;
+            gap: 10px;
+            flex-wrap: wrap;
+            li {
+              width: 240px;
+              height: 180px;
+              padding: 10px;
+              box-sizing: border-box;
+              cursor: pointer;
+              border-radius: 4px;
+              background-color: rgb(170, 170, 170);
+              img {
+                width: 100%;
+                height: 100%;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+</style>
+<style lang="scss">
+  .contract-tag{
+    .el-tag{
+      .el-tag__content{
+        display:inline-flex;
+        align-items:center;
+        margin-left:0!important;
+        i{
+          margin-left:4px;
+        }
+      }
+    }
+  }
+</style>

+ 126 - 0
src/views/contract_manage/components/relatedContract.vue

@@ -0,0 +1,126 @@
+
+<script setup>
+import { ref,watch } from "vue";
+
+import { contractInterface } from "@/api/api.js";
+import AllocationLable from "./allocationLable.vue";
+import mPage from "@/components/mPage.vue";
+import RaiHistoryContract from "./raiHistoryContract.vue";
+import AllocationDetailCom from "./allocationDetail.vue";
+
+const props = defineProps({
+  isShowDlg: {
+    type: Boolean,
+    default: false,
+  },
+  listDlg: {
+    type: Object,
+    default: {},
+  },
+})
+const emits = defineEmits(['update:isShowDlg','update:listDlg'])
+
+const datalist=ref([])
+const page_no=ref(1)
+const total=ref(0) //条数
+const PageSize=ref(10) //每页显示几条
+const dealList=ref([])
+const isPreview=ref(false)
+const allocationDetailVisible=ref(false)
+const allocationDetailForm=ref({})
+
+watch(()=>props.isShowDlg,(newVal)=>{
+  newVal && getList();
+})
+
+// 关闭弹框
+const handleClose=()=>{
+  emits("update:isShowDlg", false);
+  emits("update:listDlg", false);
+}
+
+// 获取数据
+const getList=async()=>{
+console.log(props.listDlg);
+const res = await contractInterface.getAllocationContract({
+  ResearcherRealName: props.listDlg.RealName,
+  Keyword: props.listDlg.searchVal,
+  StartDate: props.listDlg.date[0] ? props.listDlg.date[0] : "",
+  EndDate: props.listDlg.date[1] ? props.listDlg.date[1] : "",
+  PageSize: PageSize.value,
+  CurrentIndex: page_no.value,
+});
+  if (res.Ret === 200) {
+    datalist.value = res.Data.List;
+    total.value = res.Data.Paging.Totals;
+  }
+}
+// 非标准预览
+const isPreviewHistoryDetail=(res)=>{
+  isPreview.value = true;
+  dealList.value = res.Data.List;
+}
+//分页
+const handleCurrentChange=(page)=>{
+  page_no.value = page;
+  getList();
+}
+// 派点详情
+const allocationDetail=(item)=>{
+  allocationDetailVisible.value = true;
+  allocationDetailForm.value = item;
+  allocationDetailForm.value.isDlgType = "关联合同";
+}
+
+</script>
+
+<template>
+  <el-dialog title="关联合同" width="90%" :append-to-body="true" v-model="props.isShowDlg" v-dialogDrag :close-on-click-modal="false" :modal-append-to-body="false" center @close="handleClose">
+    <allocation-lable :tableList="datalist" typeLable="关联合同" @isPreviewHistoryDetail="isPreviewHistoryDetail" @allocationDetail="allocationDetail" />
+    <el-col :span="24" class="toolbar">
+      <m-page :total="total" :page_no="page_no" :pageSize="10" @handleCurrentChange="handleCurrentChange" />
+    </el-col>
+    <rai-history-contract v-model:isPreview="isPreview" v-model:dealList="dealList" />
+    <allocation-detail-com v-model:allocationDetailVisible="allocationDetailVisible" v-model:allocationDetailForm="allocationDetailForm" />
+  </el-dialog>
+</template>
+
+<style scoped lang="scss">
+.content-box-table-detail {
+  height: 400px;
+  overflow: hidden;
+  overflow-y: auto;
+  position: relative;
+  margin-top: 20px;
+  .table-cont-top {
+    position: sticky;
+    top: 0;
+    left: 0;
+  }
+  .table-cont {
+    display: flex;
+  }
+  .head-column {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    border: 1px solid #dcdfe6;
+    background-color: #ebeef5;
+    color: #333333;
+    font-weight: 500;
+    margin-top: -1px;
+    margin-left: -0.5px;
+  }
+  .head-column-item {
+    width: 107px;
+    height: 48px;
+  }
+  .head-column-item-Proportion {
+    width: 73px;
+    height: 48px;
+  }
+}
+.toolbar{
+  height: 52px;
+}
+</style>

+ 288 - 0
src/views/contract_manage/raiAllocationPage.vue

@@ -0,0 +1,288 @@
+<script setup>
+import { ref,reactive,computed } from "vue";
+import moment from "moment"; 
+import { Search } from '@element-plus/icons-vue'
+
+import { customInterence, contractInterface } from "@/api/api.js";
+import AllocationLable from "./components/allocationLable.vue";
+import AllocationNumber from "./components/allocationNumber.vue";
+import AllocationDetailPage from "./components/allocationDetail.vue";
+import mPage from "@/components/mPage.vue";
+import RaiHistoryContract from "./components/raiHistoryContract.vue";
+
+
+/* 筛选条件 */
+const filterObj=reactive({
+  month: "",
+  date: [],
+  type: "",
+  sale: "",
+  area: "",
+  status: "",
+  contractType: "",
+})
+const monthLabel=reactive([
+  {
+    label: "近1个月",
+  },
+  {
+    label: "近2个月",
+  },
+  {
+    label: "近3个月",
+  },
+])
+const searchVal=ref("")
+const typeArr=reactive([
+  {
+    value: "非标",
+    label: "非标合同",
+  },
+  {
+    value: "标准",
+    label: "标准合同",
+  },
+])
+const typeArrStatus=reactive([
+  {
+    value: "0",
+    label: "未派点",
+  },
+  {
+    value: "1",
+    label: "已派点",
+  },
+])
+const salesArr=ref([]) //销售列表
+const contractTypeArr=reactive([
+  {
+    value: "新签合同",
+    label: "新签合同",
+  },
+  {
+    value: "续约合同",
+    label: "续约合同",
+  },
+  {
+    value: "补充协议",
+    label: "补充协议",
+  },
+]) // 合同类型
+const statusArr=ref([]) // 派点状态
+const defaultSalesProps=reactive({
+  multiple: true,
+  label: "RealName",
+  children: "ChildrenList",
+  value: "AdminId",
+}) //销售级联配置
+
+const tableList=ref([])
+const allocationVisible=ref(false) // 派点
+const allocationForm=ref({}) // 派点
+const allocationDetailVisible=ref(false) // 派点详情
+const allocationDetailForm=ref({}) // 派点详情
+const page_no=ref(1)
+const total=ref(0)
+const PageSize=ref(10)
+const isPreview=ref(false)
+const dealList=ref([])
+
+const exportExcel=computed(()=>{
+  let baseUrl = import.meta.env.VITE_APP_API_ROOT + "/cygx/allocation/company_contract_list";
+  let token = localStorage.getItem("auth") || "";
+  let paramStr = "";
+  let salesArr = [];
+  if (filterObj.sale.length) {
+    salesArr = filterObj.sale.map((item) => {
+      return item[item.length - 1];
+    });
+  }
+  let obj = {
+    IsExport: true,
+    FormalType: filterObj.type,
+    ContractType: filterObj.contractType,
+    PageSize: PageSize.value,
+    CurrentIndex: page_no.value,
+    Keyword: searchVal.value,
+    AdminId: salesArr.join(","),
+    IsAllocation: filterObj.status,
+    StartDate: filterObj.date ? filterObj.date[0]||"" : "",
+    EndDate: filterObj.date ? filterObj.date[1]||"" : "",
+  };
+  for (let key in obj) {
+    paramStr = `${paramStr}&${key}=${obj[key]}`;
+  }
+  return `${baseUrl}?${token}${paramStr}`;
+})
+
+/* 切换月份 */
+const toggleMonth=(label)=>{
+  filterObj.month = label;
+  let days = label == "近1个月" ? 1 : label == "近2个月" ? 2 : label == "近3个月" ? 3 : 0;
+  filterDate(days);
+}
+/* 获取近几个月的日期范围 */
+const filterDate=(month)=>{
+  if (month) {
+    let date_now = moment().format("YYYY-MM-DD");
+    let date_after = moment().add(-month, "M").format("YYYY-MM-DD");
+    let date = [date_after, date_now];
+    filterObj.date = date;
+    page_no.value = 1;
+    searchVal.value = "";
+    getTableData();
+  }
+}
+/* 获取销售 */
+const getSale=()=>{
+  customInterence.getSale().then((res) => {
+    if (res.Ret === 200) {
+      salesArr.value = res.Data.List;
+    }
+  });
+}
+const getTableData=async()=>{
+  let salesArr = [];
+  if (filterObj.sale.length) {
+    salesArr = filterObj.sale.map((item) => {
+      return item[item.length - 1];
+    });
+  }
+  const res = await contractInterface.getAllocationContract({
+    FormalType: filterObj.type,
+    ContractType: filterObj.contractType,
+    PageSize: PageSize.value,
+    CurrentIndex: page_no.value,
+    Keyword: searchVal.value,
+    AdminId: salesArr.join(","),
+    IsAllocation: filterObj.status,
+    StartDate: filterObj.date ? filterObj.date[0]||"" : "",
+    EndDate: filterObj.date ? filterObj.date[1]||"" : "",
+  });
+  if (res.Ret === 200) {
+    tableList.value = res.Data.List;
+    total.value = res.Data.Paging.Totals;
+  }
+}
+const changeFilter=()=>{
+  page_no.value = 1;
+  getTableData();
+}
+const handleSearch=()=>{
+  getTableData();
+}
+//分页
+const handleCurrentChange=(page)=>{
+  page_no.value = page;
+  getTableData();
+}
+// 非标准预览
+const isPreviewHistoryDetail=(res)=>{
+  isPreview.value = true;
+  dealList.value = res.Data.List;
+}
+// 派点
+const allocationDetailList=(item)=>{
+  allocationForm.value = item;
+  allocationVisible.value = true;
+}
+// 派点详情
+const allocationDetail=(item)=>{
+  allocationDetailVisible.value = true;
+  allocationDetailForm.value = item;
+}
+/* 选择日期 */
+const dateChange=(e)=>{
+  page_no.value = 1;
+  getTableData();
+}
+
+getSale();
+getTableData();
+
+</script>
+
+<template>
+  <div class="container rai-allocation-page">
+    <div class="dataReport-top">
+      <a :href="exportExcel" download>
+        <button class="button-sty act" >导出EXCEL</button>
+      </a>
+      <button :class="['button-sty', { act: filterObj.month === item.label }]" v-for="item in monthLabel" @click="toggleMonth(item.label)" :key="item.label">
+        {{ item.label }}
+      </button>
+      <el-date-picker v-model="filterObj.date" type="daterange" format="YYYY-MM-DD" value-format="YYYY-MM-DD" size="large"
+      @change="dateChange" start-placeholder="开始" end-placeholder="结束" style="max-width: 280px;"> </el-date-picker>
+      <!-- vue-datepicker-next -->
+      <!-- <date-picker v-model="filterObj.date" type="date" range value-type="format" placeholder="自定义时间段" clearable :editable="false" @change="dateChange" /> -->
+      <el-input placeholder="请输入客户名称" v-model.trim="searchVal" style="width: 400px; margin-left: auto" @input="handleSearch" clearable
+      size="large" :prefix-icon="Search" />
+    </div>
+    <el-card style="margin-top: 20px">
+      <div style="margin-bottom: 30px">
+        <el-select v-model="filterObj.type" placeholder="转正类型" style="width: 230px; margin-right: 20px" clearable @change="changeFilter"
+        size="large">
+          <el-option v-for="item in typeArr" :key="item" :label="item.label" :value="item.value"> </el-option>
+        </el-select>
+
+        <el-select v-model="filterObj.contractType" placeholder="合同类型" style="width: 230px; margin-right: 20px" clearable @change="changeFilter"
+        size="large">
+          <el-option v-for="item in contractTypeArr" :key="item" :label="item.label" :value="item.value"> </el-option>
+        </el-select>
+        <el-cascader
+          v-model="filterObj.sale"
+          placeholder="请选择销售"
+          style="width: 230px; margin-right: 20px"
+          :options="salesArr"
+          :props="defaultSalesProps"
+          :show-all-levels="false"
+          collapse-tags
+          clearable
+          filterable
+          @change="changeFilter"
+          size="large"
+        >
+        </el-cascader>
+        <el-select v-model="filterObj.status" placeholder="派点状态" style="width: 230px; margin-right: 20px" clearable @change="changeFilter"
+        size="large">
+          <el-option v-for="item in typeArrStatus" :key="item" :label="item.label" :value="item.value"> </el-option>
+        </el-select>
+      </div>
+      <allocation-lable :tableList="tableList" @isPreviewHistoryDetail="isPreviewHistoryDetail" @allocationDetailList="allocationDetailList" @allocationDetail="allocationDetail" />
+      <el-col :span="24" class="toolbar">
+        <m-page :total="total" :page_no="page_no" :pageSize="10" @handleCurrentChange="handleCurrentChange" />
+      </el-col>
+    </el-card>
+    <allocation-number v-model:allocationVisible="allocationVisible" v-model:allocationForm="allocationForm" />
+    <allocation-detail-page @allocationDetailList="allocationDetailList" v-model:allocationDetailVisible="allocationDetailVisible" 
+    v-model:allocationDetailForm="allocationDetailForm" />
+    <rai-history-contract v-model:isPreview="isPreview" v-model:dealList="dealList" @emitGetTableData="getTableData"/>
+  </div>
+</template>
+
+<style scoped lang="scss">
+.rai-allocation-page {
+  .dataReport-top {
+    display: flex;
+    align-items: center;
+    border: 1px solid #ececec;
+    padding: 20px 30px;
+    background: #fff;
+    border-radius: 4px;
+    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
+    .button-sty {
+      margin-right: 20px;
+      border: none;
+      padding: 6px 12px;
+      background: #e0eefd;
+      color: #2d8cf0;
+      cursor: pointer;
+      border-radius: 4px;
+      &.act {
+        background: #409eff;
+        color: #fff;
+      }
+    }
+  }
+}
+</style>

+ 257 - 0
src/views/contract_manage/researcherStatistics.vue

@@ -0,0 +1,257 @@
+<script setup>
+import { ref,reactive,computed } from "vue";
+import { Search } from '@element-plus/icons-vue'
+
+import { contractInterface } from "@/api/api.js";
+import RelatedContract from "./components/relatedContract.vue";
+import moment from "moment";
+
+/* 筛选条件 */
+const filterObj=reactive({
+  month: "",
+  date: [],
+  type: "",
+  sale: "",
+  area: "",
+})
+const searchVal=ref("")
+const monthLabel=reactive([
+  {
+    label: "近1个月",
+  },
+  {
+    label: "近2个月",
+  },
+  {
+    label: "近3个月",
+  },
+])
+const tableTheadColumns=reactive(["组别", "研究员", "关联合同", "总派点", "组内占比", "部门占比"])
+const datalist=ref([])
+const isShowDlg=ref(false)
+const listDlg=ref({})
+const TotalMoney=ref("")
+const TotalContract=ref("")
+
+const exportExcel=computed(()=>{
+  let baseUrl = import.meta.env.VITE_APP_API_ROOT + "/cygx/allocation/statistics";
+  let token = localStorage.getItem("auth") || "";
+  let paramStr = "";
+  let obj = {
+    StartDate: filterObj.date[0] ? filterObj.date[0] : "",
+    EndDate: filterObj.date[1] ? filterObj.date[1] : "",
+    Keyword: searchVal.value,
+    IsExport: true,
+  };
+  for (let key in obj) {
+    paramStr = `${paramStr}&${key}=${obj[key]}`;
+  }
+  return `${baseUrl}?${token}${paramStr}`;
+})
+
+/* 切换月份 */
+const toggleMonth=(label)=>{
+  filterObj.month = label;
+  let days = label == "近1个月" ? 1 : label == "近2个月" ? 2 : label == "近3个月" ? 3 : 0;
+  filterDate(days);
+}
+
+/* 获取近几个月的日期范围 */
+const filterDate=(month)=>{
+  if (month) {
+    let date_now = moment().format("YYYY-MM-DD");
+    let date_after = moment().add(-month, "M").format("YYYY-MM-DD");
+    let date = [date_after, date_now];
+    filterObj.date = date;
+    searchVal.value = "";
+    getTableData();
+  }
+}
+
+const getTableData=async()=>{
+  const res = await contractInterface.getAllocationStatistic({
+    Keyword: searchVal.value,
+    StartDate: filterObj.date[0] ? filterObj.date[0] : "",
+    EndDate: filterObj.date[1] ? filterObj.date[1] : "",
+  });
+  if (res.Ret === 200) {
+    datalist.value = res.Data.List;
+    TotalContract.value = res.Data.TotalContract;
+    TotalMoney.value = res.Data.TotalMoney;
+  }
+}
+
+/* 选择日期 */
+const dateChange=(e)=>{
+  getTableData();
+}
+// 查看关联合同数
+const lookDetailsHadelr=(item)=>{
+  if (item.RealName == "合计" || item.RealName == "平均") return;
+  isShowDlg.value = true;
+  listDlg.value = {
+    ...item,
+    date: filterObj.date,
+    searchVal: searchVal,
+  };
+}
+const handleSearch=()=>{
+  getTableData();
+}
+
+getTableData();
+
+</script>
+
+<template>
+  <div class="container researcher-statistics">
+    <div class="dataReport-top">
+      <a :href="exportExcel" download>
+        <button class="button-sty act">导出EXCEL</button>
+      </a>
+      <button :class="['button-sty', { act: filterObj.month === item.label }]" v-for="item in monthLabel" @click="toggleMonth(item.label)" :key="item.label">
+        {{ item.label }}
+      </button>
+      <el-date-picker v-model="filterObj.date" type="daterange" format="YYYY-MM-DD" value-format="YYYY-MM-DD" size="large"
+      @change="dateChange" start-placeholder="开始" end-placeholder="结束" style="max-width: 280px;"> </el-date-picker>
+      <!-- vue-datepicker-next -->
+      <!-- <date-picker v-model="filterObj.date" type="date" range value-type="format" placeholder="自定义时间段" clearable :editable="false" :disabled-date="disabledBeforeToday" @change="dateChange" /> -->
+      <el-input placeholder="合同编号/客户名称/社会信用码" v-model="searchVal" style="width: 400px; margin-left: auto" @input="handleSearch" 
+      clearable size="large" :prefix-icon="Search" />
+    </div>
+    <el-card style="margin-top: 20px">
+      <div class="table-cont">
+        <table>
+          <thead>
+            <tr>
+              <td v-for="(item, index) in tableTheadColumns" :key="item" :class="['head-column', index > 0 && 'head-column-item']">
+                {{ item }}
+              </td>
+            </tr>
+          </thead>
+        </table>
+
+        <div class="table-body-wrapper">
+          <table>
+            <tbody v-for="(item, index) in datalist" :key="index">
+              <tr>
+                <td :rowspan="item.List.length + 1" class="thead-rs">{{ item.ChartPermissionName }}</td>
+              </tr>
+              <tr v-for="rs in item.List" :key="rs.RealName" class="content-ul">
+                <td>{{ rs.RealName }}</td>
+                <td @click="lookDetailsHadelr(rs)" :class="[rs.RealName == '合计' || rs.RealName == '平均' ? '' : 'association']">{{ rs.TotalRelatedContract }}</td>
+                <td>{{ rs.TotalDispatchPoint }}</td>
+                <td>{{ rs.GroupProportion }}</td>
+                <td>{{ rs.DepartmentProportion }}</td>
+              </tr>
+            </tbody>
+
+            <tfoot>
+              <tr>
+                <td colspan="2">部门合计</td>
+                <td>{{ TotalContract }}</td>
+                <td>{{ TotalMoney }}</td>
+                <td>--</td>
+                <td>100%</td>
+              </tr>
+            </tfoot>
+          </table>
+        </div>
+      </div>
+    </el-card>
+    <related-contract v-model:isShowDlg="isShowDlg" v-model:listDlg="listDlg" />
+  </div>
+</template>
+
+<style scoped lang="scss">
+.researcher-statistics {
+  * {
+    box-sizing: border-box;
+  }
+  .dataReport-top {
+    display: flex;
+    align-items: center;
+    border: 1px solid #ececec;
+    padding: 20px 30px;
+    background: #fff;
+    border-radius: 4px;
+    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
+    .button-sty {
+      margin-right: 20px;
+      border: none;
+      padding: 6px 12px;
+      background: #e0eefd;
+      color: #2d8cf0;
+      cursor: pointer;
+      border-radius: 4px;
+      &.act {
+        background: #409eff;
+        color: #fff;
+      }
+    }
+  }
+  .table-cont {
+    .table-body-wrapper {
+      max-height: calc(100vh - 340px);
+      margin-right: -6px;
+      overflow-y: scroll;
+      overflow-x: auto;
+      border-bottom: 1px solid #dcdfe6;
+      border-top: 1px solid #dcdfe6;
+    }
+    .head-column-item {
+      width: 15%;
+    }
+    table {
+      width: 100%;
+      font-size: 14px;
+      color: #666;
+      thead {
+        position: sticky;
+        top: 0;
+        left: 0;
+        border-left: 1px solid #dcdfe6;
+        border-right: 1px solid #dcdfe6;
+        td {
+          border: none;
+          outline-color: #dcdfe6;
+          outline-style: solid;
+          outline-width: 0.5px;
+        }
+      }
+      td,
+      th {
+        min-width: 35px;
+        // word-break: break-all;
+        border: 1px solid #dcdfe6;
+        height: 45px;
+        text-align: center;
+        background-color: #fff;
+      }
+
+      .head-column {
+        background-color: #f0f2f5;
+      }
+
+      .data-cell {
+        color: #409eff;
+        cursor: pointer;
+      }
+
+      .thead-sticky {
+        position: sticky;
+        top: 0;
+      }
+    }
+    .content-ul {
+      td {
+        width: 15%;
+      }
+      .association {
+        color: #409eff;
+        cursor: pointer;
+      }
+    }
+  }
+}
+</style>