|
|
@@ -1,159 +1,232 @@
|
|
|
<template>
|
|
|
- <a-flex style="padding: 0 20px" vertical :gap="10">
|
|
|
- <a-card :bordered="false">
|
|
|
- <a-flex justify="space-between" align="center">
|
|
|
- <a-flex align="center" gap="small">
|
|
|
- <a-flex vertical gap="small">
|
|
|
- <div class="header-info">
|
|
|
- <div class="header-info-top">
|
|
|
- <span>{{ singleCusValue?.customerName }}</span>
|
|
|
- <a-tag color="#D4AF37" style="font-size: 15px">111</a-tag>
|
|
|
- </div>
|
|
|
- <div class="header-info-bottom">
|
|
|
- <div>
|
|
|
- 客户类型:
|
|
|
- <span>{{ singleCusValue?.customerType?.[0]?.valueName }}</span>
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- 客户编码:
|
|
|
- <span>{{ singleCusValue?.customerCode }}</span>
|
|
|
- </div>
|
|
|
- <div>
|
|
|
- 所在省市:
|
|
|
- <span>{{ `${singleCusValue?.provinceName}${singleCusValue?.cityName}` }}</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </a-flex>
|
|
|
- </a-flex>
|
|
|
- </a-flex>
|
|
|
- </a-card>
|
|
|
- <a-card :bordered="false">
|
|
|
- <a-flex vertical gap="small">
|
|
|
- <div class="context">
|
|
|
- <div v-for="item in descList" :key="item.id" class="context-item">
|
|
|
- <span>{{ item.label }}</span>
|
|
|
- <span>{{ item.value }}</span>
|
|
|
+ <div class="page-detail">
|
|
|
+ <page-detail-layout :tabs="tabs" v-model:tab-active-key="tabActiveKey" :index-config="indexConfig" :title="headerIndexData?.customerName">
|
|
|
+ <template #titleRight>
|
|
|
+ <img v-if="customerDetailData?.customerGrade?.[0].valueCode === 'S'" src="/@/assets/images/page-detail-layout/customer/SS_user.png" alt="" />
|
|
|
+ <img v-if="customerDetailData?.customerGrade?.[0].valueCode === 'A'" src="/@/assets/images/page-detail-layout/customer/AA_user.png" alt="" />
|
|
|
+ <img v-if="customerDetailData?.customerGrade?.[0].valueCode === 'B'" src="/@/assets/images/page-detail-layout/customer/BB_user.png" alt="" />
|
|
|
+ <img v-if="customerDetailData?.customerGrade?.[0].valueCode === 'C'" src="/@/assets/images/page-detail-layout/customer/CC_user.png" alt="" />
|
|
|
+ <bs-dic-tag :dicts="customerDetailData?.customerSource" />
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #toolBtn>
|
|
|
+ <a-button danger ghost type="primary" size="small">
|
|
|
+ <UserAddOutlined />
|
|
|
+ <span>加入黑名单</span>
|
|
|
+ </a-button>
|
|
|
+ <a-button danger ghost type="primary" size="small" @click="handleTransferPublicSea">
|
|
|
+ <UserDeleteOutlined />
|
|
|
+ <span>释放公海</span>
|
|
|
+ </a-button>
|
|
|
+ <a-button ghost type="primary" size="small" @click="customerTransferModalRef.showModal()">
|
|
|
+ <RightSquareOutlined />
|
|
|
+ <span> 客户转移 </span></a-button
|
|
|
+ >
|
|
|
+ <a-button type="primary" size="small">
|
|
|
+ <EditOutlined />
|
|
|
+ <span>信息编辑</span>
|
|
|
+ </a-button>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #titleBottom>
|
|
|
+ <a-tag color="#f0f4fe" v-for="(tagItem, tagIndex) in tagList" :key="tagIndex" @click="tagItem?.click(tagItem)" style="cursor: pointer">
|
|
|
+ <div class="tag-stl">
|
|
|
+ <img :src="tagItem.icon" alt="" />
|
|
|
+ <span class="title-render">{{ tagItem.title }}</span>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </a-flex>
|
|
|
- </a-card>
|
|
|
- <a-card :tab-list="tabList" :active-tab-key="tabKey" @tabChange="onTabChange">
|
|
|
- <component :is="tabList[tabKey]['component']" :id="query.id" :descData="singleCusValue"></component>
|
|
|
- </a-card>
|
|
|
- </a-flex>
|
|
|
+ </a-tag>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #BasicInfo>
|
|
|
+ <BasicInfo :id="route.query.id" :descData="headerIndexData" />
|
|
|
+ </template>
|
|
|
+ <template #ProjectInfo>
|
|
|
+ <ProjectInfo :id="route.query.id" />
|
|
|
+ </template>
|
|
|
+ <template #InfoMaterial>
|
|
|
+ <InfoMaterial :id="route.query.id" />
|
|
|
+ </template>
|
|
|
+ </page-detail-layout>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
- import { ref, defineAsyncComponent, onMounted, watchEffect } from 'vue';
|
|
|
- import { clientManageApi } from '/@/api/market-manage/index.js';
|
|
|
- import { useRouter } from 'vue-router';
|
|
|
-
|
|
|
-
|
|
|
- onMounted(() => {
|
|
|
- getSingleCustomerList();
|
|
|
- });
|
|
|
-
|
|
|
- const router = useRouter();
|
|
|
- const query = router.currentRoute.value.query;
|
|
|
+ import { onMounted, reactive, ref, watch } from 'vue';
|
|
|
+ import { useRoute } from 'vue-router';
|
|
|
+ import PageDetailLayout from '/@/components/business/page-detail-layout/index.vue';
|
|
|
+ import BasicInfo from '/@/views/market-manage/external-manage/customer-manage/single-customer/components/customer-info.vue';
|
|
|
+ import ProjectInfo from '/@/views/market-manage/external-manage/customer-manage/single-customer/components/project-list.vue';
|
|
|
+ import InfoMaterial from '/@/views/market-manage/external-manage/customer-manage/single-customer/components/file-info.vue';
|
|
|
+ import { clientManageApi, fetchCustomerHeaderInfo, fetchCustomerDetail } from '/@/api/market-manage/index.js';
|
|
|
+
|
|
|
+ const route = useRoute();
|
|
|
+ const headerIndexData = ref(null);
|
|
|
+ const stepsData = [
|
|
|
+ {
|
|
|
+ title: '标段备案',
|
|
|
+ time: '2024-09-18',
|
|
|
+ status: 'completed',
|
|
|
+ number: 1,
|
|
|
+ lineTopNum: 100,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '商机管理',
|
|
|
+ time: '2024-09-20',
|
|
|
+ status: 'completed',
|
|
|
+ number: 2,
|
|
|
+ lineTopNum: 100,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '项目立项',
|
|
|
+ time: '2024-10-11',
|
|
|
+ status: 'completed',
|
|
|
+ number: 3,
|
|
|
+ lineTopNum: 100,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '投标评审',
|
|
|
+ status: 'current',
|
|
|
+ number: 4,
|
|
|
+ lineTopNum: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '投标管理',
|
|
|
+ status: 'todo',
|
|
|
+ number: 5,
|
|
|
+ lineTopNum: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '中标捷报',
|
|
|
+ status: 'todo',
|
|
|
+ number: 6,
|
|
|
+ lineTopNum: 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '合同签订',
|
|
|
+ status: 'todo',
|
|
|
+ number: 7,
|
|
|
+ lineTopNum: 0,
|
|
|
+ },
|
|
|
+ ];
|
|
|
|
|
|
- const singleCusValue = ref();
|
|
|
+ const handleTransferPublicSea = () => {
|
|
|
+ transferPublicSeaModalRef.value.showModal();
|
|
|
+ };
|
|
|
|
|
|
- const descList = ref([
|
|
|
- { id: '1', label: '合同数量', value: '0' },
|
|
|
- { id: '2', label: '累计合同额', value: '0' },
|
|
|
- { id: '3', label: '联系人', value: '0' },
|
|
|
- { id: '4', label: '联系电话', value: '0' },
|
|
|
- ]);
|
|
|
+ const getImgUrl = (name) => {
|
|
|
+ return new URL('/src/assets/images/page-detail-layout/customer/' + name + '.svg', import.meta.url).href;
|
|
|
+ };
|
|
|
|
|
|
- const tabKey = ref('0');
|
|
|
- const tabList = [
|
|
|
+ const tagList = [
|
|
|
{
|
|
|
- key: '0',
|
|
|
- tab: '基本信息',
|
|
|
- component: defineAsyncComponent(() => import('./components/customer-info.vue')),
|
|
|
+ title: '天眼查',
|
|
|
+ icon: getImgUrl('icon-tianyancha'),
|
|
|
},
|
|
|
{
|
|
|
- key: '1',
|
|
|
- tab: '项目信息',
|
|
|
- component: defineAsyncComponent(() => import('./components/project-list.vue')),
|
|
|
+ title: '线索登记',
|
|
|
+ icon: getImgUrl('icon-xiansuodengji'),
|
|
|
},
|
|
|
{
|
|
|
- key: '2',
|
|
|
- tab: '文件资料',
|
|
|
- component: defineAsyncComponent(() => import('./components/file-info.vue')),
|
|
|
+ title: '标签管理',
|
|
|
+ icon: getImgUrl('icon-biaoqianguanli'),
|
|
|
+ click(it) {
|
|
|
+ tagManageModalRef.value.showModal();
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '曾用名',
|
|
|
+ icon: getImgUrl('icon-cengyongming'),
|
|
|
+ click(it) {
|
|
|
+ usedNameModalRef.value.showModal();
|
|
|
+ },
|
|
|
},
|
|
|
];
|
|
|
|
|
|
+ const tabs = ref([
|
|
|
+ {
|
|
|
+ title: '基本信息',
|
|
|
+ key: 'BasicInfo',
|
|
|
+ slotName: 'BasicInfo',
|
|
|
+ selectedIcon: getImgUrl('icon-jibenxinxi-all'),
|
|
|
+ unSelectedIcon: getImgUrl('icon-jibenxinxi'),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '项目信息',
|
|
|
+ key: 'ProjectInfo',
|
|
|
+ slotName: 'ProjectInfo',
|
|
|
+ selectedIcon: getImgUrl('icon-jibenxinxi-all'),
|
|
|
+ unSelectedIcon: getImgUrl('icon-jibenxinxi'),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '信息资料',
|
|
|
+ key: 'InfoMaterial',
|
|
|
+ slotName: 'InfoMaterial',
|
|
|
+ selectedIcon: getImgUrl('icon-xinxiziliao-all'),
|
|
|
+ unSelectedIcon: getImgUrl('icon-xinxiziliao'),
|
|
|
+ },
|
|
|
+ ]);
|
|
|
|
|
|
- // 查询列表
|
|
|
- function getSingleCustomerList() {
|
|
|
- clientManageApi.customerDetails(query.id).then(
|
|
|
- (res) => {
|
|
|
- singleCusValue.value = res.data;
|
|
|
- // 动态更新 descList
|
|
|
- descList.value = [
|
|
|
- { id: '1', label: '合同数量', value: singleCusValue.value.customerManager },
|
|
|
- { id: '2', label: '累计合同额', value: singleCusValue.value.customerManager },
|
|
|
- { id: '3', label: '联系人', value: singleCusValue.value.customerManager },
|
|
|
- { id: '4', label: '联系电话', value: singleCusValue.value.customerManagerMobile },
|
|
|
- ];
|
|
|
- },
|
|
|
- (err) => {
|
|
|
- console.error(err);
|
|
|
- }
|
|
|
- );
|
|
|
- }
|
|
|
+ const customerDetailData = ref(null);
|
|
|
+
|
|
|
+ const indexConfig = ref({
|
|
|
+ sourceData: [],
|
|
|
+ labelKey: 'label',
|
|
|
+ valueKey: 'value',
|
|
|
+ });
|
|
|
|
|
|
- const onTabChange = (value) => {
|
|
|
- tabKey.value = value;
|
|
|
+ const setSourceData = (resData) => {
|
|
|
+ indexConfig.value = {
|
|
|
+ sourceData: [
|
|
|
+ {
|
|
|
+ label: '合同数量',
|
|
|
+ value: resData.legalPerson || 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '累计合同金额(元)',
|
|
|
+ value: resData.legalPerson || 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '累计收款(元)',
|
|
|
+ value: resData.legalPerson || 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '累计开票(元)',
|
|
|
+ value: resData.legalPerson || 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '累计未回款(元)',
|
|
|
+ value: resData.legalPerson || 0,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ labelKey: 'label',
|
|
|
+ valueKey: 'value',
|
|
|
+ };
|
|
|
};
|
|
|
-</script>
|
|
|
|
|
|
-<style lang="less" scoped>
|
|
|
- .header-info {
|
|
|
- .header-info-top {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 20px;
|
|
|
- margin-bottom: 10px;
|
|
|
+ onMounted(() => {
|
|
|
+ clientManageApi.customerDetails(route.query.id).then((res) => {
|
|
|
+ headerIndexData.value = res.data;
|
|
|
+ setSourceData(headerIndexData.value);
|
|
|
+ });
|
|
|
+
|
|
|
+ fetchCustomerDetail(route.query.id).then((res) => {
|
|
|
+ customerDetailData.value = res.data;
|
|
|
+ });
|
|
|
+ });
|
|
|
+</script>
|
|
|
|
|
|
- span {
|
|
|
- font-size: 20px;
|
|
|
- font-weight: 600;
|
|
|
- }
|
|
|
- }
|
|
|
+<style lang="scss" scoped>
|
|
|
+ .page-detail {
|
|
|
+ width: 100%;
|
|
|
|
|
|
- .header-info-bottom {
|
|
|
+ .tag-stl {
|
|
|
display: flex;
|
|
|
+ gap: 5px;
|
|
|
align-items: center;
|
|
|
- gap: 80px;
|
|
|
-
|
|
|
- span {
|
|
|
- font-size: 15px;
|
|
|
- font-weight: 600;
|
|
|
- color: rgb(0, 0, 0);
|
|
|
+ .title-render {
|
|
|
+ color: #999999;
|
|
|
+ font-size: 14px;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- .context {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 100px;
|
|
|
- margin-left: 20px;
|
|
|
-
|
|
|
- .context-item {
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
- align-items: center;
|
|
|
- gap: 10px;
|
|
|
- }
|
|
|
-
|
|
|
- span:nth-child(1) {
|
|
|
- font-size: 15px;
|
|
|
- font-weight: 600;
|
|
|
- color: rgb(1, 1, 1);
|
|
|
- }
|
|
|
- }
|
|
|
</style>
|