baijunde 11 ヶ月 前
コミット
9f1296740d

+ 4 - 0
src/api/index.ts

@@ -35,6 +35,8 @@ import logApi from '@/api/modules/log.ts'
 
 import insurancePolicyApi from '@/api/modules/insurancePolicy.ts'
 
+import saleApi from '@/api/modules/sale.ts'
+
 const axiosInstance:ApiInstance = axios.create({
   baseURL: (import.meta.env.DEV && import.meta.env.VITE_OPEN_PROXY === 'true') ? '/proxy/' : import.meta.env.VITE_APP_API_BASEURL,
   timeout: 1000 * 60,
@@ -136,5 +138,7 @@ const api = {
   financeApi: financeApi(axiosInstance),
   invoiceRecordApi: invoiceRecordApi(axiosInstance),
   settlementApi: settlementApi(axiosInstance),
+  saleApi: saleApi(axiosInstance),
+
 }
 export default api

+ 28 - 0
src/api/modules/sale.ts

@@ -0,0 +1,28 @@
+import { ApiInstance } from '../type'
+const product = (axiosInstance: ApiInstance) => ({
+  //结构树
+  agreementdeptTree: (data: any) => axiosInstance.post('dept/getDeptTree',data),
+  //保存分销设置
+  saveSetting:(data:any)=>axiosInstance.post('sysDistributionSetting/saveSetting',data),
+  //查询分销设置
+  details:()=>axiosInstance.get(`sysDistributionSetting/getSettingBySystemCode`),
+  //修改分销设置
+  update:(data:any)=>axiosInstance.post('sysDistributionSetting/updateSetting',data),
+  deleteUser:(data:any)=>axiosInstance.post('userInfo/deleteDistribution',data),
+  getDistributionRelation:(params: any)=>axiosInstance.get('userInfo/getDistributionRelation',{params}),
+
+  /**
+   * @param 分销管理
+   */
+  list: (data: any) => axiosInstance.post('sysDistributionSetting/distributorList', data),
+
+  //佣金明细
+  commissionDetails:(data: any) => axiosInstance.post('sysDistributionSetting/commissionDetails', data),
+  export:(data: any) => axiosInstance.post('sysDistributionSetting/exportCommissionDetailsExcel', data,{responseType: 'blob'}),
+
+  //分销员审核列表
+    auditList:(data:any)=>axiosInstance.post('sysDistributionSetting/distributorAuditList',data),
+    distributorAudit:(data:any)=>axiosInstance.post('sysDistributionSetting/distributorAudit',data),
+})
+
+export default product

BIN
src/assets/images/check.png


+ 10 - 0
src/views/quoteConfig/dispatch/dispatch.vue

@@ -0,0 +1,10 @@
+<template>
+  <div>dispatch</div>
+</template>
+
+<script lang="ts" setup>
+</script>
+
+<style>
+
+</style>

+ 296 - 0
src/views/sale/commission.vue

@@ -0,0 +1,296 @@
+<template>
+  <div>
+    <PageMain class="vh100">
+      <ElForm
+        :inline="false"
+        :model="formInline"
+        class="demo-form-inline"
+        label-width="100px"
+      >
+        <ElRow :gutter="20">
+          <ElCol :md="8">
+            <ElFormItem label="分销员姓名">
+              <el-input
+                v-model="formInline.distributor"
+                placeholder="请输入姓名查找"
+                clearable
+                class="el-inputs"
+              />
+            </ElFormItem>
+          </ElCol>
+          <ElCol :md="8">
+            <ElFormItem label="分销员手机号">
+              <el-input
+                v-model="formInline.distributorMobile"
+                placeholder="请输入手机号查找"
+                clearable
+                class="el-inputs"
+              />
+            </ElFormItem>
+          </ElCol>
+          <!-- <ElCol :md="8">
+            <ElFormItem label="推荐上级">
+              <el-input
+                v-model="formInline.inviteePerson"
+                placeholder="请输入推荐人姓名查找"
+                clearable
+                class="el-inputs"
+              />
+            </ElFormItem>
+          </ElCol> -->
+          <ElCol :md="8">
+            <ElFormItem label="签单时间">
+              <el-date-picker
+                v-model="joinTimeRange"
+                type="daterange"
+                range-separator="至"
+                start-placeholder="开始时间"
+                end-placeholder="结束时间"
+                size="default"
+                format="YYYY-MM-DD"
+              />
+            </ElFormItem>
+          </ElCol>
+          <ElCol :md="6">
+            <ElFormItem>
+              <div class="flex j-end" style="width: 100%">
+                <el-button type="primary" @click="findpage">
+                  <template #icon>
+                    <SvgIcon name="i-ep:search" />
+                  </template>
+                  查询</el-button
+                >
+                <el-button type="default" @click="resetForm">重置</el-button>
+              </div>
+            </ElFormItem>
+          </ElCol>
+        </ElRow>
+      </ElForm>
+      <div>
+        <el-button type="default" @click="exportExcel">导出</el-button>
+      </div>
+      <div style="height: 559px;">
+        <el-table :data="tableData">
+          <el-table-column prop="orderNo" label="订单编号" width="180">
+            <template #default="{ row }">
+              <el-link
+                type="primary"
+                @click="handleOrderClick(row.orderNo, row)"
+              >
+                {{ row.orderNo }}
+              </el-link>
+            </template>
+          </el-table-column>
+          <el-table-column prop="premium" label="保费金额" width="180" />
+          <el-table-column prop="salesman" label="业务员" width="150" />
+          <el-table-column
+            prop="salesmanMobile"
+            label="业务员手机号"
+            width="180"
+          />
+          <el-table-column prop="signingTime" label="签单时间" width="180" />
+          <el-table-column prop="distributor" label="分销员" width="100" />
+          <el-table-column
+            prop="distributorMobile"
+            label="分销员手机号"
+            width="180"
+          />
+
+          <el-table-column prop="commission" label="分销员金额" width="180" />
+
+          <el-table-column
+            prop="distributionLevel"
+            label="分销员等级"
+            width="100"
+          >
+          <template #default="{ row }">
+             {{ row.distributionLevel==1?'一级分销':row.distributionLevel==2?'二级分销':'三级分销' }}
+            </template>
+        </el-table-column>
+          <el-table-column
+            prop="distributionRatio"
+            label="分销比例"
+            width="180"
+          />
+        </el-table>
+      </div>
+
+      <div class="pagination-wrapper">
+        <el-pagination
+          v-model:current-page="pageInfo.pageNum"
+          v-model:page-size="pageInfo.pageSize"
+          :page-sizes="[10, 20, 30, 50, 100]"
+          :total="pageInfo.total"
+          layout="total, sizes, prev, pager, next, jumper"
+          background
+          @size-change="handleSizeChange"
+          @current-change="handleCurrentChange"
+        />
+      </div>
+    </PageMain>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive, watch, onBeforeMount } from "vue";
+import api from "@/api";
+import { RouterLink, useRouter } from "vue-router";
+import {
+  ElMessage,
+  ElMessageBox,
+  formatter,
+  TableColumnCtx,
+} from "element-plus";
+import useAuth from "@/utils/composables/useAuth";
+import dayjs from "dayjs";
+import { template } from "lodash-es";
+const router = useRouter();
+const { auth } = useAuth();
+interface PageInfo {
+  pageNum: number;
+  pageSize: number;
+  sizes: number[];
+  total: number;
+}
+const provinceoptions = ref<string[]>([]); //省市区回显数据
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 100,
+});
+const formInline = reactive({
+  distributor: "",
+  distributorMobile: "",
+  inviteePerson: "",
+  signingTimeStart: "",
+  signingTimeEnd: "",
+});
+const joinTimeRange = ref([]);
+const tableData = ref([]);
+onBeforeMount(() => {
+  findpage(); //列表数据
+  if (auth("organizationlist.view")) {
+  }
+});
+function findpage() {
+  console.log(formInline);
+
+  api.saleApi
+    .commissionDetails({
+      pages: pageInfo.value.pageNum,
+      size: pageInfo.value.pageSize,
+      ...formInline,
+    })
+    .then((res: any) => {
+      if (res.code == 200) {
+        tableData.value = res.data.records;
+        pageInfo.value.pageNum = res.data.current;
+        pageInfo.value.pageSize = res.data.size;
+        pageInfo.value.total = res.data.total;
+      }
+    });
+}
+
+const resetForm = () => {
+  (formInline.distributor = ""),
+    (formInline.distributorMobile = ""),
+    (formInline.inviteePerson = ""),
+    (formInline.signingTimeStart = ""),
+    (formInline.signingTimeEnd = ""),
+    (provinceoptions.value = []);
+  findpage();
+};
+const exportExcel = () => {
+  api.saleApi.export({}).then((res) => {
+    console.log(res);
+    const blob = new Blob([res], { type: "application/vnd.ms-excel" });
+    const fileName = "分销佣金明细" + new Date().getTime() + ".xlsx";
+    if ("download" in document.createElement("a")) {
+      const elink = document.createElement("a");
+      elink.download = fileName;
+      elink.style.display = "none";
+      elink.href = URL.createObjectURL(blob);
+      document.body.appendChild(elink);
+      elink.click();
+      URL.revokeObjectURL(elink.href);
+      document.body.removeChild(elink);
+    } else {
+      navigator.msSaveBlob(blob, fileName);
+    }
+  });
+};
+// 每页显示条数改变
+const handleSizeChange = (newSize: number) => {
+  pageInfo.pageSize = newSize;
+  pageInfo.pageNum = 1; // 重置到第一页
+  findpage();
+};
+
+// 当前页改变
+const handleCurrentChange = (newPage: number) => {
+  pageInfo.pageNum = newPage;
+  findpage();
+};
+const handleOrderClick = (orderNo: string, row: any) => {
+  const resolved = router.resolve({
+    path: `/additionalOrder/order/orderDetail`,
+     query: { 
+      id: row.orderNo  // 查询参数,id 的值为 row.orderNo
+    }
+  });
+  window.open(resolved.href, '_blank');
+};
+watch(
+  joinTimeRange,
+  (newRange) => {
+    if (Array.isArray(newRange) && newRange.length === 2) {
+      formInline.signingTimeStart = dayjs(newRange[0]).format("YYYY-MM-DD");
+      formInline.signingTimeEnd = dayjs(newRange[1]).format("YYYY-MM-DD");
+    } else {
+      formInline.signingTimeStart = "";
+      formInline.signingTimeEnd = "";
+    }
+  },
+  { immediate: true }
+);
+</script>
+
+<style lang="scss" scoped>
+.demo-form-inline .el-input {
+  --el-input-width: 220px;
+}
+
+.demo-form-inline .el-select {
+  --el-select-width: 220px;
+}
+
+:deep(.el-dropdown-link) {
+  display: flex;
+  align-items: center;
+  margin-left: 15px;
+  color: var(--el-color-primary);
+  cursor: pointer;
+}
+
+.el-inputs {
+  width: 100% !important;
+}
+::v-deep.el-table td.el-table__cell div i {
+  display: none;
+}
+::v-deep.el-table .caret-wrapper {
+  display: none;
+}
+:deep(.current-style) {
+  color: #339dff;
+  position: relative;
+  padding-left: 20px;
+}
+.pagination-wrapper {
+  display: flex;
+  justify-content: flex-end; // 右对齐
+  width: 100%;
+  padding: 20px 0;
+}
+</style>

