Browse Source

init 14.3

bding 1 year ago
parent
commit
f4f4b6f74d

+ 18 - 9
src/routes/modules/contractRoutes.js

@@ -150,15 +150,24 @@ export default [
 					keepAlive: false
 				}
 			},
-			// {
-			// 	path:"contractapprovallist",
-			// 	component:()=>import("@/views/contract_manage/approvalList.vue"),
-			// 	name:"合同审批",
-			// 	hidden:false,
-			// 	meta: {
-			// 		keepAlive: false
-			// 	}
-			// }
+			{
+				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
+				}
+			}
 		]
 	},
 ]

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

@@ -0,0 +1,173 @@
+<template>
+  <el-dialog title="派点" :visible.sync="allocationVisible" v-dialogDrag :close-on-click-modal="false" :modal-append-to-body="false" center @close="handleClose">
+    <div class="table-cont">
+      <table>
+        <thead>
+          <tr>
+            <template v-for="item in datalist">
+              <td :key="item" :class="['head-column', 'head-column-item']">
+                {{ item.Name }}
+              </td>
+              <td :key="item" :class="['head-column', 'head-column-item']">
+                {{ item.GruopId }}
+              </td>
+            </template>
+          </tr>
+        </thead>
+      </table>
+
+      <div class="table-body-wrapper">
+        <table>
+          <tbody v-for="(item, index) in datalist" :key="index">
+            <tr class="content-ul">
+              <template v-for="rs in item.Item">
+                <td :key="rs.AdminId">{{ rs.Name }}</td>
+                <td :key="rs.AdminId">{{ rs.DepartmentPercentage }}</td>
+              </template>
+            </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+    <span slot="footer" class="dialog-footer">
+      <el-button @click="handleClose">取 消</el-button>
+      <el-button type="primary" @click="addAllocationHandler">修 改</el-button>
+    </span>
+  </el-dialog>
+</template>
+
+<script>
+import TemplateMessage from "../../rai_manage/components/apply/templateMessage.vue";
+export default {
+  name: "",
+  components: {},
+  props: {},
+  data() {
+    return {
+      allocationVisible: true,
+      datalist: [
+        {
+          Item: [
+            {
+              Name: "测试1", // 研究员
+              AdminId: 517,
+              ContractCount: 0, // 关联合同
+              TotalPoints: 0, // 总派点
+              GroupPercentage: 0, // 组内占比
+              DepartmentPercentage: 0, // 部门占比
+            },
+            {
+              Name: "测试2", // 研究员
+              AdminId: 517,
+              ContractCount: 0, // 关联合同
+              TotalPoints: 0, // 总派点
+              GroupPercentage: 0, // 组内占比
+              DepartmentPercentage: 0, // 部门占比
+            },
+          ],
+          Name: "消费组", // 组别
+          GruopId: 0,
+        },
+        {
+          Item: [
+            {
+              Name: "测试1", // 研究员
+              AdminId: 517,
+              ContractCount: 0, // 关联合同
+              TotalPoints: 0, // 总派点
+              GroupPercentage: 0, // 组内占比
+              DepartmentPercentage: 0, // 部门占比
+            },
+            {
+              Name: "测试2", // 研究员
+              AdminId: 517,
+              ContractCount: 0, // 关联合同
+              TotalPoints: 0, // 总派点
+              GroupPercentage: 0, // 组内占比
+              DepartmentPercentage: 0, // 部门占比
+            },
+          ],
+          Name: "科技组", // 组别
+          GruopId: 0,
+        },
+      ],
+    };
+  },
+  computed: {},
+  watch: {},
+  created() {},
+  mounted() {},
+  methods: {
+    // 关闭弹框
+    handleClose(item) {},
+    processingData() {
+      for (let index = 0; index < this.datalist.length; index++) {}
+    },
+  },
+};
+</script>
+<style scoped lang="scss">
+.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>

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

