From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目
---
src/views/crm/backlog/index.vue | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 177 insertions(+), 0 deletions(-)
diff --git a/src/views/crm/backlog/index.vue b/src/views/crm/backlog/index.vue
new file mode 100644
index 0000000..49a1d4c
--- /dev/null
+++ b/src/views/crm/backlog/index.vue
@@ -0,0 +1,177 @@
+<template>
+ <doc-alert title="銆愰�氱敤銆戣窡杩涜褰曘�佸緟鍔炰簨椤�" url="https://doc.iocoder.cn/crm/follow-up/" />
+
+ <el-row :gutter="20">
+ <el-col :span="4" class="min-w-[200px]">
+ <div class="side-item-list">
+ <div
+ v-for="(item, index) in leftSides"
+ :key="index"
+ :class="leftMenu == item.menu ? 'side-item-select' : 'side-item-default'"
+ class="side-item"
+ @click="sideClick(item)"
+ >
+ {{ item.name }}
+ <el-badge v-if="item.count > 0" :max="99" :value="item.count" />
+ </div>
+ </div>
+ </el-col>
+ <el-col :span="20" :xs="24">
+ <CustomerTodayContactList v-if="leftMenu === 'customerTodayContact'" />
+ <ClueFollowList v-if="leftMenu === 'clueFollow'" />
+ <ContractAuditList v-if="leftMenu === 'contractAudit'" />
+ <ReceivableAuditList v-if="leftMenu === 'receivableAudit'" />
+ <ContractRemindList v-if="leftMenu === 'contractRemind'" />
+ <CustomerFollowList v-if="leftMenu === 'customerFollow'" />
+ <CustomerPutPoolRemindList v-if="leftMenu === 'customerPutPoolRemind'" />
+ <ReceivablePlanRemindList v-if="leftMenu === 'receivablePlanRemind'" />
+ </el-col>
+ </el-row>
+</template>
+
+<script lang="ts" setup>
+import CustomerFollowList from './components/CustomerFollowList.vue'
+import CustomerTodayContactList from './components/CustomerTodayContactList.vue'
+import CustomerPutPoolRemindList from './components/CustomerPutPoolRemindList.vue'
+import ClueFollowList from './components/ClueFollowList.vue'
+import ContractAuditList from './components/ContractAuditList.vue'
+import ContractRemindList from './components/ContractRemindList.vue'
+import ReceivablePlanRemindList from './components/ReceivablePlanRemindList.vue'
+import ReceivableAuditList from './components/ReceivableAuditList.vue'
+import * as CustomerApi from '@/api/crm/customer'
+import * as ClueApi from '@/api/crm/clue'
+import * as ContractApi from '@/api/crm/contract'
+import * as ReceivableApi from '@/api/crm/receivable'
+import * as ReceivablePlanApi from '@/api/crm/receivable/plan'
+
+defineOptions({ name: 'CrmBacklog' })
+
+const leftMenu = ref('customerTodayContact')
+
+const clueFollowCount = ref(0)
+const customerFollowCount = ref(0)
+const customerPutPoolRemindCount = ref(0)
+const customerTodayContactCount = ref(0)
+const contractAuditCount = ref(0)
+const contractRemindCount = ref(0)
+const receivableAuditCount = ref(0)
+const receivablePlanRemindCount = ref(0)
+
+const leftSides = ref([
+ {
+ name: '浠婃棩闇�鑱旂郴瀹㈡埛',
+ menu: 'customerTodayContact',
+ count: customerTodayContactCount
+ },
+ {
+ name: '鍒嗛厤缁欐垜鐨勭嚎绱�',
+ menu: 'clueFollow',
+ count: clueFollowCount
+ },
+ {
+ name: '鍒嗛厤缁欐垜鐨勫鎴�',
+ menu: 'customerFollow',
+ count: customerFollowCount
+ },
+ {
+ name: '寰呰繘鍏ュ叕娴风殑瀹㈡埛',
+ menu: 'customerPutPoolRemind',
+ count: customerPutPoolRemindCount
+ },
+ {
+ name: '寰呭鏍稿悎鍚�',
+ menu: 'contractAudit',
+ count: contractAuditCount
+ },
+ {
+ name: '寰呭鏍稿洖娆�',
+ menu: 'receivableAudit',
+ count: receivableAuditCount
+ },
+ {
+ name: '寰呭洖娆炬彁閱�',
+ menu: 'receivablePlanRemind',
+ count: receivablePlanRemindCount
+ },
+ {
+ name: '鍗冲皢鍒版湡鐨勫悎鍚�',
+ menu: 'contractRemind',
+ count: contractRemindCount
+ }
+])
+
+/** 渚ц竟鐐瑰嚮 */
+const sideClick = (item: any) => {
+ leftMenu.value = item.menu
+}
+
+const getCount = () => {
+ CustomerApi.getTodayContactCustomerCount().then(
+ (count) => (customerTodayContactCount.value = count)
+ )
+ CustomerApi.getPutPoolRemindCustomerCount().then(
+ (count) => (customerPutPoolRemindCount.value = count)
+ )
+ CustomerApi.getFollowCustomerCount().then((count) => (customerFollowCount.value = count))
+ ClueApi.getFollowClueCount().then((count) => (clueFollowCount.value = count))
+ ContractApi.getAuditContractCount().then((count) => (contractAuditCount.value = count))
+ ContractApi.getRemindContractCount().then((count) => (contractRemindCount.value = count))
+ ReceivableApi.getAuditReceivableCount().then((count) => (receivableAuditCount.value = count))
+ ReceivablePlanApi.getReceivablePlanRemindCount().then(
+ (count) => (receivablePlanRemindCount.value = count)
+ )
+}
+
+/** 婵�娲绘椂 */
+onActivated(async () => {
+ getCount()
+})
+
+/** 鍒濆鍖� */
+onMounted(async () => {
+ getCount()
+})
+</script>
+
+<style lang="scss" scoped>
+.side-item-list {
+ top: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1;
+ font-size: 14px;
+ background-color: var(--el-bg-color);
+ border: 1px solid var(--el-border-color);
+ border-radius: 5px;
+
+ .side-item {
+ position: relative;
+ height: 50px;
+ padding: 0 20px;
+ line-height: 50px;
+ cursor: pointer;
+ }
+}
+
+.side-item-default {
+ color: var(--el-text-color-primary);
+ border-right: 2px solid transparent;
+}
+
+.side-item-select {
+ color: var(--el-color-primary);
+ background-color: var(--el-color-primary-light-9);
+ border-right: 2px solid var(--el-color-primary);
+}
+
+.el-badge :deep(.el-badge__content) {
+ top: 0;
+ border: none;
+}
+
+.el-badge {
+ position: absolute;
+ top: 0;
+ right: 15px;
+}
+</style>
--
Gitblit v1.8.0