+ 173 - 0
src/views/sale/components/drawer.vue

@@ -0,0 +1,173 @@
+<template>
+  <div>
+    <el-drawer 
+      v-model="props.Drawer" 
+      :direction="direction" 
+      @open="DrawerOpen" 
+      @close="cancel" 
+      :close-on-click-modal="false"
+    >
+      <template #header>
+        <h4>参与机构</h4>
+      </template>
+      <template #default>
+        <div class="flex f-c">
+          <div>
+            <el-input 
+              v-model="deptName" 
+              class="m-right-20" 
+              style="width: 240px;" 
+              placeholder="输入名称"
+              :prefix-icon="Search" 
+            />
+            <el-button @click="query">查询</el-button>
+          </div>
+          <!-- 全选复选框 -->
+          <el-checkbox 
+            v-model="checkedALL" 
+            label="全选" 
+            size="large"
+            @change="handleCheckAllChange"
+          />
+          <!-- 树形组件 -->
+          <el-tree 
+            :data="props.deptlist" 
+            :show-checkbox="true" 
+            node-key="id" 
+            ref="treeRef" 
+            :props="defaultProps"
+            :default-expand-all="true" 
+            @check="handleCheck" 
+            :default-checked-keys="props.checkedKeys"
+            :check-strictly="true" 
+          />
+        </div>
+      </template>
+      <template #footer>
+        <div>
+          <el-button @click="cancel">取消</el-button>
+          <el-button type="primary" @click="save">保存</el-button>
+        </div>
+      </template>
+    </el-drawer>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { defineProps, defineEmits, ref, watch, nextTick } from "vue";
+import { DrawerProps } from 'element-plus';
+import { Search } from '@element-plus/icons-vue'
+import { ElTree } from 'element-plus';
+
+// 定义属性类型
+interface DeptNode {
+  id: string;
+  name: string;
+  children?: DeptNode[];
+}
+
+const props = defineProps<{
+  Drawer: boolean;
+  deptlist: DeptNode[];
+  checkedKeys: string[];
+  checkedIds: string[];
+}>();
+
+const emits = defineEmits(["cancel", 'save', 'DrawerOpen', 'query']);
+
+// 树形组件配置
+const defaultProps = {
+  children: 'children',
+  label: 'name',
+};
+
+const direction = ref<DrawerProps['direction']>('rtl');
+const deptName = ref('');
+const treeRef = ref<InstanceType<typeof ElTree>>();
+const checkedALL = ref(false);
+const ids = ref<string[]>([]);
+
+// 当抽屉打开时初始化全选状态
+const DrawerOpen = () => {
+  nextTick(() => {
+    updateCheckAllStatus();
+  });
+};
+
+// 监听属性变化,更新选中状态和全选状态
+watch(props, () => {
+  if (props.Drawer) {
+    ids.value = [...props.checkedIds];
+    nextTick(() => {
+      updateCheckAllStatus();
+    });
+  }
+}, { deep: true });
+
+// 处理全选状态变化
+const handleCheckAllChange = (checked: boolean) => {
+  if (!treeRef.value) return;
+  
+  if (checked) {
+    // 全选:获取所有节点ID并选中
+    const allIds = getAllNodeIds(props.deptlist);
+    treeRef.value.setCheckedKeys(allIds);
+    ids.value = allIds;
+  } else {
+    // 取消全选:清空选中
+    treeRef.value.setCheckedKeys([]);
+    ids.value = [];
+  }
+};
+
+// 处理树形组件选择变化
+const handleCheck = (
+  _checkedNodes: any[],
+  checkedInfo: {
+    checkedKeys: string[];
+    checkedNodes: any[];
+    halfCheckedKeys: any[];
+    halfCheckedNodes: any[];
+  }
+) => {
+  ids.value = checkedInfo.checkedKeys;
+  updateCheckAllStatus(); // 更新全选框状态
+};
+
+// 更新全选框状态
+const updateCheckAllStatus = () => {
+  if (!treeRef.value) return;
+  
+  const allIds = getAllNodeIds(props.deptlist);
+  // 当所有节点都被选中时,全选框才勾选
+  checkedALL.value = allIds.length > 0 && 
+    ids.value.length === allIds.length &&
+    allIds.every(id => ids.value.includes(id));
+};
+
+// 递归获取所有节点的ID
+const getAllNodeIds = (nodes: DeptNode[], result: string[] = []): string[] => {
+  nodes.forEach(node => {
+    result.push(node.id);
+    if (node.children && node.children.length > 0) {
+      getAllNodeIds(node.children, result);
+    }
+  });
+  return result;
+};
+
+// 取消操作
+const cancel = () => {
+  emits('cancel');
+};
+
+// 保存操作
+const save = () => {
+  emits('save', ids.value);
+};
+
+// 查询操作
+const query = () => {
+  emits('query', deptName.value);
+};
+</script>