@@ -0,0 +1,65 @@
+<template>
+  <div>
+    <el-table border :data="tableList">
+      <el-table-column align="center" prop="ContractCode" label="合同编号" width="160">
+        <template slot-scope="{ row }">
+          <span class="editsty" @click="lookContractHandler(row)">{{ row.ContractCode }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" prop="ContractCode" label="转正类型" width="100"> </el-table-column>
+      <el-table-column align="center" prop="ContractCode" label="合同类型" width=""> </el-table-column>
+      <el-table-column align="center" prop="CompanyName" label="公司名称" width="">
+        <template slot-scope="{ row }">
+          <span class="editsty" @click="lookCompanyNameHandler(row)">{{ row.CompanyName }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column align="center" prop="ContractCode" label="所属销售" width="100"> </el-table-column>
+      <el-table-column align="center" prop="ContractCode" label="合同金额" width=""> </el-table-column>
+      <el-table-column align="center" prop="ContractCode" label="合同期限" width=""> </el-table-column>
+      <el-table-column align="center" prop="ContractCode" label="状态" width=""> </el-table-column>
+      <el-table-column align="center" prop="ContractCode" label="操作">
+        <template slot-scope="{ row }">
+          <span class="editsty">派点</span>
+          <span class="editsty" @click="detailsHandler(row)">派点详情</span>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "",
+  components: {},
+  props: {
+    tableList: {
+      type: Array,
+      default: [],
+    },
+  },
+  data() {
+    return {};
+  },
+  computed: {},
+  watch: {},
+  created() {},
+  mounted() {},
+  methods: {
+    // 查看合同
+    lookContractHandler(item) {},
+    // 查看公司详情
+    lookCompanyNameHandler(item) {
+      const { href } = this.$router.resolve({
+        path: "/customDetail",
+        query: {
+          id: item.CompanyId,
+        },
+      });
+      window.open(href, "_blank");
+    },
+    // 派点详情
+    detailsHandler(item) {},
+  },
+};
+</script>
+<style scoped lang=""></style>

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

@@ -0,0 +1,220 @@
+<template>
+  <div class="container-allocation-number-rai">
+    <el-dialog title="派点" :visible.sync="allocationVisible" v-dialogDrag :close-on-click-modal="false" :modal-append-to-body="false" center @close="handleClose">
+      <div>
+        <h5>总点数:15W,其中3w默认归属买方研选,请对剩余12W按照100%进行比值分配</h5>
+        <p>
+          1)单行业套餐只能在对应行业内部分配研究员贡献百分比<br />
+          2)多行业套餐先在行业间分配百分比(最低不低于平均值的一半),再分配到个人<br />
+          3)允许总额20%以内的负分<br />
+          4)转正后一个季度内可以提交和修改
+          <br />
+        </p>
+      </div>
+      <div class="content-box">
+        <div v-for="item in listArr" :key="item.IndustryName">
+          <div class="industry-ul">
+            <span class="industry-name">{{ item.IndustryName }}</span>
+            <el-input :min="-100" :max="100" type="number" v-model="item.PerCent" size="small" @input="restrictInput(item)" style="width: 76px; margin: 0 5px 0 8px">
+              <div class="per_cent_" slot="suffix">%</div>
+            </el-input>
+            <p style="width: 38px">{{ roundedResult(item.PerCent) }}</p>
+          </div>
+          <div v-for="study in item.Item" :key="study.StudyName" class="industry-ul">
+            <span class="study-name">{{ study.StudyName }}</span>
+            <el-input :min="-100" :max="100" type="number" v-model="study.PerCent" size="small" style="width: 76px; margin: 0 5px 0 8px">
+              <div class="per_cent_" slot="suffix">%</div>
+            </el-input>
+            <p style="width: 38px">{{ roundedResult(study.PerCent) }}</p>
+          </div>
+          <div class="all-item">
+            {{ allPerCentHandler(item) == 0 ? "" : `总值:${allPerCentHandler(item)}` }}
+          </div>
+        </div>
+      </div>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="handleClose">取 消</el-button>
+        <el-button type="primary" @click="addAllocationHandler">发 布</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "",
+  components: {},
+  props: {
+    allocationVisible: {
+      default: false,
+      type: Boolean,
+    },
+  },
+  data() {
+    return {
+      listArr: [
+        {
+          IndustryName: "消费",
+          PerCent: "",
+          Item: [
+            {
+              StudyName: "赵璐",
+              PerCent: "",
+            },
+            {
+              StudyName: "郭望葳",
+              PerCent: "",
+            },
+            {
+              StudyName: "张天",
+              PerCent: "",
+            },
+            {
+              StudyName: "时昕",
+              PerCent: "",
+            },
+          ],
+        },
+        {
+          IndustryName: "科技",
+          PerCent: "",
+          Item: [
+            {
+              StudyName: "张晶",
+              PerCent: "",
+            },
+            {
+              StudyName: "欧阳志宏",
+              PerCent: "",
+            },
+            {
+              StudyName: "王修远",
+              PerCent: "",
+            },
+            {
+              StudyName: "陈昫锟",
+              PerCent: "",
+            },
+            {
+              StudyName: "许晓葳",
+              PerCent: "",
+            },
+            {
+              StudyName: "李婉月",
+              PerCent: "",
+            },
+          ],
+        },
+        {
+          IndustryName: "智造",
+          PerCent: "",
+          Item: [
+            {
+              StudyName: "杨云鹏",
+              PerCent: "",
+            },
+            {
+              StudyName: "钟正宇",
+              PerCent: "",
+            },
+            {
+              StudyName: "张振",
+              PerCent: "",
+            },
+            {
+              StudyName: "钱程鹏",
+              PerCent: "",
+            },
+            {
+              StudyName: "齐妍",
+              PerCent: "",
+            },
+          ],
+        },
+      ],
+      allNum: 12,
+    };
+  },
+  computed: {},
+  watch: {},
+  created() {},
+  mounted() {},
+  methods: {
+    // 取消弹框
+    handleClose() {},
+    // 提交弹框
+    addAllocationHandler() {},
+    // 处理百分比
+    roundedResult(PerCent) {
+      let num = PerCent >= 0 ? `0.${PerCent}` : PerCent / 100;
+      return PerCent ? (this.allNum * num).toFixed(2) : "";
+    },
+    // 输入框的限制
+    restrictInput(item) {
+      if (item.PerCent > 100) return (item.PerCent = 100);
+      if (item.PerCent < -100) return (item.PerCent = -100);
+    },
+    // 数量的总和
+    allPerCentHandler(item) {
+      let num = 0;
+      item && item.Item.forEach((key) => (num = num + +key.PerCent));
+      return num;
+    },
+  },
+};
+</script>
+<style lang="scss">
+.container-allocation-number-rai {
+  .content-box {
+    display: flex;
+    .industry-ul {
+      display: flex;
+      align-items: center;
+      margin: 30px 0;
+      width: 180px;
+      color: #333;
+      margin-right: 35px;
+      .per_cent_ {
+        line-height: 32px;
+      }
+      .industry-name {
+        width: 58px;
+        flex-shrink: 0;
+        font-weight: 500;
+        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;
+  }
+  /* 取消[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>

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

@@ -0,0 +1,304 @@
+<template>
+  <!-- 历史签约弹窗 -->
+  <div class="history-contract-wrap">
+    <el-dialog :visible.sync="isPreview" :modal-append-to-body="false" @close="$emit('close')" 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>
+                {{ item.ContractType }}
+                <el-tooltip class="item" effect="dark" v-if="item.ContractType != '补充协议'" placement="top-start">
+                  <div slot="content" v-if="item.ContractType == '新签合同'">没有正式转试用记录的客户,在申请转正时提交的合同</div>
+                  <div slot="content" v-if="item.ContractType == '续约合同'">
+                    1、有正式转试用记录的客户,在申请转正时提交的合同<br />
+                    2、所有客户在续约申请时提交的合同
+                  </div>
+                  <i class="el-icon-info"></i>
+                </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>审批时间:{{ item.ModifyTimeStr | formatTime }}</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="marginright: 30px; fontweight: 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"
+        :on-close="
+          () => {
+            this.showViewer = false;
+          }
+        "
+        :url-list="constractFileImgList"
+      />
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import ElImageViewer from "element-ui/packages/image/src/image-viewer";
+export default {
+  props: {
+    isPreview: {
+      type: Boolean,
+      default: false,
+    },
+    dealList: {
+      type: Array,
+      default: () => {
+        return [];
+      },
+    },
+  },
+  components: { ElImageViewer },
+  watch: {
+    isPreview(val) {
+      if (val) {
+        this.getContractList();
+      }
+    },
+  },
+  data() {
+    return {
+      ficcContractList: [],
+      raiContractList: [],
+      contractList: [],
+      contractType: "",
+      showViewer: false,
+      constractFileImgList: [],
+    };
+  },
+  methods: {
+    getContractList() {
+      this.ficcContractList = this.dealList.filter((i) => i.ProductId === 1);
+      this.raiContractList = this.dealList.filter((i) => i.ProductId === 2);
+      this.changeContractType("ficc");
+      if (!this.ficcContractList.length && this.raiContractList.length) {
+        this.changeContractType("rai");
+      }
+    },
+    changeContractType(type) {
+      if (this.contractType === type) return;
+      this.contractType = type;
+      type === "ficc" && (this.contractList = this.ficcContractList);
+      type === "rai" && (this.contractList = this.raiContractList);
+    },
+    showContractFiles(data) {
+      this.constractFileImgList = [];
+      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) => {
+        this.constractFileImgList.push(i.url);
+      });
+      if (this.constractFileImgList.length) {
+        this.showViewer = true;
+      }
+    },
+    preViewConstractFile(data, list = []) {
+      this.constractFileImgList = [];
+      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) => {
+            this.constractFileImgList.push(i.url);
+          });
+        const index = this.constractFileImgList.findIndex((url) => url === data.url);
+        this.constractFileImgList = [...this.constractFileImgList.slice(index), ...this.constractFileImgList.slice(0, index)];
+        if (this.constractFileImgList.length) {
+          this.showViewer = true;
+        }
+      }
+    },
+    showExpand(index, type = "root") {
+      type === "root" && (this.contractList[index].extend = !this.contractList[index].extend);
+      type === "files" && (this.contractList[index].filesExtend = !this.contractList[index].filesExtend);
+      this.contractList.splice(index, 1, this.contractList[index]);
+    },
+    toContractDetail(item) {
+      if (!item.ContractId) return;
+      const { href } = this.$router.resolve({ path: "/contractdetail", query: { contractId: item.ContractId } }) || { href: "" };
+      href && window.open(href, "_blank");
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss">
+.history-contract-wrap {
+  .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>

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

@@ -0,0 +1,223 @@
+<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>
+      <date-picker
+        v-model="filterObj.date"
+        type="date"
+        range
+        value-type="format"
+        placeholder="自定义时间段"
+        :clearable="false"
+        :editable="false"
+        :disabled-date="disabledBeforeToday"
+        @change="dateChange"
+      />
+      <el-input placeholder="请输入客户名称" v-model="searchVal" style="width: 400px; margin-left: auto" @input="handleSearch" clearable>
+        <i slot="prefix" class="el-input__icon el-icon-search"></i>
+      </el-input>
+    </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">
+          <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">
+          <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"
+        >
+        </el-cascader>
+        <el-select v-model="filterObj.status" placeholder="派点状态" style="width: 230px; margin-right: 20px" clearable @change="changeFilter">
+          <el-option v-for="item in typeArr" :key="item" :label="item.name" :value="item.name"> </el-option>
+        </el-select>
+      </div>
+      <allocation-lable :tableList="tableList" />
+    </el-card>
+    <allocation-number :allocationVisible.sync="allocationVisible" />
+    <allocation-detail />
+  </div>
+</template>
+
+<script>
+import { dataMainInterface, customInterence } from "@/api/api.js";
+import AllocationLable from "./components/allocationLable.vue";
+import AllocationNumber from "./components/allocationNumber.vue";
+import AllocationDetail from "./components/allocationDetail.vue";
+var moment = require("moment");
+moment().format();
+export default {
+  name: "",
+  components: { AllocationLable, AllocationNumber, AllocationDetail },
+  props: {},
+  data() {
+    return {
+      /* 筛选条件 */
+      filterObj: {
+        month: "近1个月",
+        date: [],
+        type: "",
+        sale: "",
+        area: "",
+      },
+      monthLabel: [
+        {
+          label: "近1个月",
+        },
+        {
+          label: "近2个月",
+        },
+        {
+          label: "近3个月",
+        },
+      ],
+      searchVal: "",
+      typeArr: [
+        {
+          value: "非标合同",
+          label: "非标合同",
+        },
+        {
+          value: "非标合同",
+          label: "标准合同",
+        },
+      ],
+      salesArr: [], //销售列表
+      contractTypeArr: [
+        {
+          value: "新签合同",
+          label: "新签合同",
+        },
+        {
+          value: "续约合同",
+          label: "续约合同",
+        },
+        {
+          value: "补充协议",
+          label: "补充协议",
+        },
+      ], // 合同类型
+      statusArr: [], // 派点状态
+      defaultSalesProps: {
+        multiple: true,
+        label: "RealName",
+        children: "ChildrenList",
+        value: "AdminId",
+      }, //销售级联配置
+      tableList: [],
+      allocationVisible: false, // 派点
+    };
+  },
+  computed: {
+    exportExcel() {
+      let baseUrl = process.env.API_ROOT + "/statistic_report/will_expire_list";
+      let token = localStorage.getItem("auth") || "";
+      let paramStr = "";
+      let salesArr = [];
+      if (this.filterObj.sale.length) {
+        salesArr = this.filterObj.sale.map((item) => {
+          return item[item.length - 1];
+        });
+      }
+      let obj = {
+        PageSize: this.pageSize,
+        CurrentIndex: this.page_no,
+        CompanyType: this.filterObj.type,
+        AdminId: salesArr.join(","),
+        RegionType: this.filterObj.area,
+        EndDate: this.end_date,
+        StartDate: this.start_date,
+        Keyword: this.searchVal,
+        IsExport: true,
+      };
+      for (let key in obj) {
+        paramStr = `${paramStr}&${key}=${obj[key]}`;
+      }
+      return `${baseUrl}?${token}${paramStr}`;
+    },
+  },
+  watch: {},
+  created() {},
+  mounted() {
+    this.getSale();
+    /* 默认选中近1个月 */
+    this.filterDate(this.filterObj.month === "近1个月" ? 1 : this.filterObj.month === "近2个月" ? 2 : this.filterObj.month === "近3个月" ? 3 : 0);
+    this.$nextTick(() => {
+      this.tableList = [{ ContractCode: "HZEQ20230904002", CompanyName: "xxxx", CompanyId: 16 }];
+    });
+  },
+  methods: {
+    /* 切换月份 */
+    toggleMonth(label) {
+      this.filterObj.month = label;
+      let days = label == "近1个月" ? 1 : label == "近2个月" ? 2 : label == "近3个月" ? 3 : 0;
+      this.filterDate(days);
+    },
+    /* 获取近几个月的日期范围 */
+    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];
+        this.start_date = date_now;
+        this.end_date = date_after;
+        this.filterObj.date = date;
+        this.page_no = 1;
+        this.searchVal = "";
+        this.getTableData();
+      }
+    },
+    /* 获取销售 */
+    getSale() {
+      customInterence.getSale().then((res) => {
+        if (res.Ret === 200) {
+          this.salesArr = res.Data.List;
+        }
+      });
+    },
+    getTableData() {},
+  },
+};
+</script>
+<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>

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

