三七 22 godzin temu
rodzic
commit
2244c7a612

+ 53 - 0
src/api/company/show.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询用户展示字段列表
+export function listShow(query) {
+  return request({
+    url: '/company/show/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询用户展示字段详细
+export function getShow(type) {
+  return request({
+    url: '/company/show/' + type,
+    method: 'get'
+  })
+}
+
+// 新增用户展示字段
+export function addShow(data) {
+  return request({
+    url: '/company/show',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改用户展示字段
+export function updateShow(data) {
+  return request({
+    url: '/company/show',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除用户展示字段
+export function delShow(id) {
+  return request({
+    url: '/company/show/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出用户展示字段
+export function exportShow(query) {
+  return request({
+    url: '/company/show/export',
+    method: 'get',
+    params: query
+  })
+}

+ 96 - 0
src/api/crm/business.js

@@ -0,0 +1,96 @@
+import request from '@/utils/request'
+
+// 查询商机列表
+export function listBusiness(query) {
+  return request({
+    url: '/crm/business/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询商机列表
+export function myListBusiness(query) {
+  return request({
+    url: '/crm/business/myList',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询商机详细
+export function getBusiness(businessId) {
+  return request({
+    url: '/crm/business/' + businessId,
+    method: 'get'
+  })
+}
+
+// 新增商机
+export function addBusiness(data) {
+  return request({
+    url: '/crm/business',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改商机
+export function updateBusiness(data) {
+  return request({
+    url: '/crm/business',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除商机
+export function delBusiness(businessId) {
+  return request({
+    url: '/crm/business/' + businessId,
+    method: 'delete'
+  })
+}
+
+// 导出商机
+export function exportBusiness(query) {
+  return request({
+    url: '/crm/business/export',
+    method: 'get',
+    params: query
+  })
+}
+
+// 导出商机
+export function exportMyBusiness(query) {
+  return request({
+    url: '/crm/business/exportMy',
+    method: 'get',
+    params: query
+  })
+}
+
+//捞取商机
+export function gainBusiness(data) {
+  return request({
+    url: '/crm/business/gain',
+    method: 'post',
+    data: data
+  })
+}
+
+// 下载用户导入模板
+export function importTemplate() {
+  return request({
+    url: '/crm/business/importTemplate',
+    method: 'get'
+  })
+}
+
+// // 删除商机
+// export function setBusinessPool(businessId) {
+//   return request({
+//     url: '/crm/business/' + businessId,
+//     method: 'get'
+//   })
+// }

+ 570 - 0
src/views/crm/components/addBusiness.vue

@@ -0,0 +1,570 @@
+<template>
+    <div>
+        <el-form ref="form" :model="form" :rules="rules" label-width="100px">
+            <el-form-item label="线索来源" prop="source">
+                <el-select v-model="form.source" :disabled="form.source !== null" placeholder="请选择线索来源" clearable size="small">
+                <el-option
+                    v-for="item in clueSourceOptions"
+                    :key="item.dictValue"
+                    :label="item.dictLabel"
+                    :value="item.dictValue"
+                />
+                </el-select>
+            </el-form-item>
+            <el-form-item label="客户经理" prop="manager">
+                <el-input v-model="form.manager" placeholder="请输入客户经理" />
+            </el-form-item>
+            <el-form-item label="公司名称" prop="companyName">
+                <el-input v-model="form.companyName"  placeholder="请输入公司名称(只填公司全称,个人用户就填名字)" />
+            </el-form-item>
+            <el-form-item label="联系电话" v-show="form.customerId !== null" prop="mobile">
+                <el-input  v-model="form.mobile" :disabled="form.customerId !== null" placeholder="请输入电话号码"/>
+            </el-form-item>
+            <el-form-item label="其他联系方式">
+                <el-button type="text" @click="showAddContactDialog">添加其他联系电话</el-button>
+            </el-form-item>
+            <el-table border v-loading="loading" :data="mobileList" v-if="mobileList && mobileList.length > 0" >
+                <el-table-column label="姓名" align="center" prop="name" />
+                <el-table-column label="手机" align="center" prop="mobile" />
+                <el-table-column label="备注" align="center" prop="remark" />
+                <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+                <template slot-scope="scope">
+                    <el-button
+                    size="mini"
+                    type="text"
+                    icon="el-icon-delete"
+                    @click="handleDelete(scope.row)"
+                    v-hasPermi="['crm:customerContacts:remove']"
+                    v-if="scope.row.contactsId == null"
+                    >删除</el-button>
+                </template>
+                </el-table-column>
+            </el-table>
+
+            <el-form-item label="接口人角色" prop="contactRole">
+                <el-select v-model="form.contactRole" placeholder="请选择" clearable size="small">
+                    <el-option
+                        v-for="item in contactRoleOptions"
+                        :key="item.dictValue"
+                        :label="item.dictLabel"
+                        :value="item.dictValue"
+                    />
+                </el-select>
+            </el-form-item>
+            <el-form-item label="业务场景" prop="businessScenario">
+                <el-select v-model="form.businessScenario"  placeholder="请选择线索业务场景" clearable size="small">
+                <el-option
+                    v-for="item in businessScenarioOptions"
+                    :key="item.dictValue"
+                    :label="item.dictLabel"
+                    :value="item.dictValue"
+                />
+                </el-select>
+            </el-form-item>
+            <el-form-item label="意向产品" prop="product">
+                <el-input v-model="form.product" placeholder="请输入方案涉及产品" />
+            </el-form-item>
+            <el-form-item label="采购周期" prop="purchaseCycle">
+                <el-input v-model="form.purchaseCycle" placeholder="请输入采购周期(单位:天)" />
+            </el-form-item>
+            <el-form-item label="跟进状态" prop="businessStatus">
+                <el-radio-group v-model="form.businessStatus">
+                    <el-radio label=0>跟进中</el-radio>
+                    <el-radio label=1>已流失</el-radio>
+                    <el-radio label=2>已赢单</el-radio>
+                    <el-radio label=3>待验证</el-radio>
+                </el-radio-group>
+            </el-form-item>
+            <el-form-item label="项目阶段" prop="projectPhase">
+                <!-- 移除 filteredProjectPhaseOptions,直接使用 projectPhaseOptions -->
+                <el-select v-model="form.projectPhase" placeholder="请选择" clearable size="small">
+                    <el-option
+                        v-for="item in projectPhaseOptions"
+                        :key="item.dictValue"
+                        :label="item.dictLabel"
+                        :value="item.dictValue"
+                    />
+                </el-select>
+            </el-form-item>
+            <el-form-item label="意向等级" prop="level">
+                <el-select v-model="form.level" placeholder="请选择" clearable size="small">
+                    <el-option
+                        v-for="item in levelOptions"
+                        :key="item.dictValue"
+                        :label="item.dictLabel"
+                        :value="item.dictValue"
+                    />
+                </el-select>
+            </el-form-item>
+            <el-form-item label="是否绑定BP">
+                <el-radio-group v-model="form.isBp">
+                    <el-radio label="0">未注册</el-radio>
+                    <el-radio label="1">已注册未绑定</el-radio>
+                    <el-radio label="2">不明确</el-radio>
+                    <el-radio label="3">已绑定</el-radio>
+                </el-radio-group>
+            </el-form-item>
+            <el-form-item label="预计成单时间" prop="preTime">
+                <el-date-picker clearable size="small" style="width: 200px"
+                    v-model="form.preTime"
+                    type="date"
+                    value-format="yyyy-MM-dd"
+                    placeholder="选择预计成单时间">
+                </el-date-picker>
+            </el-form-item>
+            <el-form-item label="预计成交金额" prop="preMoney">
+                <el-input v-model="form.preMoney" placeholder="请输入预计成交金额(元)" />
+            </el-form-item>
+            <el-form-item label="首次跟进内容" prop="content" v-if="form.businessId == null">
+                <el-input v-model="form.content" placeholder="请输入首次跟进内容" />
+            </el-form-item>
+            <el-form-item label="下次跟进时间" prop="nextTime">
+                <el-date-picker clearable size="small" style="width: 200px"
+                    v-model="form.nextTime"
+                    type="date"
+                    value-format="yyyy-MM-dd"
+                    placeholder="选择下次跟进时间">
+                </el-date-picker>
+            </el-form-item>
+        </el-form>
+        <div class="footer">
+            <el-button type="primary" @click="submitForm">确 定</el-button>
+        </div>
+        <el-dialog  :title=title :visible.sync="open" width="500px" append-to-body>
+            <el-form ref="contactForm" :model="contactForm" :rules="contactRules" label-width="120px">
+            <el-form-item label="联系人名称" prop="name">
+                <el-input v-model="contactForm.name" placeholder="请输入联系人名称" />
+            </el-form-item>
+            <el-form-item label="手机" prop="mobile">
+                <el-input v-model="contactForm.mobile" placeholder="请输入手机" />
+            </el-form-item>
+            <el-form-item label="备注" prop="remark">
+                <el-input v-model="contactForm.remark" type="textarea" placeholder="请输入内容" />
+            </el-form-item>
+            </el-form>
+            <div slot="footer" class="dialog-footer">
+                <el-button type="primary" @click="submitContactForm">确 定</el-button>
+                <el-button @click="cancelContact">取 消</el-button>
+            </div>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+    import { addBusiness, updateBusiness } from "@/api/crm/business";
+    import { listCustomerContacts, getCustomerContacts, addCustomerContacts, exportCustomerContacts } from "@/api/crm/customerContacts";
+    export default {
+        name: "business",
+        data() {
+            return {
+                // 弹出层标题
+                title: "",
+                // 是否显示弹出层
+                open: false,
+                // 遮罩层
+                loading: true,
+                mobileList: [],
+                // dialogVisible:false,
+                //联系方式表格
+                contactForm: {
+                    contactsId: null,
+                    customerId: null,
+                    businessId: null,
+                    name: null,
+                    mobile: null,
+                    remark: null
+                },
+                businessScenarioOptions: [],
+                clueSourceOptions: [],
+                contactRoleOptions: [],
+                projectPhaseOptions: [],
+                levelOptions: [],
+                // 添加标志位防止循环触发 - 确保初始化为 false
+                isUpdatingStatus: false,
+                isUpdatingPhase: false,
+                form: {
+                    businessId: null,
+                    customerId: null,
+                    source: null,
+                    manager: null,
+                    companyName: null,
+                    mobile: null,
+                    mobileList: [],
+                    contactRole: null,
+                    businessScenario: null,
+                    product: null,
+                    purchaseCycle: null,
+                    // businessStatus: 0,
+                    remark: null,
+                    projectPhase: null,
+                    level: null,
+                    isBp: '0',
+                    bpAccount: null,
+                    preTime: null,
+                    preMoney: null,
+                    nextTime: null,
+                    createTime: null,
+                    updateTime: null,
+                    createBy: null,
+                    recoveryTime: null,
+                    status: '1'
+                },
+                // 表单校验
+                rules: {
+                    source: [
+                        { required: true, message: "客户来源不能为空", trigger: "change" }
+                    ],
+                    companyName: [
+                        { required: true, message: "客户名称不能为空", trigger: "blur" }
+                    ],
+                    businessScenario: [
+                        { required: true, message: "业务场景不能为空", trigger: "change" }
+                    ],
+                    businessStatus: [
+                        { required: true, message: "请选择跟进状态", trigger: "change" }
+                    ],
+                    projectPhase: [
+                        { required: true, message: "请选择项目阶段", trigger: "change" }
+                    ],
+
+                },
+                //联系方式表单校验
+                contactRules: {
+                    name: [
+                        { required: true, message: "联系人不能为空", trigger: "blur" }
+                    ],
+                    mobile: [
+                        { required: true, message: "手机不能为空", trigger: "blur" },
+                        { min: 8, max: 11, message: '长度在 8 到 11 个字符', trigger: 'blur' }
+                    ]
+                }
+
+            };
+        },
+        created() {
+            this.getDicts("crm_customer_source").then((response) => {
+                this.clueSourceOptions = response.data;
+            });
+            this.getDicts("crm_contact_role").then((response) => {
+                this.contactRoleOptions = response.data;
+            });
+            this.getDicts("crm_project_phase").then((response) => {
+                this.projectPhaseOptions = response.data;
+            });
+            this.getDicts("crm_level").then((response) => {
+                this.levelOptions = response.data;
+            });
+            this.getDicts("business_scenario_type").then((response) => {
+                this.businessScenarioOptions = response.data;
+            });
+        },
+        // 修改监听器:实现正确的自动匹配逻辑
+        watch: {
+            // 监听跟进状态变化,自动匹配项目阶段
+            'form.businessStatus': {
+                handler: function(newVal, oldVal) {
+                    console.log('跟进状态变化:', oldVal, '->', newVal);
+
+                    if (this.isUpdatingStatus) {
+                        console.log('跳过状态更新,防止循环');
+                        return;
+                    }
+
+                    // 设置标志位防止循环触发
+                    this.isUpdatingPhase = true;
+
+                    if (newVal == 2) {
+                        // 已赢单 -> 自动设置为100%转商
+                        const winOption = this.projectPhaseOptions.find(item => {
+                            return item.dictLabel === '100%转商' ||
+                                   item.dictValue === 'A';
+                        });
+                        console.log('找到的赢单选项:', winOption);
+                        if (winOption) {
+                            this.form.projectPhase = winOption.dictValue;
+                            console.log('设置项目阶段为:', winOption.dictValue);
+                        }
+                    } else if (newVal == 1) {
+                        // 已流失 -> 自动设置为丢单
+                        const lostOption = this.projectPhaseOptions.find(item => {
+                            return item.dictLabel === '丢单' ||
+                                   item.dictValue === 'L' ;
+                        });
+                        console.log('找到的丢单选项:', lostOption);
+                        if (lostOption) {
+                            this.form.projectPhase = lostOption.dictValue;
+                            console.log('设置项目阶段为:', lostOption.dictValue);
+                        }
+                    }
+
+                    // 重置标志位
+                    this.$nextTick(() => {
+                        this.isUpdatingPhase = false;
+                        console.log('重置isUpdatingPhase标志位');
+                    });
+                },
+                immediate: false
+            },
+
+            // 监听项目阶段变化,自动匹配跟进状态
+            'form.projectPhase': {
+                handler: function(newVal, oldVal) {
+                    console.log('项目阶段变化:', oldVal, '->', newVal);
+
+                    if (this.isUpdatingPhase) {
+                        console.log('跳过阶段更新,防止循环');
+                        return;
+                    }
+
+                    // 设置标志位防止循环触发
+                    this.isUpdatingStatus = true;
+
+                    // 根据项目阶段自动匹配跟进状态
+                    const selectedPhase = this.projectPhaseOptions.find(item => item.dictValue === newVal);
+                    console.log('选中的阶段选项:', selectedPhase);
+
+                    if (selectedPhase) {
+                        if (selectedPhase.dictLabel == '100%转商' ||
+                            selectedPhase.dictValue == 'A') {
+                            // 100%转商 -> 自动设置为已赢单
+                            this.form.businessStatus = '2';
+                            console.log('设置跟进状态为已赢单');
+                        } else if (selectedPhase.dictLabel == '丢单' ||
+                                  selectedPhase.dictValue == 'L' ) {
+                            // 丢单 -> 自动设置为已流失
+                            this.form.businessStatus = '1';
+                            console.log('设置跟进状态为已流失');
+                        }
+                    }
+
+                    // 重置标志位
+                    this.$nextTick(() => {
+                        this.isUpdatingStatus = false;
+                        console.log('重置isUpdatingStatus标志位');
+                    });
+                },
+                immediate: false
+            }
+        },
+        methods: {
+            addProduct() {
+            },
+            delCustomerContacts(mobile) {
+                const index = this.mobileList.findIndex(phone => phone.id === mobile);
+                if (index !== -1) {
+                    this.mobileList.splice(index, 1); // 删除找到的对象
+                }
+                this.open = false;
+                this.loading = false;
+                console.log("3333333333333", JSON.stringify(this.mobileList));
+            },
+            /** 删除按钮操作 */
+            handleDelete(row) {
+                this.loading = true;
+                const mobile = row.mobile;
+                const index = this.mobileList.findIndex(phone => phone.mobile === mobile);
+                if (index !== -1) {
+                    this.mobileList.splice(index, 1); // 删除找到的对象
+                }
+                this.open = false;
+                this.loading = false;
+
+            },
+
+            /** 提交按钮 */
+            submitContactForm() {
+                this.$refs["contactForm"].validate(valid => {
+                    if (valid) {
+                        //新增
+                        const newMobile = {
+                            mobile: this.contactForm.mobile,
+                            name: this.contactForm.name,
+                            remark: this.contactForm.remark,
+                        };
+                        this.mobileList.push(newMobile);
+                        this.open = false;
+                        this.loading = false;
+                    }
+                });
+            },
+            updateMobileList(mobile, newMobileData) {
+                // 查找要修改的对象
+                const index = this.mobileList.findIndex(phone => phone.mobile === mobile);
+                if (index !== -1) {
+                    // 更新找到的对象
+                    this.$set(this.mobileList, index, { ...this.mobileList[index], ...newMobileData });
+                }
+            },
+            // 取消按钮
+            cancelContact() {
+                this.open = false;
+                this.resetContact();
+            },
+            resetContact() {
+                this.contactForm = {
+                    contactsId: null,
+                    customerId: null,
+                    name: null,
+                    mobile: null,
+                    email: null,
+                    weixin: null,
+                    address: null,
+                    remark: null,
+                    createUserId: null,
+                    createTime: null,
+                    updateTime: null,
+                    isDel: null,
+                    companyId: null
+                };
+            },
+            //添加联系方式
+            showAddContactDialog() {
+                this.open = true; // 显示弹窗
+                this.contactForm.mobile = ''; // 清空表单数据
+            },
+            addContact() {
+                // 添加联系方式逻辑
+                this.form.mobile = this.contactForm.mobile; // 将联系方式添加到form.mobile
+                this.open = false; // 关闭弹窗
+            },
+            updateReset(row){
+                // 重置标志位
+                this.isUpdatingStatus = false;
+                this.isUpdatingPhase = false;
+
+                this.form = row;
+                if(row.source != null){
+                    this.form.source = String(row.source);
+                }
+                if(row.contactRole != null){
+                    this.form.contactRole = String(row.contactRole);
+                }
+                if(row.businessScenario != null){
+                    this.form.businessScenario = String(row.businessScenario);
+                }
+                this.mobileList = this.form.mobileList;
+                if(row.level != null){
+                    this.form.level = String(row.level);
+                }
+                if(row.isBp != null){
+                    this.form.isBp = String(row.isBp);
+                }
+                this.loading = false;
+            },
+            reset(row) {
+                // 重置标志位
+                this.isUpdatingStatus = false;
+                this.isUpdatingPhase = false;
+
+                this.form = row;
+                this.form.source=String(row.source);
+                // 电话
+                this.getContact(row.customerId,this.form.businessId);
+                // // 跟进状态
+                // this.form.businessStatus = 0
+                // 客户名字
+                if(row.customerCompanyName){
+                    this.form.companyName = row.customerCompanyName
+                }
+            },
+            getContact(customerId,businessId){
+                this.loading = true;
+                listCustomerContacts({ customerId: customerId, businessId: businessId }).then(response => {
+                    if (response.code === 200) {
+                        if (response.rows.length > 0)
+                            this.mobileList = response.rows;
+                        this.loading = false;
+                    } else {
+                        this.mobileList = []
+                    }
+                })
+            },
+            businessReset() {
+                // 重置标志位
+                this.isUpdatingStatus = false;
+                this.isUpdatingPhase = false;
+
+                this.form = {
+                    businessId: null,
+                    customerId: null,
+                    source: null,
+                    manager: null,
+                    companyName: null,
+                    mobile: null,
+                    contactRole: null,
+                    businessScenario: null,
+                    product: null,
+                    purchaseCycle: null,
+                    remark: null,
+                    projectPhase: null,
+                    level: null,
+                    isBp: null,
+                    bpAccount: null,
+                    preTime: null,
+                    preMoney: null,
+                    nextTime: null,
+                    createTime: null,
+                    updateTime: null,
+                    createBy: null,
+                    recoveryTime: null,
+                    status: 0,
+                    content:null
+                };
+                this.resetContact();
+            },
+            /** 提交按钮 */
+            submitForm() {
+                this.$refs["form"].validate(valid => {
+                    if (valid) {
+                        this.form.mobileList = this.mobileList;
+                        if (this.form.businessId != null) {
+                            updateBusiness(this.form).then(response => {
+                                if (response.code === 200) {
+                                    this.msgSuccess("修改成功");
+                                    this.businessReset();
+                                    this.$emit('closeBusiness');
+                                }
+                            });
+                        } else {
+                            addBusiness(this.form).then(response => {
+                                if (response.code === 200) {
+                                    this.msgSuccess("提交成功");
+                                    this.businessReset();
+                                    this.$emit('closeBusiness');
+                                }
+                            });
+                        }
+
+                    }
+                });
+            },
+        }
+    };
+</script>
+
+<style lang="scss" scoped>
+.contents {
+    height: 100%;
+    background-color: #fff;
+    padding: 20px;
+
+}
+.footer {
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+}
+</style>
+
+<style scoped>
+.avatar-uploader .el-upload {
+    border: 1px dashed #d9d9d9;
+    border-radius: 6px;
+    cursor: pointer;
+    position: relative;
+    overflow: hidden;
+}
+.avatar-uploader .el-upload:hover {
+    border-color: #409EFF;
+}
+</style>

+ 96 - 0
src/views/crm/components/setColumn.vue

@@ -0,0 +1,96 @@
+<template>
+    <div>
+        <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+            <el-form-item label="全部字段" prop="columns">
+                <p></p>
+                <el-checkbox-group v-model="form.columns">
+                    <!-- 循环遍历选项 -->
+                    <el-checkbox
+                        v-for="(item, index) in allColumns"
+                        :key="index"
+                        :label="item.prop"
+                        :disabled="item.prop == 'customerId' || item.prop == 'businessId'"
+                    >
+                        {{ item.label }}
+                    </el-checkbox>
+                </el-checkbox-group>
+            </el-form-item>
+            <div   class="footer">
+                <el-button type="primary" @click="submitForm">确定</el-button>
+                <el-button  @click="cancel">取消</el-button>
+            </div>
+        </el-form>
+    </div>
+</template>
+
+<script>
+    import {updateShow} from "@/api/company/show";
+
+    export default {
+        name: "business",
+        data() {
+            return {
+                form:{
+                    type:'',
+                    columns:[],
+                },
+                allColumns:[],
+                // 表单校验
+                rules: {
+                    type: [
+                        { required: true, message: "type不能为空", trigger: "blur" }
+                    ],
+                    columns: [
+                        { required: true, message: '请至少选择一个选项', trigger: 'change' },
+                        ],
+
+                },
+
+
+            }
+        },
+
+        created() {
+
+        },
+        methods: {
+            cancel(){
+                this.$emit('close');
+            },
+            reset(allColumns,selectedKeys,type,){
+                this.allColumns = allColumns;
+                this.form.columns = selectedKeys;
+                this.form.type = type;
+                console.log("==========",JSON.stringify(this.allColumns))
+                console.log("==========2",JSON.stringify(this.form.columns))
+            },
+            /** 提交按钮 */
+            submitForm() {
+                this.$refs["form"].validate(valid => {
+                if (valid) {
+                    console.log("==========2",JSON.stringify(this.form))
+                    updateShow(this.form).then(response => {
+                        if (response.code === 200) {
+                            this.msgSuccess("提交成功");
+                            this.$emit('close');
+                        }
+                    });
+                }
+                });
+            },
+        }
+    };
+</script>
+<style lang="scss" scoped>
+.contents{
+    height: 100%;
+    background-color: #fff;
+    padding: 20px;
+
+}
+.footer{
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+}
+</style>

+ 24 - 2
src/views/crm/customer/my.vue

@@ -219,6 +219,7 @@
             @click="handleRecover(scope.row)"
             v-hasPermi="['crm:customer:recover']"
           >回收公海</el-button>
+          <el-button size="mini" type="text" @click="handleBusiness(scope.row)" v-hasPermi="['crm:business:add']">新建商机</el-button>
           <!-- <el-button
 
             size="mini"
@@ -269,6 +270,10 @@
     <el-dialog :title="addVisitStatus.title" :visible.sync="addVisitStatus.open" width="600px" append-to-body>
         <add-visit-status ref="visitStatus" @close="closeVisitStatus()"></add-visit-status>
     </el-dialog>
+
+      <el-dialog :title="business.title" :visible.sync="business.open" width="600px" append-to-body>
+          <add-business @closeBusiness="closeBusiness"   ref="addBusiness" />
+      </el-dialog>
   </div>
 </template>
 
@@ -285,9 +290,10 @@ import addTag from '../components/addTag.vue';
 import addRemark from '../components/addRemark.vue';
 import addCustomerType from '../components/addCustomerType.vue';
 import addVisitStatus from '../components/addVisitStatus.vue';
+import addBusiness from '../components/addBusiness.vue';
 export default {
   name: "Customer",
-  components: {addVisitStatus,addCustomerType,addRemark,addTag,assignUser,addOrEditCustomer,editSource, addBatchSms,customerDetails,addVisit,addVisit },
+  components: {addVisitStatus,addCustomerType,addRemark,addTag,assignUser,addOrEditCustomer,editSource, addBatchSms,customerDetails,addVisit,addBusiness },
   data() {
     return {
       addVisitStatus:{
@@ -423,7 +429,10 @@ export default {
           { required: true, message: "客户来源不能为空", trigger: "blur" }
         ],
       },
-      loading:null,
+        business:{
+            open:false,
+            title:"新建商机"
+        },
     };
   },
   created() {
@@ -452,6 +461,19 @@ export default {
     this.getList();
   },
   methods: {
+
+      closeBusiness(){
+          this.business.open=false;
+          this.getList();
+      },
+
+      handleBusiness(row){
+          this.business.open=true;
+          setTimeout(() => {
+              this.$refs.addBusiness.reset(row);
+          }, 200);
+      },
+
     closeVisitStatus(){
         this.addVisitStatus.open=false;
         this.getList();

+ 882 - 0
src/views/crm/customerBusiness/index.vue

@@ -0,0 +1,882 @@
+<template>
+  <div class="app-container"  customer-page-box>
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+      <!-- <el-form-item label="客户名称" prop="companyName">
+        <el-input
+          v-model="queryParams.companyName"
+          placeholder="请输入客户名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item> -->
+      <el-form-item label="线索来源" prop="source">
+        <el-select v-model="queryParams.source" placeholder="请选择线索来源" clearable size="small">
+          <el-option
+            v-for="item in clueSourceOptions"
+              :key="item.dictValue"
+              :label="item.dictLabel"
+              :value="item.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <!-- <el-form-item label="客户经理" prop="manager">
+        <el-input
+          v-model="queryParams.manager"
+          placeholder="请输入客户经理"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item> -->
+      <el-form-item label="企业名称" prop="companyName">
+        <el-input
+          v-model="queryParams.companyName"
+          placeholder="请输入企业名称"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="相关客户" prop="mobile">
+        <el-input
+          v-model="queryParams.mobile"
+          placeholder="请输入相关客户电话号码"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <!-- <el-form-item label="接口人角色" prop="contactRole">
+        <el-select v-model="queryParams.contactRole" placeholder="请选择" clearable size="small">
+          <el-option
+            v-for="item in contactRoleOptions"
+              :key="item.dictValue"
+              :label="item.dictLabel"
+              :value="item.dictValue"
+            />
+         </el-select>
+      </el-form-item> -->
+      <el-form-item label="业务场景" prop="businessScenario">
+        <el-input
+          v-model="queryParams.businessScenario"
+          placeholder="请输入业务场景"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item>
+      <!-- <el-form-item label="方案涉及的产品" prop="product">
+        <el-input
+          v-model="queryParams.product"
+          placeholder="请输入方案涉及的产品"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item> -->
+      <!-- <el-form-item label="采购周期(单位:天)" prop="purchaseCycle">
+        <el-input
+          v-model="queryParams.purchaseCycle"
+          placeholder="请输入采购周期(单位:天)"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item> -->
+      <el-form-item label="跟进状态" prop="businessStatus">
+        <el-select v-model="queryParams.businessStatus" placeholder="请选择跟进状态" clearable size="small">
+          <el-option
+            v-for="item in businessStatusOptions"
+              :key="item.dictValue"
+              :label="item.dictLabel"
+              :value="item.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="项目阶段" prop="projectPhase">
+        <el-select v-model="queryParams.projectPhase" placeholder="请选择" clearable size="small">
+          <el-option
+              v-for="item in projectPhaseOptions"
+              :key="item.dictValue"
+              :label="item.dictLabel"
+              :value="item.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="意向等级" prop="level">
+        <el-select v-model="queryParams.level" placeholder="请选择" clearable size="small">
+          <el-option
+              v-for="item in levelOptions"
+              :key="item.dictValue"
+              :label="item.dictLabel"
+              :value="item.dictValue"
+          />
+        </el-select>
+      </el-form-item>
+      <!-- <el-form-item label="是否绑定BP账号" prop="isBp">
+        <el-input
+          v-model="queryParams.isBp"
+          placeholder="请输入是否绑定BP账号"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item> -->
+      <!-- <el-form-item label="BP账户" prop="bpAccount">
+        <el-input
+          v-model="queryParams.bpAccount"
+          placeholder="请输入BP账户"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item> -->
+      <!-- <el-form-item label="预计成单时间" prop="preTime">
+        <el-date-picker clearable size="small" style="width: 200px"
+          v-model="queryParams.preTime"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择预计成单时间">
+        </el-date-picker>
+      </el-form-item> -->
+      <!-- <el-form-item label="预计付费(元)" prop="preMoney">
+        <el-input
+          v-model="queryParams.preMoney"
+          placeholder="请输入预计付费(元)"
+          clearable
+          size="small"
+          @keyup.enter.native="handleQuery"
+        />
+      </el-form-item> -->
+      <!-- <el-form-item label="挖掘时间" prop="createTime">
+        <el-date-picker clearable size="small" style="width: 200px"
+          v-model="queryParams.createTime"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择挖掘时间">
+        </el-date-picker>
+      </el-form-item> -->
+      <el-form-item label="挖掘时间" prop="createTimeRange">
+        <el-date-picker
+          style="width:205.4px"
+          clearable size="small"
+          v-model="createTimeRange"
+          type="daterange"
+          value-format="yyyy-MM-dd"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期">
+        </el-date-picker>
+      </el-form-item>
+      <!-- <el-form-item label="下次跟进时间" prop="nextTime">
+        <el-date-picker clearable size="small" style="width: 200px"
+          v-model="queryParams.nextTime"
+          type="date"
+          value-format="yyyy-MM-dd"
+          placeholder="选择下次跟进时间">
+        </el-date-picker>
+      </el-form-item> -->
+      <el-form-item label="下次跟进" prop="nextTimeRange">
+        <el-date-picker
+          style="width:205.4px"
+          clearable size="small"
+          v-model="nextTimeRange"
+          type="daterange"
+          value-format="yyyy-MM-dd"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期">
+        </el-date-picker>
+      </el-form-item>
+
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <!-- <el-col :span="1.5">
+        <el-button
+          type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['crm:business:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['crm:business:edit']"
+        >修改</el-button>
+      </el-col> -->
+      <!-- <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['crm:business:remove']"
+        >删除</el-button>
+      </el-col> -->
+      <!-- <el-col :span="1.5">
+        <el-button
+          type="danger"
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+        >删除</el-button>
+      </el-col> -->
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          icon="el-icon-download"
+          size="mini"
+          @click="handleExport"
+          v-hasPermi="['crm:business:export']"
+        >导出</el-button>
+      </el-col>
+      <el-col :span="1.5">
+          <el-button size="mini" icon="el-icon-s-operation" @click="handleSetColumn()" >设置列表</el-button>
+      </el-col>
+
+	  <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <div>
+      <el-table  border v-loading="loading" :data="businessList"
+        @selection-change="handleSelectionChange"
+        @sort-change="handleSortChange"
+        >
+        <el-table-column type="selection" width="55" align="center" />
+        <!-- 动态渲染列 -->
+        <el-table-column
+          v-for="col in visibleColumns"
+          :key="col.prop"
+          :label="col.label"
+          :width="col.width"
+          align="center"
+          :prop="col.prop"
+          :sortable="col.prop === 'nextTime' ? 'custom' : false"
+          >
+
+          <template slot-scope="scope">
+
+            <!-- 如果是客户来源字段 -->
+            <template v-if="col.prop === 'source'">
+              <el-tag v-for="item in clueSourceOptions" :key="item.dictValue" v-show="scope.row.source == item.dictValue">
+                {{ item.dictLabel }}
+              </el-tag>
+            </template>
+
+
+
+            <!-- <template v-else-if="col.prop === 'mobile'">
+              <template>
+                {{scope.row.mobile}}
+                <el-button type="text"    size="mini" @click="callNumber(scope.row.customerId,null)" v-show="scope.row.mobile!=null">拨号</el-button>
+                <el-button v-hasPermi="['crm:customer:addVisit']"  type="text" size="mini" @click="handleAddVisit(scope.row)">写跟进</el-button>
+              </template>
+            </template>
+
+            <template v-else-if="col.prop === 'mobileList'">
+              <div>
+                <el-tag v-for="(phone, index) in scope.row.mobileList" :key="index" v-if="scope.row.mobileList">
+                  {{ phone.mobile }}
+                </el-tag>
+
+              </div>
+            </template>   -->
+
+             <!-- 如果是相关客户电话号码字段 -->
+             <template v-else-if="col.prop === 'mobile'">
+                <template>
+                  {{scope.row.mobile}}
+                  <!-- <el-button type="text"    size="mini" @click="callNumber(scope.row.customerId,null)" v-show="scope.row.mobile!=null">拨号</el-button>
+                  <el-button v-hasPermi="['crm:customer:addVisit']"  type="text" size="mini" @click="handleAddVisit(scope.row)" v-show="scope.row.mobile!=null">写跟进</el-button> -->
+                </template>
+              </template>
+
+              <!-- 如果是电话号码字段 -->
+              <template v-else-if="col.prop === 'mobileList'">
+                <div>
+                    <template>
+                        <div v-for="(phone, index) in scope.row.mobileList" :key="index" v-if="scope.row.mobileList">
+                            <el-tag >
+                                {{ phone.mobile }}
+                            </el-tag>
+                            <!-- <el-button type="text"    size="mini" @click="callNumber(null,phone.contactsId)" v-show="phone.mobile!=null">拨号</el-button> -->
+                        </div>
+                        <!-- <el-button v-hasPermi="['crm:customer:addVisit']"  type="text" size="mini" @click="handleAddVisit(scope.row)" v-show="scope.row.mobile==null">写跟进</el-button> -->
+                    </template>
+                </div>
+              </template>
+
+             <!-- 如果是接口人角色字段 -->
+             <template v-else-if="col.prop === 'contactRole'">
+              <span prop="contactRole" v-for="(item, index) in contactRoleOptions"    v-if="scope.row.contactRole==item.dictValue">{{item.dictLabel}}</span>
+            </template>
+
+            <!-- 如果是业务场景字段 -->
+            <template v-else-if="col.prop === 'businessScenario'">
+              <el-tag v-for="item in businessScenarioOptions" :key="item.dictValue" v-show="scope.row.businessScenario == item.dictValue">
+                {{ item.dictLabel }}
+              </el-tag>
+            </template>
+
+            <!-- 如果是采购周期字段 -->
+            <template v-else-if="col.prop === 'purchaseCycle'">
+              <span>{{scope.row.purchaseCycle||'--'}}天</span>
+            </template>
+
+            <!-- 如果是跟进状态字段 -->
+            <template v-else-if="col.prop === 'businessStatus'">
+              <span prop="businessStatus" v-for="(item, index) in businessStatusOptions"    v-if="scope.row.businessStatus==item.dictValue">{{item.dictLabel}}</span>
+            </template>
+
+            <!-- 如果是项目阶段字段 -->
+            <template v-else-if="col.prop === 'projectPhase'">
+              <span prop="projectPhase" v-for="(item, index) in projectPhaseOptions" v-if="scope.row.projectPhase==item.dictValue">{{item.dictLabel}}</span>
+            </template>
+
+            <!-- 如果是意向等级字段 -->
+            <template v-else-if="col.prop === 'level'">
+              <span prop="level" v-for="(item, index) in levelOptions" v-if="scope.row.level==item.dictValue">{{item.dictLabel}}</span>
+            </template>
+
+            <!-- 如果是是否绑定BP账号字段 -->
+            <template v-else-if="col.prop === 'isBp'">
+              <span prop="isBp" v-for="(item, index) in isBpOptions" v-if="scope.row.isBp==item.dictValue">{{item.dictLabel}}</span>
+            </template>
+
+            <!-- 如果是预计成单时间字段 -->
+            <template v-else-if="col.prop === 'preTime'">
+              <span>{{ parseTime(scope.row.preTime, '{y}-{m}-{d}') }}</span>
+            </template>
+
+            <!-- 如果是预计付费字段 -->
+            <template v-else-if="col.prop === 'preMoney'">
+              <span>{{scope.row.preMoney||'--'}}元</span>
+            </template>
+
+            <!-- 如果是下次跟进时间字段 -->
+            <template v-else-if="col.prop === 'nextTime'">
+              <span>{{ parseTime(scope.row.nextTime, '{y}-{m}-{d}') }}</span>
+            </template>
+
+            <!-- 如果是下次跟进时间 -->
+            <template v-else-if="col.prop === 'nextTime'">
+              <span style="color: red;">
+                {{ scope.row.nextTime }}
+              </span>
+            </template>
+            <!-- 其他普通字段 -->
+            <span v-else>{{ scope.row[col.prop] }}</span>
+          </template>
+
+
+        </el-table-column>
+
+        <!-- 操作列,始终显示 -->
+        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+          <template slot-scope="scope">
+            <!-- <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['crm:business:edit']">修改</el-button>
+            <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['crm:business:remove']">删除</el-button> -->
+            <div v-if="scope.row.customerId !== null">
+              <el-button size="mini" type="text" icon="el-icon-s-custom" @click="handleShow(scope.row)" v-hasPermi="['crm:customer:query']">查看相关客户</el-button>
+            </div>
+            <div v-if="scope.row.customerId == null">
+                <el-button size="mini" type="text" icon="el-icon-s-custom" @click="handlevisitShow(scope.row)" v-hasPermi="['crm:customer:query']">查看商机跟进</el-button>
+              </div>
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <pagination
+        v-show="total>0"
+        :total="total"
+        :page.sync="queryParams.pageNum"
+        :limit.sync="queryParams.pageSize"
+        @pagination="getList"
+      />
+
+      <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
+        <add-business @closeBusiness="closeBusiness"   ref="addBusiness" />
+      </el-dialog>
+      <!-- 显示 allColumns 数据的对话框 -->
+      <el-dialog :visible.sync="columns.open" :title="columns.title">
+        <set-column ref="setColumn" @close="closeSetColumn"/>
+      </el-dialog>
+      <el-drawer size="75%" :title="show.title" :visible.sync="show.open">
+        <customer-details  ref="customerDetails" />
+      </el-drawer>
+      <el-dialog :title="visit.title" :visible.sync="visit.open" width="600px" append-to-body>
+        <add-visit @closeVisit="closeVisit"   ref="addVisit" />
+      </el-dialog>
+      <el-dialog :title="visitView.title" :visible.sync="visitView.open" width="1000px" append-to-body>
+          <customer-visit-list ref="visit"></customer-visit-list>
+      </el-dialog>
+    </div>
+  </div>
+</template>
+
+<script>
+import { listBusiness, getBusiness, delBusiness, updateBusiness, exportBusiness,setBusinessPool } from "@/api/crm/business";
+import addBusiness from '../components/addBusiness.vue';
+import setColumn from '../components/setColumn.vue';
+import addVisit from '../components/addVisit.vue';
+import {getShow} from "@/api/company/show";
+import customerDetails from '../components/customerDetails.vue';
+import customerVisitList from '../components/customerVisitList.vue';
+export default {
+  name: "Business",
+  components: {setColumn,addBusiness,customerDetails,addVisit,customerVisitList},
+  data() {
+    return {
+      visitView:{
+            open:false,
+            title:"跟进记录"
+        },
+      visit:{
+          open:false,
+          title:"写跟进"
+      },
+      show:{
+        title:"客户详情",
+        open:false,
+      },
+      columns:{
+        title:"设置列表",
+        open:false,
+      },
+      columnType:'business',
+      visibleColumns: [],
+       // 可选字段
+       allColumns: [
+       { prop: "businessId", label: "商机ID" },
+        // { prop: "companyName", label: "客户名称" },
+        { prop: "customerId", label: "客户ID" },
+        { prop: "source", label: "线索来源" },
+        { prop: "manager", label: "客户经理" },
+        { prop: "companyName", label: "企业名称" },
+        { prop: "mobile", label: "相关客户电话",width:120  },
+        { prop: "mobileList", label: "电话号码",width:120},
+        { prop: "contactRole", label: "接口人角色" },
+        { prop: "businessScenario", label: "业务场景" },
+        { prop: "product", label: "方案涉及产品" },
+        { prop: "purchaseCycle", label: "采购周期" },
+        { prop: "businessStatus", label: "跟进状态" },
+        { prop: "content", label: "最新跟进内容" },
+        { prop: "nextTime", label: "下次跟进时间",width: 180, sortable: 'custom' },// 启用自定义排序
+        { prop: "projectPhase", label: "项目阶段" },
+        { prop: "level", label: "意向等级" },
+        { prop: "isBp", label: "是否绑定BP账号" },
+        { prop: "bpAccount", label: "BP账户" },
+        { prop: "preTime", label: "预计成单时间", width: 105 },
+        { prop: "preMoney", label: "预计付费" },
+        { prop: "createTime", label: "挖掘时间", width: 105 },
+      ],
+      // 选中的字段(默认显示所有字段)
+      selectedKeys: [
+        "businessId",
+        "customerId",
+        "source",
+        "manager",
+        "companyName",
+        "mobile",
+        "mobileList",
+        "contactRole",
+        "businessScenario",
+        "product",
+        "purchaseCycle",
+        "businessStatus",
+        "content",
+        "nextTime",
+        "projectPhase",
+        "level",
+        "isBp",
+        "bpAccount",
+        "preTime",
+        "preMoney",
+        "createTime"
+      ],
+      createTimeRange:[],
+      nextTimeRange:[],
+      recoveryRange:[],
+      statusOptions:[
+        {
+          dictValue:1,
+          dictLabel:"已分配"
+        },
+        {
+          dictValue:2,
+          dictLabel:"进行中"
+        },
+        {
+          dictValue:3,
+          dictLabel:"回收"
+        }
+      ],
+      clueSourceOptions:[],
+      contactRoleOptions:[],
+      projectPhaseOptions:[],
+      businessScenarioOptions:[],
+      levelOptions:[],
+      businessStatusOptions:[],
+      isBpOptions:[
+        {
+          dictValue:0,
+          dictLabel:"未注册"
+        },
+        {
+          dictValue:1,
+          dictLabel:"已注册未绑定"
+        },
+        {
+          dictValue:2,
+          dictLabel:"不明确"
+        },
+        {
+          dictValue:3,
+          dictLabel:"已绑定"
+        }
+      ],
+
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 商机表格数据
+      businessList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        // customerId: null,
+        source: null,
+        manager: null,
+        companyName: null,
+        mobile: null,
+        contactRole: null,
+        businessScenario: null,
+        product: null,
+        purchaseCycle: null,
+        businessStatus: null,
+        projectPhase: null,
+        level: null,
+        isBp: null,
+        bpAccount: null,
+        preTime: null,
+        preMoney: null,
+        nextTime: null,
+        recoveryTime: null,
+        status: null,
+        companyName:null,
+        orderBy:null,//nextTime排序规则
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        customerId: [
+          { required: true, message: "客户id不能为空", trigger: "blur" }
+        ],
+      },
+
+    };
+  },
+  created() {
+    this.getDicts("business_scenario_type").then((response) => {
+      this.businessScenarioOptions = response.data;
+    });
+    this.getDicts("crm_customer_source").then((response) => {
+      this.clueSourceOptions = response.data;
+    });
+    this.getDicts("crm_contact_role").then((response) => {
+      this.contactRoleOptions = response.data;
+    });
+    this.getDicts("crm_project_phase").then((response) => {
+      this.projectPhaseOptions = response.data;
+    });
+    this.getDicts("crm_level").then((response) => {
+      this.levelOptions = response.data;
+    });
+    this.getDicts("crm_business_status").then((response) => {
+      this.businessStatusOptions = response.data;
+    });
+    this.getList();
+  },
+  methods: {
+    getData(customerId){
+        this.queryParams.customerId=customerId;
+        this.queryParams.pageNum=1;
+        this.getList();
+    },
+    handlevisitShow(row){
+        this.visitView.open=true;
+        setTimeout(() => {
+            this.$refs.visit. getBusinessData(row.businessId);
+        }, 200);
+
+      },
+    async handleSortChange({ prop, order }) {
+      try {
+        this.loading = true; // 开始加载
+        const sortOrder = order === 'ascending' ? 'asc' : 'desc'; // 转换排序顺序
+        // const params = {
+        //   sortOrder: sortOrder // 排序顺序
+        // };
+        this.queryParams.orderBy = sortOrder;
+
+        // 调用后端接口获取排序后的数据
+        const response = await this.getList();
+      } catch (error) {
+        console.error('排序失败:', error);
+      } finally {
+        this.loading = false; // 结束加载
+      }
+    },
+    handleAddVisit(row){
+        this.visit.open=true;
+        setTimeout(() => {
+            this.$refs.addVisit.reset(row.customerId);
+        }, 200);
+    },
+    closeVisit(){
+        this.visit.open=false;
+        this.getList();
+    },
+    handleShow(row){
+      this.show.open=true;
+      var that=this;
+      const tab = "visit";
+      setTimeout(() => {
+        that.$refs.customerDetails.getDetails(row.customerId);
+        that.$refs.customerDetails.handleClick(tab);
+
+      }, 200);
+    },
+    handleSetColumn(){
+      this.columns.open=true;
+      var that=this;
+      setTimeout(() => {
+            that.$refs.setColumn.reset(that.allColumns,that.selectedKeys,that.columnType);
+      }, 200);
+    },
+    closeSetColumn(){
+      this.columns.open=false;
+      this.getList();
+    },
+    handleBusiness(row){
+        this.business.open=true;
+        setTimeout(() => {
+            this.$refs.addBusiness.reset(row);
+        }, 200);
+    },
+    closeBusiness(){
+        this.business.open=false;
+        this.getList();
+    },
+    //查询显示字段
+    async getColumn(){
+      const response = await getShow(this.columnType);
+      if (response.code === 200 && response.data) {
+        this.selectedKeys = response.data.columns.split(",");
+        this.$set(this, "visibleColumns", this.allColumns.filter(col => this.selectedKeys.includes(col.prop)));
+
+      } else{
+        this.$set(this, "visibleColumns", this.allColumns);
+      }
+    },
+    /** 查询客户列表 */
+    async getList() {
+      this.loading = true;
+      await this.getColumn(); // 确保 visibleColumns 先获取到
+      if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+        this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+      }
+      else{
+        this.queryParams.createTimeRange=null;
+      }
+      if(this.nextTimeRange!=null&&this.nextTimeRange.length==2){
+        this.queryParams.nextTimeRange=this.nextTimeRange[0]+"--"+this.nextTimeRange[1]
+      }
+      else{
+        this.queryParams.nextTimeRange=null;
+      }
+      if(this.recoveryRange!=null&&this.recoveryRange.length==2){
+        this.queryParams.recoveryRange=this.recoveryRange[0]+"--"+this.recoveryRange[1]
+      }
+      else{
+        this.queryParams.recoveryRange=null;
+      }
+      const response = await listBusiness(this.addDateRange(this.queryParams, this.dateRange));
+      this.businessList = response.rows
+      this.total = response.total;
+      this.loading = false;
+
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        businessId: null,
+        customerId: null,
+        source: null,
+        manager: null,
+        companyName: null,
+        mobile: null,
+        contactRole: null,
+        businessScenario: null,
+        product: null,
+        purchaseCycle: null,
+        businessStatus: 0,
+        remark: null,
+        projectPhase: null,
+        level: null,
+        isBp: null,
+        bpAccount: null,
+        preTime: null,
+        preMoney: null,
+        nextTime: null,
+        createTime: null,
+        updateTime: null,
+        createBy: null,
+        recoveryTime: null,
+        status: 0,
+        // createTimeRange:null,
+        // nextTimeRange:null,
+        // recoveryRange:null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.businessId)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加商机";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.reset();
+      const businessId = row.businessId || this.ids
+      getBusiness(businessId).then(response => {
+        this.form = response.data;
+        this.form.source = String(response.data.source);
+        this.form.contactRole = String(response.data.contactRole);
+        this.form.level = String(response.data.level);
+        this.form.businessStatus = String(response.data.businessStatus);
+        console.log("111111111111111111111",JSON.stringify(this.form))
+        this.open = true;
+        this.title = "修改商机";
+        setTimeout(() => {
+            this.$refs.addBusiness.updateReset(row);
+        }, 200);
+      });
+    },
+    // /** 提交按钮 */
+    // submitForm() {
+    //   this.$refs["form"].validate(valid => {
+    //     if (valid) {
+    //       if (this.form.businessId != null) {
+    //         updateBusiness(this.form).then(response => {
+    //           if (response.code === 200) {
+    //             this.msgSuccess("修改成功");
+    //             this.open = false;
+    //             this.getList();
+    //           }
+    //         });
+    //       } else {
+    //         addBusiness(this.form).then(response => {
+    //           if (response.code === 200) {
+    //             this.msgSuccess("新增成功");
+    //             this.open = false;
+    //             this.getList();
+    //           }
+    //         });
+    //       }
+    //     }
+    //   });
+    // },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const businessIds = row.businessId || this.ids;
+      this.$confirm('是否确认删除商机编号为"' + businessIds + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delBusiness(businessIds);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    // /** 退回公海按钮操作 */
+    // handleDelete(row) {
+    //   const businessIds = row.businessId || this.ids;
+    //   this.$confirm('是否确认删除商机编号为"' + businessIds + '"的数据项?', "警告", {
+    //       confirmButtonText: "确定",
+    //       cancelButtonText: "取消",
+    //       type: "warning"
+    //     }).then(function() {
+    //       return setBusinessPool(businessIds);
+    //     }).then(() => {
+    //       this.getList();
+    //       this.msgSuccess("删除成功");
+    //     }).catch(function() {});
+    // },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有商机数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportBusiness(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    }
+  }
+};
+</script>

+ 930 - 0
src/views/crm/customerBusiness/my.vue

@@ -0,0 +1,930 @@
+<template>
+    <div class="app-container"  customer-page-box>
+      <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
+        <!-- <el-form-item label="客户名称" prop="companyName">
+          <el-input
+            v-model="queryParams.companyName"
+            placeholder="请输入客户名称"
+            clearable
+            size="small"
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item> -->
+        <el-form-item label="线索来源" prop="source">
+          <el-select v-model="queryParams.source" placeholder="请选择线索来源" clearable size="small">
+            <el-option
+              v-for="item in clueSourceOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+            />
+          </el-select>
+        </el-form-item>
+        <!-- <el-form-item label="客户经理" prop="manager">
+          <el-input
+            v-model="queryParams.manager"
+            placeholder="请输入客户经理"
+            clearable
+            size="small"
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item> -->
+        <el-form-item label="企业名称" prop="companyName">
+          <el-input
+            v-model="queryParams.companyName"
+            placeholder="请输入企业名称"
+            clearable
+            size="small"
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <el-form-item label="相关客户" prop="mobile">
+          <el-input
+            v-model="queryParams.mobile"
+            placeholder="请输入相关客户电话号码"
+            clearable
+            size="small"
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <!-- <el-form-item label="接口人角色" prop="contactRole">
+          <el-select v-model="queryParams.contactRole" placeholder="请选择" clearable size="small">
+            <el-option
+              v-for="item in contactRoleOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+              />
+           </el-select>
+        </el-form-item> -->
+        <el-form-item label="业务场景" prop="businessScenario">
+          <el-input
+            v-model="queryParams.businessScenario"
+            placeholder="请输入业务场景"
+            clearable
+            size="small"
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item>
+        <!-- <el-form-item label="方案涉及的产品" prop="product">
+          <el-input
+            v-model="queryParams.product"
+            placeholder="请输入方案涉及的产品"
+            clearable
+            size="small"
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item> -->
+        <!-- <el-form-item label="采购周期(单位:天)" prop="purchaseCycle">
+          <el-input
+            v-model="queryParams.purchaseCycle"
+            placeholder="请输入采购周期(单位:天)"
+            clearable
+            size="small"
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item> -->
+        <el-form-item label="跟进状态" prop="businessStatus">
+          <el-select v-model="queryParams.businessStatus" placeholder="请选择跟进状态" clearable size="small">
+            <el-option
+              v-for="item in businessStatusOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="项目阶段" prop="projectPhase">
+          <el-select v-model="queryParams.projectPhase" placeholder="请选择" clearable size="small">
+            <el-option
+                v-for="item in projectPhaseOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="意向等级" prop="level">
+          <el-select v-model="queryParams.level" placeholder="请选择" clearable size="small">
+            <el-option
+                v-for="item in levelOptions"
+                :key="item.dictValue"
+                :label="item.dictLabel"
+                :value="item.dictValue"
+            />
+          </el-select>
+        </el-form-item>
+        <!-- <el-form-item label="是否绑定BP账号" prop="isBp">
+          <el-input
+            v-model="queryParams.isBp"
+            placeholder="请输入是否绑定BP账号"
+            clearable
+            size="small"
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item> -->
+        <!-- <el-form-item label="BP账户" prop="bpAccount">
+          <el-input
+            v-model="queryParams.bpAccount"
+            placeholder="请输入BP账户"
+            clearable
+            size="small"
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item> -->
+        <!-- <el-form-item label="预计成单时间" prop="preTime">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="queryParams.preTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择预计成单时间">
+          </el-date-picker>
+        </el-form-item> -->
+        <!-- <el-form-item label="预计付费(元)" prop="preMoney">
+          <el-input
+            v-model="queryParams.preMoney"
+            placeholder="请输入预计付费(元)"
+            clearable
+            size="small"
+            @keyup.enter.native="handleQuery"
+          />
+        </el-form-item> -->
+        <!-- <el-form-item label="挖掘时间" prop="createTime">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="queryParams.createTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择挖掘时间">
+          </el-date-picker>
+        </el-form-item> -->
+        <el-form-item label="挖掘时间" prop="createTimeRange">
+          <el-date-picker
+            style="width:205.4px"
+            clearable size="small"
+            v-model="createTimeRange"
+            type="daterange"
+            value-format="yyyy-MM-dd"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期">
+          </el-date-picker>
+        </el-form-item>
+        <!-- <el-form-item label="下次跟进时间" prop="nextTime">
+          <el-date-picker clearable size="small" style="width: 200px"
+            v-model="queryParams.nextTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择下次跟进时间">
+          </el-date-picker>
+        </el-form-item> -->
+        <el-form-item label="下次跟进" prop="nextTimeRange">
+          <el-date-picker
+            style="width:205.4px"
+            clearable size="small"
+            v-model="nextTimeRange"
+            type="daterange"
+            value-format="yyyy-MM-dd"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期">
+          </el-date-picker>
+        </el-form-item>
+
+        <el-form-item>
+          <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+          <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+        </el-form-item>
+      </el-form>
+
+      <el-row :gutter="10" class="mb8">
+<!--        <el-col :span="1.5">-->
+<!--          <el-button-->
+<!--            type="primary"-->
+<!--            icon="el-icon-plus"-->
+<!--            size="mini"-->
+<!--            @click="handleAdd"-->
+<!--            v-hasPermi="['crm:business:add']"-->
+<!--          >新增</el-button>-->
+<!--        </el-col>-->
+        <el-col :span="1.5">
+          <el-button
+            type="success"
+            icon="el-icon-edit"
+            size="mini"
+            :disabled="single"
+            @click="handleUpdate"
+            v-hasPermi="['crm:business:edit']"
+          >修改</el-button>
+        </el-col>
+        <!-- <el-col :span="1.5">
+          <el-button
+            type="danger"
+            icon="el-icon-delete"
+            size="mini"
+            :disabled="multiple"
+            @click="handleDelete"
+            v-hasPermi="['crm:business:remove']"
+          >删除</el-button>
+        </el-col> -->
+        <el-col :span="1.5">
+          <el-button
+            type="danger"
+            icon="el-icon-delete"
+            size="mini"
+            :disabled="multiple"
+            @click="handleDelete"
+          >删除</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button
+            type="warning"
+            icon="el-icon-download"
+            size="mini"
+            @click="handleExport"
+            v-hasPermi="['crm:business:export']"
+          >导出</el-button>
+        </el-col>
+        <el-col :span="1.5">
+          <el-button
+            type="warning"
+            icon="el-icon-upload2"
+            size="mini"
+            @click="handleImport"
+            v-hasPermi="['crm:business:import']"
+          >导入</el-button>
+        </el-col>
+
+        <el-col :span="1.5">
+            <el-button size="mini" icon="el-icon-s-operation" @click="handleSetColumn()" >设置列表</el-button>
+        </el-col>
+
+        <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+      </el-row>
+
+      <div>
+        <el-table  border v-loading="loading" :data="businessList"
+          @selection-change="handleSelectionChange"
+          @sort-change="handleSortChange"
+          >
+          <el-table-column type="selection" width="55" align="center" />
+          <!-- 动态渲染列 -->
+          <el-table-column
+            v-for="col in visibleColumns"
+            :key="col.prop"
+            :label="col.label"
+            :width="col.width"
+            align="center"
+            :prop="col.prop"
+            :sortable="col.prop === 'nextTime' ? 'custom' : false"
+            >
+
+            <template slot-scope="scope">
+
+              <!-- 如果是客户来源字段 -->
+              <template v-if="col.prop === 'source'">
+                <el-tag v-for="item in clueSourceOptions" :key="item.dictValue" v-show="scope.row.source == item.dictValue">
+                  {{ item.dictLabel }}
+                </el-tag>
+              </template>
+
+
+
+              <!-- 如果是相关客户电话号码字段 -->
+              <template v-else-if="col.prop === 'mobile'">
+                <template>
+                  {{scope.row.mobile}}
+                  <el-button type="text"    size="mini" @click="callNumber(scope.row.customerId,null)" v-show="scope.row.mobile!=null">拨号</el-button>
+                  <!-- <el-button v-hasPermi="['crm:customer:addVisit']"  type="text" size="mini" @click="handleAddVisit(scope.row)" v-show="scope.row.mobile!=null">写跟进</el-button> -->
+                  <el-button v-hasPermi="['crm:customer:addVisit']"  type="text" size="mini" @click="handleAddVisitByBusiness(scope.row)" v-show="scope.row.mobile!=null">写跟进</el-button>
+                </template>
+              </template>
+
+              <!-- 如果是电话号码字段 -->
+              <template v-else-if="col.prop === 'mobileList'">
+                <div>
+                    <template>
+                        <div v-for="(phone, index) in scope.row.mobileList" :key="index" v-if="scope.row.mobileList">
+                            <el-tag >
+                                {{ phone.mobile }}
+                            </el-tag>
+                            <el-button type="text"    size="mini" @click="callNumber(null,phone.contactsId)" v-show="phone.mobile!=null">拨号</el-button>
+                        </div>
+                        <el-button v-hasPermi="['crm:customer:addVisit']"  type="text" size="mini" @click="handleAddVisitByBusiness(scope.row)" v-show="scope.row.mobile==null">写跟进</el-button>
+                    </template>
+                </div>
+              </template>
+
+               <!-- 如果是接口人角色字段 -->
+               <template v-else-if="col.prop === 'contactRole'">
+                <span prop="contactRole" v-for="(item, index) in contactRoleOptions"    v-if="scope.row.contactRole==item.dictValue">{{item.dictLabel}}</span>
+              </template>
+
+              <!-- 如果是业务场景字段 -->
+              <template v-else-if="col.prop === 'businessScenario'">
+                <el-tag v-for="item in businessScenarioOptions" :key="item.dictValue" v-show="scope.row.businessScenario == item.dictValue">
+                  {{ item.dictLabel }}
+                </el-tag>
+              </template>
+
+              <!-- 如果是采购周期字段 -->
+              <template v-else-if="col.prop === 'purchaseCycle'">
+                <span>{{scope.row.purchaseCycle||'--'}}天</span>
+              </template>
+
+              <!-- 如果是跟进状态字段 -->
+              <template v-else-if="col.prop === 'businessStatus'">
+                <span prop="businessStatus" v-for="(item, index) in businessStatusOptions"    v-if="scope.row.businessStatus==item.dictValue">{{item.dictLabel}}</span>
+              </template>
+
+              <!-- 如果是项目阶段字段 -->
+              <template v-else-if="col.prop === 'projectPhase'">
+                <span prop="projectPhase" v-for="(item, index) in projectPhaseOptions" v-if="scope.row.projectPhase==item.dictValue">{{item.dictLabel}}</span>
+              </template>
+
+              <!-- 如果是意向等级字段 -->
+              <template v-else-if="col.prop === 'level'">
+                <span prop="level" v-for="(item, index) in levelOptions" v-if="scope.row.level==item.dictValue">{{item.dictLabel}}</span>
+              </template>
+
+              <!-- 如果是是否绑定BP账号字段 -->
+              <template v-else-if="col.prop === 'isBp'">
+                <span prop="isBp" v-for="(item, index) in isBpOptions" v-if="scope.row.isBp==item.dictValue">{{item.dictLabel}}</span>
+              </template>
+
+              <!-- 如果是预计成单时间字段 -->
+              <template v-else-if="col.prop === 'preTime'">
+                <span>{{ parseTime(scope.row.preTime, '{y}-{m}-{d}') }}</span>
+              </template>
+
+              <!-- 如果是预计付费字段 -->
+              <template v-else-if="col.prop === 'preMoney'">
+                <span>{{scope.row.preMoney||'--'}}元</span>
+              </template>
+
+              <!-- 如果是下次跟进时间字段 -->
+              <template v-else-if="col.prop === 'nextTime'">
+                <span>{{ parseTime(scope.row.nextTime, '{y}-{m}-{d}') }}</span>
+              </template>
+
+              <!-- 如果是下次跟进时间 -->
+              <template v-else-if="col.prop === 'nextTime'">
+                <span style="color: red;">
+                  {{ scope.row.nextTime }}
+                </span>
+              </template>
+              <!-- 其他普通字段 -->
+              <span v-else>{{ scope.row[col.prop] }}</span>
+            </template>
+
+
+          </el-table-column>
+
+          <!-- 操作列,始终显示 -->
+          <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+            <template slot-scope="scope">
+              <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['crm:business:edit']">修改</el-button>
+              <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['crm:business:remove']">删除</el-button>
+              <div v-if="scope.row.customerId !== null">
+                <el-button size="mini" type="text" icon="el-icon-s-custom" @click="handleShow(scope.row)" v-hasPermi="['crm:customer:query']">查看相关客户</el-button>
+              </div>
+              <div v-if="scope.row.customerId == null">
+                <el-button size="mini" type="text" icon="el-icon-s-custom" @click="handlevisitShow(scope.row)" v-hasPermi="['crm:customer:query']">查看商机跟进</el-button>
+              </div>
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <pagination
+          v-show="total>0"
+          :total="total"
+          :page.sync="queryParams.pageNum"
+          :limit.sync="queryParams.pageSize"
+          @pagination="getList"
+        />
+
+        <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
+          <add-business @closeBusiness="closeBusiness"   ref="addBusiness" />
+        </el-dialog>
+        <!-- 显示 allColumns 数据的对话框 -->
+        <el-dialog :visible.sync="columns.open" :title="columns.title">
+          <set-column ref="setColumn" @close="closeSetColumn"/>
+        </el-dialog>
+        <el-drawer size="75%" :title="show.title" :visible.sync="show.open">
+          <customer-details  ref="customerDetails" />
+        </el-drawer>
+        <el-dialog :title="visit.title" :visible.sync="visit.open" width="600px" append-to-body>
+          <add-visit @closeVisit="closeVisit"   ref="addVisit" />
+        </el-dialog>
+        <el-dialog :title="visitView.title" :visible.sync="visitView.open" width="1000px" append-to-body>
+            <customer-visit-list ref="visit"></customer-visit-list>
+        </el-dialog>
+
+        <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+            <el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport + '&type=0'" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
+              <i class="el-icon-upload"></i>
+              <div class="el-upload__text">
+                将文件拖到此处,或
+                <em>点击上传</em>
+              </div>
+              <div class="el-upload__tip" slot="tip">
+                <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
+              </div>
+              <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
+            </el-upload>
+            <div slot="footer" class="dialog-footer">
+              <el-button type="primary" @click="submitFileForm">确 定</el-button>
+              <el-button @click="upload.open = false">取 消</el-button>
+            </div>
+        </el-dialog>
+        <el-dialog title="导入结果" :close-on-press-escape="false" :close-on-click-modal="false" :visible.sync="importMsgOpen" width="500px" append-to-body>
+          <div class="import-msg" v-html="importMsg">
+          </div>
+        </el-dialog>
+      </div>
+    </div>
+  </template>
+
+  <script>
+  import { myListBusiness, getBusiness, delBusiness, updateBusiness, exportMyBusiness,setBusinessPool,importTemplate } from "@/api/crm/business";
+  import addBusiness from '../components/addBusiness.vue';
+  import setColumn from '../components/setColumn.vue';
+  import addVisit from '../components/addVisit.vue';
+  import {getShow} from "@/api/company/show";
+  import customerDetails from '../components/customerDetails.vue';
+  import customerVisitList from '../components/customerVisitList.vue';
+  import { getToken } from "@/utils/auth";
+  export default {
+    name: "Business",
+    components: {setColumn,addBusiness,customerDetails,addVisit,customerVisitList},
+    data() {
+      return {
+        // 用户导入参数
+        upload: {
+          // 是否显示弹出层(用户导入)
+          open: false,
+          // 弹出层标题(用户导入)
+          title: "",
+          // 是否禁用上传
+          isUploading: false,
+          // 设置上传的请求头部
+          headers: { Authorization: "Bearer " + getToken() },
+          // 上传的地址
+          url: process.env.VUE_APP_BASE_API + "/crm/business/importBusinessData",
+        },
+        importMsgOpen:false,
+        importMsg:"",
+        visitView:{
+            open:false,
+            title:"跟进记录"
+        },
+        visit:{
+            open:false,
+            title:"写跟进"
+        },
+        show:{
+          title:"客户详情",
+          open:false,
+        },
+        columns:{
+          title:"设置列表",
+          open:false,
+        },
+        columnType:'business',
+        visibleColumns: [],
+         // 可选字段
+         allColumns: [
+         { prop: "businessId", label: "商机ID" },
+          // { prop: "companyName", label: "客户名称" },
+          { prop: "customerId", label: "客户ID" },
+          { prop: "source", label: "线索来源" },
+          { prop: "manager", label: "客户经理" },
+          { prop: "companyName", label: "企业名称" },
+          { prop: "mobile", label: "相关客户电话",width:120  },
+          { prop: "mobileList", label: "电话号码",width:120},
+          { prop: "contactRole", label: "接口人角色" },
+          { prop: "businessScenario", label: "业务场景" },
+          { prop: "product", label: "方案涉及产品" },
+          { prop: "purchaseCycle", label: "采购周期" },
+          { prop: "businessStatus", label: "跟进状态" },
+          { prop: "content", label: "最新跟进内容" },
+          { prop: "nextTime", label: "下次跟进时间",width: 180, sortable: 'custom' },// 启用自定义排序
+          { prop: "projectPhase", label: "项目阶段" },
+          { prop: "level", label: "意向等级" },
+          { prop: "isBp", label: "是否绑定BP账号" },
+          { prop: "bpAccount", label: "BP账户" },
+          { prop: "preTime", label: "预计成单时间", width: 105 },
+          { prop: "preMoney", label: "预计付费" },
+          { prop: "createTime", label: "挖掘时间", width: 105 },
+        ],
+        // 选中的字段(默认显示所有字段)
+        selectedKeys: [
+          "businessId",
+          "customerId",
+          "source",
+          "manager",
+          "companyName",
+          "mobile",
+          "mobileList",
+          "contactRole",
+          "businessScenario",
+          "product",
+          "purchaseCycle",
+          "businessStatus",
+          "content",
+          "nextTime",
+          "projectPhase",
+          "level",
+          "isBp",
+          "bpAccount",
+          "preTime",
+          "preMoney",
+          "createTime"
+        ],
+        createTimeRange:[],
+        nextTimeRange:[],
+        recoveryRange:[],
+        statusOptions:[
+          {
+            dictValue:1,
+            dictLabel:"已分配"
+          },
+          {
+            dictValue:2,
+            dictLabel:"进行中"
+          },
+          {
+            dictValue:3,
+            dictLabel:"回收"
+          }
+        ],
+        clueSourceOptions:[],
+        contactRoleOptions:[],
+        projectPhaseOptions:[],
+        businessScenarioOptions:[],
+        levelOptions:[],
+        businessStatusOptions:[],
+        isBpOptions:[
+          {
+            dictValue:0,
+            dictLabel:"未注册"
+          },
+          {
+            dictValue:1,
+            dictLabel:"已注册未绑定"
+          },
+          {
+            dictValue:2,
+            dictLabel:"不明确"
+          },
+          {
+            dictValue:3,
+            dictLabel:"已绑定"
+          }
+        ],
+
+        // 遮罩层
+        loading: true,
+        // 选中数组
+        ids: [],
+        // 非单个禁用
+        single: true,
+        // 非多个禁用
+        multiple: true,
+        // 显示搜索条件
+        showSearch: true,
+        // 总条数
+        total: 0,
+        // 商机表格数据
+        businessList: [],
+        // 弹出层标题
+        title: "",
+        // 是否显示弹出层
+        open: false,
+        // 查询参数
+        queryParams: {
+          pageNum: 1,
+          pageSize: 10,
+          // customerId: null,
+          source: null,
+          manager: null,
+          companyName: null,
+          mobile: null,
+          contactRole: null,
+          businessScenario: null,
+          product: null,
+          purchaseCycle: null,
+          businessStatus: null,
+          projectPhase: null,
+          level: null,
+          isBp: null,
+          bpAccount: null,
+          preTime: null,
+          preMoney: null,
+          nextTime: null,
+          recoveryTime: null,
+          status: null,
+          companyName:null,
+          orderBy:null,//nextTime排序规则
+        },
+        // 表单参数
+        form: {},
+        // 表单校验
+        rules: {
+          customerId: [
+            { required: true, message: "客户id不能为空", trigger: "blur" }
+          ],
+        },
+
+      };
+    },
+    created() {
+      this.getDicts("business_scenario_type").then((response) => {
+        this.businessScenarioOptions = response.data;
+      });
+      this.getDicts("crm_customer_source").then((response) => {
+        this.clueSourceOptions = response.data;
+      });
+      this.getDicts("crm_contact_role").then((response) => {
+        this.contactRoleOptions = response.data;
+      });
+      this.getDicts("crm_project_phase").then((response) => {
+        this.projectPhaseOptions = response.data;
+      });
+      this.getDicts("crm_level").then((response) => {
+        this.levelOptions = response.data;
+      });
+      this.getDicts("crm_business_status").then((response) => {
+        this.businessStatusOptions = response.data;
+      });
+      this.getList();
+    },
+    methods: {
+      async handleSortChange({ prop, order }) {
+        try {
+          this.loading = true; // 开始加载
+          const sortOrder = order === 'ascending' ? 'asc' : 'desc'; // 转换排序顺序
+          // const params = {
+          //   sortOrder: sortOrder // 排序顺序
+          // };
+          this.queryParams.orderBy = sortOrder;
+
+          // 调用后端接口获取排序后的数据
+          const response = await this.getList();
+        } catch (error) {
+          console.error('排序失败:', error);
+        } finally {
+          this.loading = false; // 结束加载
+        }
+      },
+      handleAddVisit(row){
+          this.visit.open=true;
+          setTimeout(() => {
+              this.$refs.addVisit.reset(row.customerId);
+          }, 200);
+      },
+      handleAddVisitByBusiness(row){
+          this.visit.open=true;
+          setTimeout(() => {
+              this.$refs.addVisit.resetBusiness(row.businessId);
+          }, 200);
+      },
+      closeVisit(){
+          this.visit.open=false;
+          this.getList();
+      },
+      handlevisitShow(row){
+        this.visitView.open=true;
+        setTimeout(() => {
+            this.$refs.visit. getBusinessData(row.businessId);
+        }, 200);
+
+      },
+      handleShow(row){
+        this.show.open=true;
+        var that=this;
+        const tab = "visit";
+        setTimeout(() => {
+          that.$refs.customerDetails.getDetails(row.customerId);
+          that.$refs.customerDetails.handleClick(tab);
+
+        }, 200);
+      },
+      handleSetColumn(){
+        this.columns.open=true;
+        var that=this;
+        setTimeout(() => {
+              that.$refs.setColumn.reset(that.allColumns,that.selectedKeys,that.columnType);
+        }, 200);
+      },
+      closeSetColumn(){
+        this.columns.open=false;
+        this.getList();
+      },
+      handleBusiness(row){
+          this.business.open=true;
+          setTimeout(() => {
+              this.$refs.addBusiness.reset(row);
+          }, 200);
+      },
+      closeBusiness(){
+          this.open=false;
+          this.getList();
+      },
+      //查询显示字段
+      async getColumn(){
+        const response = await getShow(this.columnType);
+        if (response.code === 200 && response.data) {
+          this.selectedKeys = response.data.columns.split(",");
+          this.$set(this, "visibleColumns", this.allColumns.filter(col => this.selectedKeys.includes(col.prop)));
+
+        } else{
+          this.$set(this, "visibleColumns", this.allColumns);
+        }
+      },
+      /** 查询客户列表 */
+      async getList() {
+        this.loading = true;
+        await this.getColumn(); // 确保 visibleColumns 先获取到
+        if(this.createTimeRange!=null&&this.createTimeRange.length==2){
+          this.queryParams.createTimeRange=this.createTimeRange[0]+"--"+this.createTimeRange[1]
+        }
+        else{
+          this.queryParams.createTimeRange=null;
+        }
+        if(this.nextTimeRange!=null&&this.nextTimeRange.length==2){
+          this.queryParams.nextTimeRange=this.nextTimeRange[0]+"--"+this.nextTimeRange[1]
+        }
+        else{
+          this.queryParams.nextTimeRange=null;
+        }
+        if(this.recoveryRange!=null&&this.recoveryRange.length==2){
+          this.queryParams.recoveryRange=this.recoveryRange[0]+"--"+this.recoveryRange[1]
+        }
+        else{
+          this.queryParams.recoveryRange=null;
+        }
+        const response = await myListBusiness(this.addDateRange(this.queryParams, this.dateRange));
+        this.businessList = response.rows
+        this.total = response.total;
+        this.loading = false;
+
+      },
+      // 取消按钮
+      cancel() {
+        this.open = false;
+        this.reset();
+      },
+      // 表单重置
+      reset() {
+        this.form = {
+          businessId: null,
+          customerId: null,
+          source: null,
+          manager: null,
+          companyName: null,
+          mobile: null,
+          contactRole: null,
+          businessScenario: null,
+          product: null,
+          purchaseCycle: null,
+          businessStatus: 0,
+          remark: null,
+          projectPhase: null,
+          level: null,
+          isBp: null,
+          bpAccount: null,
+          preTime: null,
+          preMoney: null,
+          nextTime: null,
+          createTime: null,
+          updateTime: null,
+          createBy: null,
+          recoveryTime: null,
+          status: 0,
+          // createTimeRange:null,
+          // nextTimeRange:null,
+          // recoveryRange:null
+        };
+        this.resetForm("form");
+      },
+      /** 搜索按钮操作 */
+      handleQuery() {
+        this.queryParams.pageNum = 1;
+        this.getList();
+      },
+      /** 重置按钮操作 */
+      resetQuery() {
+        this.resetForm("queryForm");
+        this.handleQuery();
+      },
+      // 多选框选中数据
+      handleSelectionChange(selection) {
+        this.ids = selection.map(item => item.businessId)
+        this.single = selection.length!==1
+        this.multiple = !selection.length
+      },
+      /** 新增按钮操作 */
+      handleAdd() {
+        this.reset();
+        this.open = true;
+        this.title = "添加商机";
+      },
+      /** 修改按钮操作 */
+      handleUpdate(row) {
+        this.reset();
+        const businessId = row.businessId || this.ids
+        getBusiness(businessId).then(response => {
+          this.form = response.data;
+          this.form.source = String(response.data.source);
+          this.form.contactRole = String(response.data.contactRole);
+          this.form.level = String(response.data.level);
+          this.form.businessStatus =response.data.businessStatus;
+          console.log("111111111111111111111",JSON.stringify(this.form))
+          this.open = true;
+          this.title = "修改商机";
+          setTimeout(() => {
+              this.$refs.addBusiness.updateReset(row);
+          }, 200);
+        });
+      },
+      // /** 提交按钮 */
+      // submitForm() {
+      //   this.$refs["form"].validate(valid => {
+      //     if (valid) {
+      //       if (this.form.businessId != null) {
+      //         updateBusiness(this.form).then(response => {
+      //           if (response.code === 200) {
+      //             this.msgSuccess("修改成功");
+      //             this.open = false;
+      //             this.getList();
+      //           }
+      //         });
+      //       } else {
+      //         addBusiness(this.form).then(response => {
+      //           if (response.code === 200) {
+      //             this.msgSuccess("新增成功");
+      //             this.open = false;
+      //             this.getList();
+      //           }
+      //         });
+      //       }
+      //     }
+      //   });
+      // },
+      /** 删除按钮操作 */
+      handleDelete(row) {
+        const businessIds = row.businessId || this.ids;
+        this.$confirm('是否确认删除商机编号为"' + businessIds + '"的数据项?', "警告", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          }).then(function() {
+            return delBusiness(businessIds);
+          }).then(() => {
+            this.getList();
+            this.msgSuccess("删除成功");
+          }).catch(function() {});
+      },
+     /** 导入按钮操作 */
+      handleImport() {
+        this.upload.title = "商机导入";
+        this.upload.open = true;
+
+      },
+      /** 下载模板操作 */
+      importTemplate() {
+        importTemplate().then((response) => {
+          this.download(response.msg);
+        });
+      },
+      // 文件上传中处理
+      handleFileUploadProgress(event, file, fileList) {
+        this.upload.isUploading = true;
+      },
+      // 文件上传成功处理
+      handleFileSuccess(response, file, fileList) {
+        this.upload.open = false;
+        this.upload.isUploading = false;
+        this.$refs.upload.clearFiles();
+        this.importMsgOpen=true;
+        this.importMsg=response.msg
+        this.getList();
+      },
+      // 提交上传文件
+      submitFileForm() {
+        this.$refs.upload.submit();
+      },
+      /** 导出按钮操作 */
+      handleExport() {
+        const queryParams = this.queryParams;
+        this.$confirm('是否确认导出所有商机数据项?', "警告", {
+            confirmButtonText: "确定",
+            cancelButtonText: "取消",
+            type: "warning"
+          }).then(function() {
+            return exportMyBusiness(queryParams);
+          }).then(response => {
+            this.download(response.msg);
+          }).catch(function() {});
+      }
+    }
+  };
+  </script>