+ 535 - 0
src/views/sale/list.vue

@@ -0,0 +1,535 @@
+<template>
+  <div>
+    <PageMain class="vh100">
+      <ElForm
+        :inline="false"
+        :model="formInline"
+        class="demo-form-inline"
+        label-width="100px"
+      >
+        <ElRow :gutter="20">
+          <ElCol :md="8">
+            <ElFormItem label="姓名">
+              <el-input
+                v-model="formInline.name"
+                placeholder="请输入姓名查找"
+                clearable
+                class="el-inputs"
+              />
+            </ElFormItem>
+          </ElCol>
+          <ElCol :md="8">
+            <ElFormItem label="手机号">
+              <el-input
+                v-model="formInline.mobile"
+                placeholder="请输入手机号查找"
+                clearable
+                class="el-inputs"
+              />
+            </ElFormItem>
+          </ElCol>
+          <ElCol :md="8">
+            <ElFormItem label="推荐上级">
+              <el-input
+                v-model="formInline.inviteePerson"
+                placeholder="请输入推荐人姓名查找"
+                clearable
+                class="el-inputs"
+              />
+            </ElFormItem>
+          </ElCol>
+          <ElCol :md="8">
+            <ElFormItem label="申请时间">
+              <el-date-picker
+                v-model="joinTimeRange"
+                type="daterange"
+                range-separator="至"
+                start-placeholder="开始时间"
+                end-placeholder="结束时间"
+                size="default"
+                format="YYYY-MM-DD"
+              />
+            </ElFormItem>
+          </ElCol>
+          <ElCol :md="6" :offset="10">
+            <ElFormItem>
+              <div class="flex j-end" style="width: 100%">
+                <el-button type="primary" @click="roleQuery">
+                  <template #icon>
+                    <SvgIcon name="i-ep:search" />
+                  </template>
+                  查询</el-button
+                >
+                <el-button type="default" @click="resetForm">重置</el-button>
+              </div>
+            </ElFormItem>
+          </ElCol>
+        </ElRow>
+      </ElForm>
+      <ComplexTable
+        :tableData="tableData"
+        :columns="columns"
+        :showIndex="false"
+        :columnwidth="200"
+        :showSelect="true"
+        :pageInfo="pageInfo"
+        @getList="getList"
+        @selectionChange="selectionChange"
+      >
+        <template v-slot:operation="scope">
+          <el-button type="text" @click="backtopEmits(scope.operationData)">
+            清退
+          </el-button>
+          <el-button type="text" @click="look(scope.operationData)">
+            关系查询
+          </el-button>
+        </template>
+      </ComplexTable>
+    </PageMain>
+    <el-dialog
+      v-model="dialogVisible"
+      title="分销员清退"
+      width="700"
+      :before-close="handleClose"
+    >
+      <p>正在选择清退分销员{{ deleteData.name }}</p>
+      <p>
+        清退后,将不在支持该分销员发展下级,也不在享受订单的分销佣金;原有的分销佣金不受影响。
+      </p>
+      <div>
+        <el-radio-group
+          v-model="deleteData.type"
+          style="display: flex; flex-direction: column; align-items: start"
+        >
+          <el-radio :value="1">不处理,分销员关系保留</el-radio>
+          <el-radio :value="2">解除分销员和下级的绑定关系</el-radio>
+          <el-radio :value="3"
+            >转移下级分销员给某一个分销员
+            <el-input
+              v-model="deleteData.mobile"
+              maxlength="11"
+              :style="{
+                width: '240px',
+                marginLeft: '20px',
+                border:
+                  deleteData.type === 3 &&
+                  (!deleteData.mobile || deleteData.mobile.trim() === '')
+                    ? '1px solid #f56c6c'
+                    : '1px solid #dcdfe6',
+              }"
+              placeholder="输入接收人手机号"
+            />
+            <span
+              v-if="
+                deleteData.type === 3 &&
+                (!deleteData.mobile || deleteData.mobile.trim() === '')
+              "
+              style="color: #f56c6c; font-size: 12px; margin-left: 20px"
+            >
+              {{ errorTitle }}
+            </span>
+          </el-radio>
+        </el-radio-group>
+      </div>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="dialogVisible = false">取消</el-button>
+          <el-button type="primary" @click="deleteUser"> 确定清退 </el-button>
+        </div>
+      </template>
+    </el-dialog>
+    <!-- 关系弹窗 -->
+    <el-dialog
+      v-model="isRelation"
+      title="关系查询"
+      width="700"
+      :before-close="handleClose"
+    >
+      <el-table
+        :data="relationTreeData"
+        style="width: 100%; margin-bottom: 20px"
+        row-key="id"
+        default-expand-all
+        :indent="16"
+        :tree-props="{ children: 'children' }"
+        :row-class-name="getRowClassName"
+      >
+        <el-table-column prop="name" label="姓名" sortable> </el-table-column>
+        <el-table-column prop="mobile" label="手机号" sortable />
+        <el-table-column prop="distributionTime" label="加入时间" sortable />
+      </el-table>
+    </el-dialog>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive, watch, onBeforeMount } from "vue";
+import api from "@/api";
+import { RouterLink, useRouter } from "vue-router";
+import {
+  ElMessage,
+  ElMessageBox,
+  formatter,
+  TableColumnCtx,
+} from "element-plus";
+import useAuth from "@/utils/composables/useAuth";
+import dayjs from "dayjs";
+const { auth } = useAuth();
+interface PageInfo {
+  pageNum: number;
+  pageSize: number;
+  sizes: number[];
+  total: number;
+}
+const props = {
+  expandTrigger: "hover" as const,
+  value: "areaCode",
+  label: "areaCname",
+  children: "child",
+};
+const sysUpAndDownList = ref<string[]>([]); //选中id
+const provinceoptions = ref<string[]>([]); //省市区回显数据
+const areaOptions = ref(); //省市区数据
+// const provinceChange = (value: any) => {
+//   if (value && value[0] != null && value[1] != null && value[2] != null) {
+//     formInline.provinceId = value[0];
+//     formInline.cityId = value[1];
+//     formInline.districtId = value[2];
+//   } else {
+//     formInline.provinceId = "";
+//     formInline.cityId = "";
+//     formInline.districtId = "";
+//   }
+// };
+const router = useRouter();
+const pageInfo = ref({
+  pageNum: 1,
+  pageSize: 10,
+  sizes: [10, 20, 30, 40, 50],
+  total: 0,
+});
+const sysTypelist = ref([
+  {
+    id: 0,
+    name: "保险公司",
+  },
+  {
+    id: 1,
+    name: "保险分公司",
+  },
+  {
+    id: 2,
+    name: "保险经济公司",
+  },
+  {
+    id: 3,
+    name: "汽车经销商",
+  },
+  {
+    id: 4,
+    name: "保险代理公司",
+  },
+]);
+const formInline = reactive({
+  name: "",
+  mobile: "",
+  inviteePerson: "",
+  joinTimeStart: "",
+  joinTimeEnd: "",
+});
+const joinTimeRange = ref([]);
+const tableData = ref([]);
+const dialogVisible = ref(false);
+const deleteData = ref({
+  type: 0,
+  mobile: "",
+  id: "",
+  name: "",
+});
+const relationTreeData = ref([]);
+const isRelation = ref(false);
+const currentName = ref("");
+const errorTitle = ref("请输入接收人手机号");
+onBeforeMount(() => {
+  findpage(); //列表数据
+  if (auth("organizationlist.view")) {
+  }
+});
+function findpage() {
+
+  api.saleApi
+    .list({
+      pages: pageInfo.value.pageNum,
+      size: pageInfo.value.pageSize,
+      ...formInline,
+    })
+    .then((res: any) => {
+      if (res.code == 200) {
+        tableData.value = res.data.records;
+        pageInfo.value.pageNum = res.data.current;
+        pageInfo.value.pageSize = res.data.size;
+        pageInfo.value.total = res.data.total;
+      }
+    });
+}
+const columns = [
+  { prop: "name", label: "姓名", width: "120" },
+  {
+    prop: "mobile",
+    label: "手机号",
+    width: "200",
+  },
+  {
+    prop: "typeAttr",
+    label: "类型",
+    width: "120",
+    formatter: (row: any) => {
+      if (row.typeAttr == 5) {
+        return '团队'
+      } else if(row.typeAttr ==6) {
+        return "个代"
+      }else if(row.typeAttr ==7) {
+        return "渠道"
+      }else if(row.typeAttr ==8) {
+        return "电销组"
+      }else  {
+        return "其他"
+      }
+    }
+  },
+  {
+    prop: "deptName",
+    label: "所属机构",
+    width: "120",
+  },
+  {
+    prop: "inviteePerson",
+    label: "推荐上级",
+    width: "120",
+  },
+  { prop: "totalPremium", label: "累计出单保费", width: "150" },
+  { prop: "totalFee", label: "累计佣金", width: "200" },
+  { prop: "totalInvite", label: "累计邀请", width: "150" },
+  { prop: "joinTime", label: "加入时间", width: "180" },
+];
+
+function getList(item: PageInfo) {
+  pageInfo.value.pageNum = item.pageNum;
+  pageInfo.value.pageSize = item.pageSize;
+  findpage();
+}
+function tenantUpdate(item: any) {
+  router.push({
+    name: "OrganizationAdd",
+    query: {
+      id: item.id,
+    },
+  });
+}
+
+const selectionChange = (val: any) => {
+  sysUpAndDownList.value = val;
+};
+//禁用
+const disable = (value: string) => {
+  ElMessageBox.confirm(
+    "确定要禁用该业务员账号吗,禁用后该业务员账户不可登录App进行车险出单业务?",
+    "禁用租户",
+    {
+      confirmButtonText: "确定禁用",
+      type: "warning",
+      center: true,
+    }
+  )
+    .then(() => {
+      sysUpAndDown(0, [value]);
+    })
+    .catch(() => {});
+};
+//启用
+const enable = (value: string) => {
+  sysUpAndDown(1, [value]);
+};
+//批量删除
+const batchDel = () => {
+  ElMessageBox.confirm("机构删除后不可恢复,请谨慎操作", "确定删除机构?", {
+    confirmButtonText: "确定删除",
+    cancelButtonText: "取消",
+    type: "error",
+    center: true,
+  })
+    .then(() => {
+      api.tenantApi.sysDelete(sysUpAndDownList.value).then((res: any) => {
+        if (res.code == "200") {
+          ElMessage({
+            type: "success",
+            message: res.msg,
+            plain: true,
+          });
+          findpage();
+        }
+      });
+    })
+    .catch(() => {});
+};
+//批量禁用
+const batchdisable = () => {
+  ElMessageBox.confirm(
+    "确定要禁用该业务员账号吗,禁用后该业务员账户不可登录App进行车险出单业务?",
+    "禁用租户",
+    {
+      confirmButtonText: "确定禁用",
+      cancelButtonText: "取消",
+      type: "error",
+      center: true,
+    }
+  )
+    .then(async () => {
+      await sysUpAndDown(0, undefined);
+    })
+    .catch(() => {});
+};
+//批量启用
+const batchenable = async () => {
+  await sysUpAndDown(1, undefined);
+};
+const roleQuery = () => {
+  findpage();
+};
+const sysUpAndDown = async (type: number, list?: string[]) => {
+  await api.tenantApi
+    .sysUpAndDown({ ids: list ? list : sysUpAndDownList.value, opType: type })
+    .then((res: any) => {
+      if (res.code == "200") {
+        findpage();
+        ElMessage({
+          type: "success",
+          message: res.msg,
+          plain: true,
+        });
+      }
+    });
+};
+//添加子机构
+const subOrganizationAdd = (code: string) => {
+  router.push({
+    name: "OrganizationDeptAdd",
+    query: {
+      code: code,
+    },
+  });
+};
+const resetForm = () => {
+  (formInline.name = ""),
+    (formInline.mobile = ""),
+    (formInline.inviteePerson = ""),
+    (formInline.joinTimeStart = ""),
+    (formInline.joinTimeEnd = ""),
+    (provinceoptions.value = []);
+  findpage();
+};
+//清退
+const backtopEmits = (row: any) => {
+
+  deleteData.value.id = row.id;
+  deleteData.value.name = row.name;
+  dialogVisible.value = true;
+};
+//清退确认
+const deleteUser = () => {
+  if (deleteData.value.type == 0) {
+    ElMessage({
+      message: "请选择清退方式",
+      type: "error",
+    });
+    return;
+  }else{
+     api.saleApi
+    .deleteUser({
+      ids: deleteData.value.id.split(","),
+      // ...deleteData.value
+      type: deleteData.value.type,
+      mobile: deleteData.value.mobile,
+    })
+    .then((res: any) => {
+      if (res.code == 200) {
+        ElMessage({
+          message: "清退成功",
+          type: "success",
+        });
+          dialogVisible.value = false;
+        findpage();
+      }else{
+        errorTitle.value = res.msg
+      }
+    });
+  }
+ 
+
+};
+
+//关系查询
+const look = (row: any) => {
+  currentName.value = row.name;
+
+  api.saleApi.getDistributionRelation({ id: row.id }).then((res) => {
+    relationTreeData.value = res.data;
+    isRelation.value = true;
+  });
+};
+
+const getRowClassName = ({ row }: { row: any }) => {
+  if (row.name == currentName.value) {
+
+    return "current-style";
+  } else {
+    return "";
+  }
+};
+watch(
+  joinTimeRange,
+  (newRange) => {
+    if (Array.isArray(newRange) && newRange.length === 2) {
+      formInline.joinTimeStart = dayjs(newRange[0]).format("YYYY-MM-DD");
+      formInline.joinTimeEnd = dayjs(newRange[1]).format("YYYY-MM-DD");
+    } else {
+      formInline.joinTimeStart = "";
+      formInline.joinTimeEnd = "";
+    }
+  },
+  { immediate: true }
+);
+</script>
+
+<style lang="scss" scoped>
+.demo-form-inline .el-input {
+  --el-input-width: 220px;
+}
+
+.demo-form-inline .el-select {
+  --el-select-width: 220px;
+}
+
+:deep(.el-dropdown-link) {
+  display: flex;
+  align-items: center;
+  margin-left: 15px;
+  color: var(--el-color-primary);
+  cursor: pointer;
+}
+
+.el-inputs {
+  width: 100% !important;
+}
+::v-deep.el-table td.el-table__cell div i {
+  display: none;
+}
+::v-deep.el-table .caret-wrapper {
+  display: none;
+}
+:deep(.current-style) {
+  color: #339dff;
+  position: relative;
+  padding-left: 20px;
+}
+</style>