@@ -0,0 +1,291 @@
+<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>
+      <date-picker
+        v-model="filterObj.date"
+        type="date"
+        range
+        value-type="format"
+        placeholder="自定义时间段"
+        :clearable="false"
+        :editable="false"
+        :disabled-date="disabledBeforeToday"
+        @change="dateChange"
+      />
+      <el-input placeholder="合同编号/客户名称/社会信用码" v-model="searchVal" style="width: 400px; margin-left: auto" @input="handleSearch" clearable>
+        <i slot="prefix" class="el-input__icon el-icon-search"></i>
+      </el-input>
+    </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.Item.length + 1" class="thead-rs">{{ item.Name }}</td>
+              </tr>
+              <tr v-for="rs in item.Item" :key="rs.AdminId" class="content-ul">
+                <td>{{ rs.Name }}</td>
+                <td class="association">{{ rs.ContractCount }}</td>
+                <td>{{ rs.TotalPoints }}</td>
+                <td>{{ rs.GroupPercentage }}</td>
+                <td>{{ rs.DepartmentPercentage }}</td>
+              </tr>
+            </tbody>
+
+            <tfoot>
+              <!-- <tr>
+              <td colspan="2">总合计</td>
+              <td v-for="(total_data, total_data_key) in totalGroupArr" :key="total_data_key">
+                {{ total_data.value !== 0 ? total_data.value : "" }}
+              </td>
+            </tr> -->
+            </tfoot>
+          </table>
+        </div>
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "",
+  components: {},
+  props: {},
+  data() {
+    return {
+      /* 筛选条件 */
+      filterObj: {
+        month: "近1个月",
+        date: [],
+        type: "",
+        sale: "",
+        area: "",
+      },
+      monthLabel: [
+        {
+          label: "近1个月",
+        },
+        {
+          label: "近2个月",
+        },
+        {
+          label: "近3个月",
+        },
+      ],
+      tableTheadColumns: ["组别", "研究员", "关联合同", "总派点", "组内占比", "部门占比"],
+      datalist: [
+        {
+          Item: [
+            {
+              Name: "测试1", // 研究员
+              AdminId: 517,
+              ContractCount: 0, // 关联合同
+              TotalPoints: 0, // 总派点
+              GroupPercentage: 0, // 组内占比
+              DepartmentPercentage: 0, // 部门占比
+            },
+            {
+              Name: "测试2", // 研究员
+              AdminId: 517,
+              ContractCount: 0, // 关联合同
+              TotalPoints: 0, // 总派点
+              GroupPercentage: 0, // 组内占比
+              DepartmentPercentage: 0, // 部门占比
+            },
+          ],
+          Name: "消费组", // 组别
+          GruopId: 0,
+        },
+        {
+          Item: [
+            {
+              Name: "测试1", // 研究员
+              AdminId: 517,
+              ContractCount: 0, // 关联合同
+              TotalPoints: 0, // 总派点
+              GroupPercentage: 0, // 组内占比
+              DepartmentPercentage: 0, // 部门占比
+            },
+            {
+              Name: "测试2", // 研究员
+              AdminId: 517,
+              ContractCount: 0, // 关联合同
+              TotalPoints: 0, // 总派点
+              GroupPercentage: 0, // 组内占比
+              DepartmentPercentage: 0, // 部门占比
+            },
+          ],
+          Name: "科技组", // 组别
+          GruopId: 0,
+        },
+      ],
+    };
+  },
+  computed: {
+    exportExcel() {
+      let baseUrl = process.env.API_ROOT + "/statistic_report/will_expire_list";
+      let token = localStorage.getItem("auth") || "";
+      let paramStr = "";
+      let salesArr = [];
+      if (this.filterObj.sale.length) {
+        salesArr = this.filterObj.sale.map((item) => {
+          return item[item.length - 1];
+        });
+      }
+      let obj = {
+        PageSize: this.pageSize,
+        CurrentIndex: this.page_no,
+        CompanyType: this.filterObj.type,
+        AdminId: salesArr.join(","),
+        RegionType: this.filterObj.area,
+        EndDate: this.end_date,
+        StartDate: this.start_date,
+        Keyword: this.searchVal,
+        IsExport: true,
+      };
+      for (let key in obj) {
+        paramStr = `${paramStr}&${key}=${obj[key]}`;
+      }
+      return `${baseUrl}?${token}${paramStr}`;
+    },
+  },
+  watch: {},
+  created() {},
+  mounted() {
+    /* 默认选中近1个月 */
+    this.filterDate(this.filterObj.month === "近1个月" ? 1 : this.filterObj.month === "近2个月" ? 2 : this.filterObj.month === "近3个月" ? 3 : 0);
+  },
+  methods: {
+    /* 切换月份 */
+    toggleMonth(label) {
+      this.filterObj.month = label;
+      let days = label == "近1个月" ? 1 : label == "近2个月" ? 2 : label == "近3个月" ? 3 : 0;
+      this.filterDate(days);
+    },
+    /* 获取近几个月的日期范围 */
+    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];
+        this.start_date = date_now;
+        this.end_date = date_after;
+        this.filterObj.date = date;
+        this.page_no = 1;
+        this.searchVal = "";
+        this.getTableData();
+      }
+    },
+  },
+};
+</script>
+<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>