+ 724 - 0
src/views/sale/review.vue

@@ -0,0 +1,724 @@
+<template>
+  <div class="order">
+    <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
+      <el-tab-pane name="first">
+        <template #label> 待审核({{ total1 }}) </template>
+        <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.name"
+                  placeholder="请输入姓名查找"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="手机号">
+                <el-input
+                  v-model="form.mobile"
+                  placeholder="请输入手机号查找"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="推荐上级">
+                <el-input v-model="form.inviteePerson"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="申请时间">
+                <el-date-picker
+                  v-model="joinTimeRange"
+                  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="24" style="display: flex; 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="tableData1" style="margin-top: 24px" hight="500">
+          <el-table-column label="姓名" prop="name" width="200">
+          </el-table-column>
+          <el-table-column label="手机号" prop="mobile"></el-table-column>
+          <el-table-column label="类型" prop="typeAttr">
+            <template #default="scope">
+              {{
+                scope.row.typeAttr == "5"
+                  ? "团队"
+                  : scope.row.typeAttr == "6"
+                  ? "个代"
+                  : scope.row.typeAttr == "7"
+                  ? "渠道"
+                  : scope.row.typeAttr== "8"
+                  ? "电销组"
+                  : "--"
+              }}
+            </template>
+          </el-table-column>
+          <el-table-column label="所属机构" prop="deptName"></el-table-column>
+          <el-table-column
+            label="推荐上级"
+            prop="referrerName"
+          ></el-table-column>
+          <el-table-column label="申请时间" prop="applyTime"></el-table-column>
+          <el-table-column label="操作" fixed="right" width="200">
+            <template #default="scope">
+              <!-- <el-button link type="primary">审核通过</el-button> -->
+              <el-popconfirm
+                title="确定审核通过?"
+                :hide-icon="true"
+                @confirm="review(scope.row)"
+              >
+                <template #reference>
+                  <el-button type="text">审核通过</el-button>
+                </template>
+              </el-popconfirm>
+              <!-- <el-button link type="primary" @click="handleEdit(scope.row)"
+                >驳回</el-button
+              > -->
+              <el-popconfirm
+                width="220"
+                title="审核驳回"
+                @confirm="reviewReject(scope.row)"
+              >
+                <template #reference>
+                  <el-button type="text">驳回</el-button>
+                </template>
+                <template #default="{}"> </template>
+                <template #actions="{ confirm, cancel }">
+                  <el-input
+                    v-model="remark"
+                    style="width: 100%; margin: 10px 0"
+                    :rows="2"
+                    type="textarea"
+                    placeholder="请输入驳回原因"
+                  />
+                  <el-button size="small" @click="cancel">取消</el-button>
+                  <el-button type="danger" size="small" @click="confirm">
+                    确认驳回
+                  </el-button>
+                </template>
+              </el-popconfirm>
+            </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="total1"
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+          ></el-pagination>
+        </div>
+      </el-tab-pane>
+      <el-tab-pane name="second">
+        <template #label> 审核通过({{ total2 }}) </template>
+        <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.name"
+                  placeholder="请输入姓名查找"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="手机号">
+                <el-input
+                  v-model="form.mobile"
+                  placeholder="请输入手机号查找"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="推荐上级">
+                <el-input v-model="form.inviteePerson"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="申请时间">
+                <el-date-picker
+                  v-model="joinTimeRange"
+                  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-input v-model="form.auditPerson"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="审核时间">
+                <el-date-picker
+                  v-model="reviewTimeRange"
+                  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="24" style="display: flex; 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="tableData2" style="margin-top: 24px" hight="500">
+          <el-table-column label="审核人" prop="auditPerson" width="200">
+          </el-table-column>
+          <el-table-column label="审核时间" prop="applyTime"></el-table-column>
+          <el-table-column label="姓名" prop="name" width="200">
+          </el-table-column>
+          <el-table-column label="手机号" prop="mobile"></el-table-column>
+          <el-table-column label="类型" prop="typeAttr">
+            <template #default="scope">
+              {{
+                scope.row.typeAttr == "5"
+                  ? "团队"
+                  : scope.row.typeAttr == "6"
+                  ? "个代"
+                  : scope.row.typeAttr == "7"
+                  ? "渠道"
+                  : scope.row.typeAttr== "8"
+                  ? "电销组"
+                  : "--"
+              }}
+            </template>
+          </el-table-column>
+          <el-table-column label="所属机构" prop="deptName"></el-table-column>
+          <el-table-column
+            label="推荐上级"
+            prop="referrerName"
+          ></el-table-column>
+          <el-table-column label="申请时间" prop="applyTime"></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="total2"
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+          ></el-pagination>
+        </div>
+      </el-tab-pane>
+      <el-tab-pane name="third">
+        <template #label> 审核不通过({{ total3 }}) </template>
+        <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.name"
+                  placeholder="请输入姓名查找"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="手机号">
+                <el-input
+                  v-model="form.mobile"
+                  placeholder="请输入手机号查找"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="推荐上级">
+                <el-input v-model="form.inviteePerson"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="申请时间">
+                <el-date-picker
+                  v-model="joinTimeRange"
+                  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-input v-model="form.auditPerson"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="审核时间">
+                <el-date-picker
+                  v-model="form.recordingTime"
+                  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="24" style="display: flex; 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="tableData3" style="margin-top: 24px" height="500">
+          <el-table-column
+            label="审核人"
+            prop="auditPerson"
+            width="120"
+          ></el-table-column>
+          <el-table-column
+            label="审核时间"
+            prop="auditTime"
+            width="220"
+          ></el-table-column>
+          <el-table-column
+            label="驳回原因"
+            prop="remark"
+            width=""
+            show-overflow-tooltip
+          ></el-table-column>
+          <el-table-column
+            label="姓名"
+            prop="name"
+            width="120"
+          ></el-table-column>
+          <el-table-column
+            label="手机号"
+            prop="mobile"
+            width="120"
+          ></el-table-column>
+          <el-table-column
+            label="类型"
+            prop="typeAttr"
+            width="120"
+          >
+        <template #default="scope">
+              {{
+                scope.row.typeAttr == "5"
+                  ? "团队"
+                  : scope.row.typeAttr == "6"
+                  ? "个代"
+                  : scope.row.typeAttr == "7"
+                  ? "渠道"
+                  : scope.row.typeAttr== "8"
+                  ? "电销组"
+                  : "--"
+              }}
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="所属机构"
+            prop="deptName"
+            width="120"
+          ></el-table-column>
+          <el-table-column
+            label="推荐上级"
+            prop="referrerName"
+            width="120"
+          ></el-table-column>
+          <el-table-column
+            label="申请时间"
+            prop="applyTime"
+            width="220"
+          ></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="total3"
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+          ></el-pagination>
+        </div>
+      </el-tab-pane>
+      <el-tab-pane name="fourthly">
+        <template #label> 自动审核{{ total4 }}) </template>
+        <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.name"
+                  placeholder="请输入姓名查找"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="手机号">
+                <el-input
+                  v-model="form.mobile"
+                  placeholder="请输入手机号查找"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="推荐上级">
+                <el-input v-model="form.inviteePerson"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="8">
+              <el-form-item label="申请时间">
+                <el-date-picker
+                  v-model="joinTimeRange"
+                  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="24" style="display: flex; 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="tableData4" style="margin-top: 24px" height="500">
+          <el-table-column label="审核人" prop="auditPerson" width="200">
+          </el-table-column>
+          <el-table-column label="审核时间" prop="auditTime"></el-table-column>
+          <el-table-column label="姓名" prop="name" width="200">
+          </el-table-column>
+          <el-table-column label="手机号" prop="mobile"></el-table-column>
+          <el-table-column label="类型" prop="typeAttr">
+            <template #default="scope">
+              {{
+                scope.row.typeAttr == "5"
+                  ? "团队"
+                  : scope.row.typeAttr == "6"
+                  ? "个代"
+                  : scope.row.typeAttr == "7"
+                  ? "渠道"
+                  : scope.row.typeAttr== "8"
+                  ? "电销组"
+                  : "--"
+              }}
+            </template>
+          </el-table-column>
+          <el-table-column label="所属机构" prop="deptName"></el-table-column>
+          <el-table-column
+            label="推荐上级"
+            prop="referrerName"
+          ></el-table-column>
+          <el-table-column label="申请时间" prop="applyTime"></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="total4"
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+          ></el-pagination>
+        </div>
+      </el-tab-pane>
+    </el-tabs>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useRouter } from "vue-router";
+import { ref, reactive, watch, toRaw, computed, onMounted } from "vue";
+import api from "@/api";
+import { ElMessage, ElMessageBox } from "element-plus";
+import dayjs from "dayjs";
+const joinTimeRange = ref([]);
+const reviewTimeRange = ref([]);
+const myRouter = useRouter();
+const remark = ref("");
+let activeName = ref("first");
+let type = ref("first");
+const handleClick = (e) => {
+  pages.value = 1;
+  size.value = 10;
+  form.value = {};
+  type.value = e.props.name;
+  switch (e.props.name) {
+    case "first":
+      initData(0);
+      break;
+    case "second":
+      initData(1);
+      break;
+    case "third":
+      initData(2);
+      break;
+    case "fourthly":
+      initData(3);
+      break;
+  }
+};
+
+let form = ref({});
+const tableProps = ref({
+  value: "id",
+  label: "name",
+  children: "children",
+  checkStrictly: true,
+});
+let option = ref([]);
+const timeChange = (val) => {};
+// 搜索
+const search = () => {
+  switch (type.value) {
+    case "first":
+      initData(0);
+      break;
+    case "second":
+      initData(1);
+      break;
+    case "third":
+      initData(2);
+      break;
+    case "fourthly":
+      initData(3);
+      break;
+  }
+};
+const reset = () => {
+  form.value = {};
+  initData(type.value);
+};
+
+// 列表
+let tableData1 = ref([]);
+let tableData2 = ref([]);
+let tableData3 = ref([]);
+let tableData4 = ref([]);
+const handleEdit = (row) => {
+  myRouter.push({
+    path: "/additionalOrder/additionalOrderIndex",
+    query: {
+      id: row.id,
+    },
+  });
+};
+const handleDel = (row) => {
+  ElMessageBox({
+    title: "提示",
+    message: "确认要删除当前数据吗?",
+    confirmButtonText: "确认",
+    cancelButtonText: "取消",
+    type: "warning",
+    center: true,
+  }).then((action) => {
+    if (action === "confirm") {
+      api.additionalApi.deleteById(row.id).then((res: any) => {
+        if (res.code == 200) {
+          ElMessage({
+            message: res.msg,
+            type: "success",
+          });
+          switch (type.value) {
+            case "first":
+              initData(0);
+              break;
+            case "second":
+              initData(1);
+              break;
+            case "third":
+              initData(2);
+              break;
+            case "fourthly":
+              initData(3);
+              break;
+          }
+        } else {
+          ElMessage({
+            message: res.msg,
+            type: "warning",
+          });
+        }
+      });
+    }
+  });
+};
+const review = (row: any) => {
+  console.log(row);
+  api.saleApi.distributorAudit({ id: row.id, auditStatus: 1 }).then((res) => {
+    reset();
+    initData(0);
+    initData(1);
+    initData(2);
+    initData(3);
+  });
+};
+
+const reviewReject = (row: any) => {
+  console.log(row);
+  if (!remark.value) {
+    ElMessage({
+      message: "请填写审核拒绝原因",
+      type: "warning",
+    });
+  } else {
+    api.saleApi
+      .distributorAudit({ id: row.id, auditStatus: 2, remark: remark.value })
+      .then((res) => {
+        reset();
+        initData(0);
+        initData(1);
+        initData(2);
+        initData(3);
+      });
+  }
+};
+
+// 分页
+let pages = ref(1);
+let size = ref(10);
+let total1 = ref(0);
+let total2 = ref(0);
+let total3 = ref(0);
+let total4 = ref(0);
+const handleSizeChange = (size) => {
+  size.value = size;
+  initData(type.value);
+};
+const handleCurrentChange = (page) => {
+  pages.value = page;
+  initData(type.value);
+};
+
+const initData = (type) => {
+  api.saleApi
+    .auditList({
+      pages: pages.value,
+      size: size.value,
+      isTemporarily: 0,
+      auditStatus: type,
+      orderNo: form.value.orderNo,
+      salesman: form.value.salesman,
+      salesmanCompany: form.value.salesmanCompany,
+      companyName: form.value.companyName,
+      licenseNo: form.value.licenseNo,
+      recordingTime: form.value.recordingTime,
+    })
+    .then((res: any) => {
+      if (res.code == 200) {
+        switch (type) {
+          case 0:
+            tableData1.value = res.data.records;
+            total1.value = res.data.total;
+            break;
+          case 1:
+            tableData2.value = res.data.records;
+            total2.value = res.data.total;
+            break;
+          case 2:
+            tableData3.value = res.data.records;
+            total3.value = res.data.total;
+            break;
+          case 3:
+            tableData4.value = res.data.records;
+            total4.value = res.data.total;
+            break;
+        }
+      } else {
+        ElMessage({
+          message: res.msg,
+          type: "warning",
+        });
+      }
+    });
+};
+
+// 获取保险公司
+let companyList = ref([]);
+const initCompany = () => {
+  api.insuranceApi.leftList("").then((res) => {
+    if (res.code == 200) {
+      companyList.value = res.data;
+    }
+  });
+};
+
+onMounted(() => {
+  initData(0);
+  initData(1);
+  initData(2);
+  initData(3);
+  // initCompany();
+});
+watch(
+  [joinTimeRange, reviewTimeRange],
+  ([newJoinRange, newReviewRange]) => {
+    if (Array.isArray(newJoinRange) && newJoinRange.length === 2) {
+      form.applyTimeStart = dayjs(newJoinRange[0]).format("YYYY-MM-DD");
+      form.applyTimeEnd = dayjs(newJoinRange[1]).format("YYYY-MM-DD");
+    } else {
+      form.applyTimeStart = "";
+      form.applyTimeEnd = "";
+    }
+
+    // 处理 reviewTimeRange
+    if (Array.isArray(newReviewRange) && newReviewRange.length === 2) {
+      form.auditTimeStart = dayjs(newReviewRange[0]).format("YYYY-MM-DD");
+      form.auditTimeEnd = dayjs(newReviewRange[1]).format("YYYY-MM-DD");
+    } else {
+      form.auditTimeStart = "";
+      form.auditTimeEnd = "";
+    }
+  },
+  { immediate: true }
+);
+</script>
+
+<style scoped lang="scss">
+.order {
+  width: 100%;
+  height: calc(100vh - 120px);
+  background: #ffffff;
+  padding: 24px;
+  overflow-y: auto;
+  .pagination {
+    margin-top: 24px;
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+  }
+}
+</style>

+ 615 - 0
src/views/sale/settings.vue

@@ -0,0 +1,615 @@
+<template>
+  <div>
+    <PageMain class="vh100" style="position: relative">
+      <p><span></span>分销设置</p>
+
+      <ElForm
+        ref="formRef"
+        :inline="false"
+        :model="form"
+        label-width="150px"
+        class="demo-form-inline"
+        :rules="rules"
+      >
+        <!-- 分销模式选择 -->
+        <ElFormItem
+          label="分销模式"
+          prop="distributionMode"
+          style="margin-bottom: 24px"
+        >
+          <div
+            v-for="item in type"
+            :key="item.name"
+            class="type-box"
+            :class="currentIndex == item.distributionMode ? 'active ' : ''"
+            @click="typeClick(item)"
+          >
+            <img
+              src="@/assets/images/check.png"
+              alt="选中状态"
+              v-if="currentIndex == item.distributionMode"
+            />
+            <h2 style="margin: 0">{{ item.name }}</h2>
+            {{ item.describe }}
+          </div>
+        </ElFormItem>
+        
+        <!-- 佣金比例设置 - 拆分为独立的FormItem以显示各自的校验提示 -->
+        <ElFormItem label="佣金比例" style="margin-bottom: 0;">
+          <!-- 一级佣金比例 -->
+          <ElFormItem
+            prop="commissionRatioLevel1"
+            style="margin-right: 24px; margin-bottom: 16px;"
+          >
+            <div
+              style="
+                width: 256px;
+                display: flex;
+                align-items: center;
+                justify-content: space-between;
+              "
+            >
+              <span style="color: red">*</span> 一级
+              <el-input
+                v-model="form.commissionRatioLevel1"
+                style="width: 206px"
+                type="number"
+                step="0.01"
+                @input="handleCommissionInput('commissionRatioLevel1', $event)"
+              >
+                <template #append>%</template>
+              </el-input>
+            </div>
+          </ElFormItem>
+          
+          <!-- 二级佣金比例 -->
+          <ElFormItem
+            prop="commissionRatioLevel2"
+            style="margin-right: 24px; margin-bottom: 16px;"
+            v-if="currentIndex >= 2"
+          >
+            <div
+              style="
+                width: 256px;
+                display: flex;
+                align-items: center;
+                justify-content: space-between;
+              "
+            >
+              <span style="color: red">*</span> 二级
+              <el-input
+                v-model="form.commissionRatioLevel2"
+                style="width: 206px"
+                type="number"
+                step="0.01"
+                @input="handleCommissionInput('commissionRatioLevel2', $event)"
+              >
+                <template #append>%</template>
+              </el-input>
+            </div>
+          </ElFormItem>
+          
+          <!-- 三级佣金比例 -->
+          <ElFormItem
+            prop="commissionRatioLevel3"
+            style="margin-right: 24px; margin-bottom: 16px;"
+            v-if="currentIndex >= 3"
+          >
+            <div
+              style="
+                width: 256px;
+                display: flex;
+                align-items: center;
+                justify-content: space-between;
+              "
+            >
+              <span style="color: red">*</span> 三级
+              <el-input
+                v-model="form.commissionRatioLevel3"
+                style="width: 206px"
+                type="number"
+                step="0.01"
+                @input="handleCommissionInput('commissionRatioLevel3', $event)"
+              >
+                <template #append>%</template>
+              </el-input>
+            </div>
+          </ElFormItem>
+        </ElFormItem>
+
+        <!-- 分销员招募 -->
+        <ElFormItem
+          label="分销员招募"
+          prop="recruitmentMethod"
+          style="align-items: center"
+        >
+          <el-radio-group v-model="form.recruitmentMethod" class="ml-4">
+            <el-radio label="1" size="large">手动申请</el-radio>
+            <el-radio label="2" size="large">加入组织自动成为分销员</el-radio>
+          </el-radio-group>
+        </ElFormItem>
+        
+        <!-- 不参与分销的机构 -->
+        <ElFormItem
+          label="不参与分销的机构"
+          prop="excludeDeptScope"
+          style="align-items: center"
+        >
+          <el-radio-group v-model="form.excludeDeptScope" class="ml-4">
+            <el-radio label="1" size="large">全部机构</el-radio>
+            <el-radio label="2" size="large">部门机构 </el-radio>
+          </el-radio-group>
+          <div
+            style="
+              color: #0083ff;
+              margin-left: 10px;
+              font-size: 14px;
+              cursor: pointer;
+            "
+            v-if="form.excludeDeptScope == '2'"
+            @click="showDeptDrawer = true"
+          >
+            +选择机构
+          </div>
+        </ElFormItem>
+        
+        <!-- 已选机构列表 -->
+        <el-table
+          :data="selectData"
+          style="width: 611px; margin-left: 130px; margin-top: 16px;"
+          header-cell-class-name="custom-header-cell"
+          v-if="form.excludeDeptScope == '2'"
+        >
+          <el-table-column
+            prop="name"
+            label="机构"
+            width="517"
+            align="center"
+          />
+          <el-table-column label="操作" width="">
+            <template #default="scope">
+              <span
+                @click="removeDept(scope.row.id)"
+                style="
+                  font-size: 14px;
+                  color: #0083ff;
+                  cursor: pointer;
+                  outline: none;
+                "
+                >删除</span
+              >
+            </template>
+          </el-table-column>
+        </el-table>
+      </ElForm>
+
+      <!-- 保存按钮 -->
+      <div class="btn">
+        <el-button type="primary" @click="handleSubmit" v-if="form.systemCode">修改</el-button>
+        <el-button type="primary" @click="handleUpdate" v-else>保存</el-button>
+      </div>
+      
+      <!-- 机构选择抽屉 -->
+      <Drawer
+        :Drawer="showDeptDrawer"
+        :deptlist="deptTreeData"
+        :checkedKeys="defaultCheckedIds"
+        :checkedIds="defaultCheckedIds"
+        @cancel="handleDrawerCancel"
+        @save="handleDrawerSave"
+        @DrawerOpen="handleDrawerOpen"
+        @query="handleDrawerQuery"
+      />
+    </PageMain>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive, onMounted } from "vue";
+import api from "@/api";
+import Drawer from "./components/drawer.vue";
+import { TreeOption, FormRules, FormInstance, ElMessage } from "element-plus";
+
+// 当前选中的分销模式索引
+const currentIndex = ref(3);
+// 表单引用
+const formRef = ref<FormInstance>();
+
+// 分销模式选项
+const type = ref([
+  {
+    name: "一级分销",
+    describe: "仅分销员直接推荐的业务员出单后,分销员可获佣金",
+    distributionMode: 1,
+  },
+  {
+    name: "二级分销",
+    describe:
+      "业务员可从直接推荐的客户(一级)及一级客户推荐的客户(二级)的保费中获得佣金",
+    distributionMode: 2,
+  },
+  {
+    name: "三级分销",
+    describe:
+      "向下延伸三级关系链,每一层的业务员可从这三层关系链的保费中获佣金",
+    distributionMode: 3,
+  },
+]);
+
+// 表单验证规则
+const rules = reactive<FormRules>({
+  distributionMode: [
+    { required: true, message: "请选择分销模式", trigger: "change" },
+  ],
+  // 一级佣金比例验证规则
+  commissionRatioLevel1: [
+    { required: true, message: "请输入一级佣金比例", trigger: "blur" },
+    { type: "number", message: "佣金比例必须为数字", trigger: "blur" },
+    {
+      validator: (rule, value, callback) => {
+        if (value < 0 || value > 100) {
+          callback(new Error("佣金比例需在 0-100 之间"));
+        } else {
+          callback();
+        }
+      },
+      trigger: "blur",
+    },
+  ],
+  // 二级佣金比例验证规则
+  commissionRatioLevel2: [
+    {
+      required: currentIndex.value >= 2,
+      message: "请输入二级佣金比例",
+      trigger: "blur",
+    },
+    { 
+      type: "number", 
+      message: "佣金比例必须为数字", 
+      trigger: "blur",
+      required: false,
+    },
+    {
+      validator: (rule, value, callback) => {
+        if (value !== null && value !== undefined) {
+          if (value < 0 || value > 100) {
+            callback(new Error("佣金比例需在 0-100 之间"));
+          } else {
+            callback();
+          }
+        } else {
+          callback();
+        }
+      },
+      trigger: "blur",
+    },
+  ],
+  // 三级佣金比例验证规则
+  commissionRatioLevel3: [
+    {
+      required: currentIndex.value >= 3,
+      message: "请输入三级佣金比例",
+      trigger: "blur",
+    },
+    { 
+      type: "number", 
+      message: "佣金比例必须为数字", 
+      trigger: "blur",
+      required: false,
+    },
+    {
+      validator: (rule, value, callback) => {
+        if (value !== null && value !== undefined) {
+          if (value < 0 || value > 100) {
+            callback(new Error("佣金比例需在 0-100 之间"));
+          } else {
+            callback();
+          }
+        } else {
+          callback();
+        }
+      },
+      trigger: "blur",
+    },
+  ],
+  recruitmentMethod: [
+    { required: true, message: "请选择分销员招募方式", trigger: "change" },
+  ],
+  excludeDeptScope: [
+    { required: true, message: "请选择是否排除机构", trigger: "change" },
+  ],
+});
+
+// 表单数据结构
+interface FormState {
+  distributionMode: string;
+  commissionRatioLevel1: number | null;
+  commissionRatioLevel2: number | null;
+  commissionRatioLevel3: number | null;
+  recruitmentMethod: string;
+  excludeDeptScope: string;
+  [key: string]: any;
+}
+
+// 表单数据
+const form = reactive<FormState>({
+  distributionMode: "",
+  commissionRatioLevel1: null,
+  commissionRatioLevel2: null,
+  commissionRatioLevel3: null,
+  recruitmentMethod: "",
+  excludeDeptScope: "",
+});
+
+// 机构选择抽屉相关
+const showDeptDrawer = ref(false);
+const defaultCheckedIds = ref<string[]>([]);
+const deptTreeData = ref<TreeOption[]>([]);
+const selectData = ref<any[]>([]);
+
+// 选择分销模式
+const typeClick = (item: any) => {
+  form.distributionMode = item.distributionMode;
+  currentIndex.value = item.distributionMode;
+
+  // 切换分销模式时,重置非当前层级的佣金比例
+  if (currentIndex.value < 2) {
+    form.commissionRatioLevel2 = null;
+    form.commissionRatioLevel3 = null;
+  }
+  if (currentIndex.value < 3) {
+    form.commissionRatioLevel3 = null;
+  }
+
+  // 重置表单校验状态
+  if (formRef.value) {
+    formRef.value.clearValidate(["commissionRatioLevel2", "commissionRatioLevel3"]);
+  }
+};
+
+// 页面加载时获取数据
+onMounted(() => {
+  agreementAuth();
+  getDetail()
+});
+
+// 获取协议授权机构
+const agreementAuth = () => {
+  api.saleApi.agreementdeptTree({ name: "", system: "" }).then((res: any) => {
+    if (res.code == "200") {
+      deptTreeData.value = res.data;
+    }
+  });
+};
+
+// 处理抽屉打开
+const handleDrawerOpen = async () => {
+  try {
+    // 可以在这里加载最新的机构数据
+  } catch (error) {}
+};
+
+// 取消抽屉
+const handleDrawerCancel = () => {
+  showDeptDrawer.value = false;
+};
+
+// 保存选中的机构
+const handleDrawerSave = (selectedIds: string[]) => {
+  showDeptDrawer.value = false;
+  selectData.value = [];
+  
+  // 从机构树中查找选中的节点
+  const findNodesById = (nodes: TreeOption[], ids: string[]): TreeOption[] => {
+    const result: TreeOption[] = [];
+    for (const node of nodes) {
+      if (ids.includes(node.id)) {
+        result.push(node);
+      }
+      if (node.children && node.children.length > 0) {
+        const childMatches = findNodesById(node.children, ids);
+        result.push(...childMatches);
+      }
+    }
+    return result;
+  };
+
+  selectData.value = findNodesById(deptTreeData.value, selectedIds);
+};
+
+// 搜索机构
+const handleDrawerQuery = async (searchName: string) => {
+  
+  try {
+    // const filteredData = deptTreeData.value.filter(
+    //   // (node:TreeOption) => node.name.includes(searchName)
+    //    (node: TreeOption) => 
+    // node.name.toLowerCase().includes(searchName.toLowerCase())
+    // );
+    // deptTreeData.value = filteredData;
+    searchName?deptTreeData.value = filterTree(deptTreeData.value, searchName):agreementAuth()
+    
+  } catch (error) {
+    console.error("筛选机构失败:", error);
+  }
+  
+};
+// 递归筛选树形结构
+const filterTree = (tree: TreeOption[], searchName: string) => {
+  return tree
+    .map(node => {
+      // 复制节点并递归筛选子节点
+      const newNode = { ...node };
+      if (node.children && node.children.length) {
+        newNode.children = filterTree(node.children, searchName);
+      }
+      return newNode;
+    })
+    .filter(node => {
+      // 节点本身包含搜索词,或者有符合条件的子节点
+      const nodeMatches = node.name.toLowerCase().includes(searchName.toLowerCase());
+      const hasMatchingChildren = node.children && node.children.length > 0;
+      return nodeMatches || hasMatchingChildren;
+    });
+};
+
+// 移除已选机构
+const removeDept = async (id: string) => {
+  selectData.value = selectData.value.filter((item) => item.id !== id);
+};
+
+// 处理佣金比例输入
+const handleCommissionInput = (field: string, value: any) => {
+  if (value === "" || value === null || value === undefined) {
+    form[field] = null;
+    return;
+  }
+
+  const numValue = Number(value);
+
+  if (isNaN(numValue)) {
+    form[field] = null;
+    return;
+  }
+
+  // 保留两位小数
+  form[field] = Math.round(numValue * 100) / 100;
+
+  // 限制在0-100之间
+  if (form[field] > 100) {
+    form[field] = 100;
+  }
+  if (form[field] < 0) {
+    form[field] = 0;
+  }
+};
+
+// 提交表单
+const handleSubmit = async () => {
+  if (!formRef.value) return;
+
+  try {
+    await formRef.value.validate();
+
+    const formData = {
+      ...form,
+      commissionRatioLevel1: form.commissionRatioLevel1 || 0,
+      commissionRatioLevel2: form.commissionRatioLevel2 || 0,
+      commissionRatioLevel3: form.commissionRatioLevel3 || 0,
+      excludeDeptIds:form.excludeDeptScope=='1'?[]: selectData.value.map((item) => item.id),
+       systemCode: localStorage.getItem('login_system')
+    };
+    await api.saleApi.saveSetting(formData);
+
+    ElMessage.success('保存成功');
+  } catch (error) {
+  }
+};
+const handleUpdate=async()=>{ 
+  if (!formRef.value) return;
+
+  try {
+    await formRef.value.validate();
+
+    const formData = {
+      ...form,
+      commissionRatioLevel1: form.commissionRatioLevel1 || 0,
+      commissionRatioLevel2: form.commissionRatioLevel2 || 0,
+      commissionRatioLevel3: form.commissionRatioLevel3 || 0,
+      excludeDeptIds:form.excludeDeptScope=='1'?[]: selectData.value.map((item) => item.id),
+       systemCode: localStorage.getItem('login_system')
+    };
+    await api.saleApi.update(formData);
+
+    ElMessage.success('保存成功');
+  } catch (error) {
+  }
+}
+
+//获取详情回显
+const getDetail = async () => { 
+  const res = await api.saleApi.details();
+  // form.value = res.data;
+  Object.assign(form, res.data);
+  currentIndex.value = form.distributionMode
+  selectData.value = form.excludeDept
+};
+</script>
+
+<style scoped lang="scss">
+p {
+  margin: 0;
+  height: 50px;
+  display: flex;
+  align-items: center;
+  border-bottom: 1px solid #eeeeee;
+  margin-top: -1.25rem;
+  margin-bottom: 33px;
+  
+  span {
+    display: inline-block;
+    width: 4px;
+    height: 18px;
+    background: #0083ff;
+    border-radius: 6px;
+    margin-right: 8px;
+  }
+}
+
+.type-box {
+  width: 256px;
+  height: 124px;
+  background: #ffffff;
+  border: 1px solid #e5e5e5;
+  font-size: 14px;
+  line-height: 22px;
+  color: #999999;
+  padding: 16px;
+  margin-right: 24px;
+  border-radius: 2px;
+  cursor: pointer;
+  display: inline-block;
+  vertical-align: top;
+  
+  h2 {
+    font-size: 14px;
+    font-weight: 600;
+    margin-bottom: 4px;
+    color: #333;
+  }
+}
+
+.type-box.active {
+  border: 1px solid #0083ff;
+  position: relative;
+  
+  img {
+    width: 24px;
+    height: 24px;
+    position: absolute;
+    top: 8px;
+    right: 8px;
+  }
+}
+
+.btn {
+  width: 98%;
+  height: 64px;
+  position: absolute;
+  bottom: 0;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-top: 1px solid #eeeeee;
+}
+
+::v-deep .custom-header-cell {
+  background-color: #f7f7f9 !important;
+}
+
+/* 调整表单验证提示的样式 */
+::v-deep .el-form-item__error {
+  padding-top: 4px;
+  font-size: 12px;
+}
+</style>