feat: 完善部分详情
parent
6edd0826a6
commit
4f219881c2
|
@ -1,5 +1,3 @@
|
||||||
import type { PageResult } from '@vben/request';
|
|
||||||
|
|
||||||
import { requestClient } from '#/api/request';
|
import { requestClient } from '#/api/request';
|
||||||
|
|
||||||
export namespace CrmPermissionApi {
|
export namespace CrmPermissionApi {
|
||||||
|
@ -57,7 +55,7 @@ export enum PermissionLevelEnum {
|
||||||
|
|
||||||
/** 获得数据权限列表(查询团队成员列表) */
|
/** 获得数据权限列表(查询团队成员列表) */
|
||||||
export function getPermissionList(params: CrmPermissionApi.PermissionListReq) {
|
export function getPermissionList(params: CrmPermissionApi.PermissionListReq) {
|
||||||
return requestClient.get<PageResult<CrmPermissionApi.Permission>>(
|
return requestClient.get<CrmPermissionApi.Permission[]>(
|
||||||
'/crm/permission/list',
|
'/crm/permission/list',
|
||||||
{ params },
|
{ params },
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,16 +5,18 @@ import { defineAsyncComponent, onMounted, ref } from 'vue';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
import { Page, useVbenModal } from '@vben/common-ui';
|
||||||
|
import { useTabs } from '@vben/hooks';
|
||||||
import { ArrowLeft } from '@vben/icons';
|
import { ArrowLeft } from '@vben/icons';
|
||||||
|
|
||||||
import { Button, Card, Modal, Tabs } from 'ant-design-vue';
|
import { Button, Card, Modal, Tabs } from 'ant-design-vue';
|
||||||
|
|
||||||
import { getClue, transformClue } from '#/api/crm/clue';
|
import { getClue, transformClue } from '#/api/crm/clue';
|
||||||
|
import { BizTypeEnum } from '#/api/crm/permission';
|
||||||
import { useDescription } from '#/components/description';
|
import { useDescription } from '#/components/description';
|
||||||
|
import { PermissionList, TransferForm } from '#/views/crm/permission';
|
||||||
|
|
||||||
import { useDetailSchema } from '../data';
|
import { useDetailSchema } from '../data';
|
||||||
import ClueForm from './form.vue';
|
import ClueForm from './form.vue';
|
||||||
import TransferForm from './transfer.vue';
|
|
||||||
|
|
||||||
const ClueDetailsInfo = defineAsyncComponent(() => import('./detail-info.vue'));
|
const ClueDetailsInfo = defineAsyncComponent(() => import('./detail-info.vue'));
|
||||||
|
|
||||||
|
@ -22,6 +24,7 @@ const loading = ref(false);
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const tabs = useTabs();
|
||||||
|
|
||||||
const clueId = ref(0);
|
const clueId = ref(0);
|
||||||
|
|
||||||
|
@ -58,6 +61,7 @@ async function loadClueDetail() {
|
||||||
|
|
||||||
/** 返回列表页 */
|
/** 返回列表页 */
|
||||||
function handleBack() {
|
function handleBack() {
|
||||||
|
tabs.closeCurrentTab();
|
||||||
router.push('/crm/clue');
|
router.push('/crm/clue');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +72,7 @@ function handleEdit() {
|
||||||
|
|
||||||
/** 转移线索 */
|
/** 转移线索 */
|
||||||
function handleTransfer() {
|
function handleTransfer() {
|
||||||
transferModalApi.setData({ id: clueId }).open();
|
transferModalApi.setData({ bizType: BizTypeEnum.CRM_CLUE }).open();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 转化为客户 */
|
/** 转化为客户 */
|
||||||
|
@ -141,7 +145,13 @@ onMounted(async () => {
|
||||||
<ClueDetailsInfo :clue="clue" />
|
<ClueDetailsInfo :clue="clue" />
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane tab="团队成员" key="3">
|
<Tabs.TabPane tab="团队成员" key="3">
|
||||||
<div>团队成员</div>
|
<PermissionList
|
||||||
|
ref="permissionListRef"
|
||||||
|
:biz-id="clue.id!"
|
||||||
|
:biz-type="BizTypeEnum.CRM_CLUE"
|
||||||
|
:show-action="true"
|
||||||
|
@quit-team="handleBack"
|
||||||
|
/>
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
<Tabs.TabPane tab="操作日志" key="4">
|
<Tabs.TabPane tab="操作日志" key="4">
|
||||||
<div>操作日志</div>
|
<div>操作日志</div>
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<script lang="ts" setup></script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>detail-info</div>
|
||||||
|
</template>
|
|
@ -1,7 +1,209 @@
|
||||||
<script lang="ts" setup></script>
|
<script setup lang="ts">
|
||||||
|
import type { CrmCustomerApi } from '#/api/crm/customer';
|
||||||
|
import type { SystemOperateLogApi } from '#/api/system/operate-log';
|
||||||
|
|
||||||
|
import { defineAsyncComponent, onMounted, ref } from 'vue';
|
||||||
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
import { Page } from '@vben/common-ui';
|
||||||
|
|
||||||
|
import { Button, Card, Modal, Tabs } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { getCustomer, updateCustomerDealStatus } from '#/api/crm/customer';
|
||||||
|
import { getOperateLogPage } from '#/api/crm/operateLog';
|
||||||
|
import { BizTypeEnum } from '#/api/crm/permission';
|
||||||
|
import { useDescription } from '#/components/description';
|
||||||
|
import { OperateLog } from '#/components/operate-log';
|
||||||
|
|
||||||
|
import { useDetailSchema } from '../data';
|
||||||
|
|
||||||
|
const CustomerDetailsInfo = defineAsyncComponent(
|
||||||
|
() => import('./detail-info.vue'),
|
||||||
|
);
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const customerId = ref(0);
|
||||||
|
|
||||||
|
const customer = ref<CrmCustomerApi.Customer>({} as CrmCustomerApi.Customer);
|
||||||
|
const permissionListRef = ref(); // 团队成员列表 Ref
|
||||||
|
|
||||||
|
const [Description] = useDescription({
|
||||||
|
componentProps: {
|
||||||
|
bordered: false,
|
||||||
|
column: 4,
|
||||||
|
class: 'mx-4',
|
||||||
|
},
|
||||||
|
schema: useDetailSchema(),
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 加载详情 */
|
||||||
|
async function loadCustomerDetail() {
|
||||||
|
loading.value = true;
|
||||||
|
customerId.value = Number(route.params.id);
|
||||||
|
const data = await getCustomer(customerId.value);
|
||||||
|
await getOperateLog();
|
||||||
|
customer.value = data;
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 编辑 */
|
||||||
|
function handleEdit() {
|
||||||
|
// formModalApi.setData({ id: clueId }).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 转移线索 */
|
||||||
|
function handleTransfer() {
|
||||||
|
// transferModalApi.setData({ id: clueId }).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 锁定客户 */
|
||||||
|
function handleLock() {
|
||||||
|
// transferModalApi.setData({ id: clueId }).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 解锁客户 */
|
||||||
|
function handleUnlock() {
|
||||||
|
// transferModalApi.setData({ id: clueId }).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 领取客户 */
|
||||||
|
function handleReceive() {
|
||||||
|
// transferModalApi.setData({ id: clueId }).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 分配客户 */
|
||||||
|
function handleDistributeForm() {
|
||||||
|
// transferModalApi.setData({ id: clueId }).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 客户放入公海 */
|
||||||
|
function handlePutPool() {
|
||||||
|
// transferModalApi.setData({ id: clueId }).open();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更新成交状态操作 */
|
||||||
|
async function handleUpdateDealStatus() {
|
||||||
|
const dealStatus = !customer.value.dealStatus;
|
||||||
|
try {
|
||||||
|
await Modal.confirm({
|
||||||
|
title: '提示',
|
||||||
|
content: `确定更新成交状态为【${dealStatus ? '已成交' : '未成交'}】吗?`,
|
||||||
|
});
|
||||||
|
await updateCustomerDealStatus(customerId.value, dealStatus);
|
||||||
|
Modal.success({
|
||||||
|
title: '成功',
|
||||||
|
content: '更新成交状态成功',
|
||||||
|
});
|
||||||
|
await loadCustomerDetail();
|
||||||
|
} catch {
|
||||||
|
// 用户取消操作
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取操作日志 */
|
||||||
|
const logList = ref<SystemOperateLogApi.OperateLog[]>([]); // 操作日志列表
|
||||||
|
async function getOperateLog() {
|
||||||
|
if (!customerId.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const data = await getOperateLogPage({
|
||||||
|
bizType: BizTypeEnum.CRM_CUSTOMER,
|
||||||
|
bizId: customerId.value,
|
||||||
|
});
|
||||||
|
logList.value = data.list;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载数据
|
||||||
|
onMounted(async () => {
|
||||||
|
await loadCustomerDetail();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<Page auto-content-height :title="customer?.name" :loading="loading">
|
||||||
<p>待完成</p>
|
<template #extra>
|
||||||
</div>
|
<div class="flex items-center gap-2">
|
||||||
|
<Button
|
||||||
|
v-if="permissionListRef?.validateWrite"
|
||||||
|
type="primary"
|
||||||
|
@click="handleEdit"
|
||||||
|
v-access:code="['crm:customer:update']"
|
||||||
|
>
|
||||||
|
{{ $t('ui.actionTitle.edit') }}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
v-if="permissionListRef?.validateOwnerUser"
|
||||||
|
type="primary"
|
||||||
|
@click="handleTransfer"
|
||||||
|
>
|
||||||
|
转移
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
v-if="permissionListRef?.validateWrite"
|
||||||
|
@click="handleUpdateDealStatus"
|
||||||
|
>
|
||||||
|
更改成交状态
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
v-if="customer.lockStatus && permissionListRef?.validateOwnerUser"
|
||||||
|
@click="handleUnlock"
|
||||||
|
>
|
||||||
|
解锁
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
v-if="!customer.lockStatus && permissionListRef?.validateOwnerUser"
|
||||||
|
@click="handleLock"
|
||||||
|
>
|
||||||
|
锁定
|
||||||
|
</Button>
|
||||||
|
<Button v-if="!customer.ownerUserId" @click="handleReceive">
|
||||||
|
领取
|
||||||
|
</Button>
|
||||||
|
<Button v-if="!customer.ownerUserId" @click="handleDistributeForm">
|
||||||
|
分配
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
v-if="customer.ownerUserId && permissionListRef?.validateOwnerUser"
|
||||||
|
@click="handlePutPool"
|
||||||
|
>
|
||||||
|
放入公海
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<Card>
|
||||||
|
<Description :data="customer" />
|
||||||
|
</Card>
|
||||||
|
<Card class="mt-4">
|
||||||
|
<Tabs>
|
||||||
|
<Tabs.TabPane tab="跟进记录" key="1">
|
||||||
|
<div>跟进记录</div>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane tab="基本信息" key="2">
|
||||||
|
<CustomerDetailsInfo />
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane tab="联系人" key="3">
|
||||||
|
<div>联系人</div>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane tab="团队成员" key="4">
|
||||||
|
<div>团队成员</div>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane tab="商机" key="5">
|
||||||
|
<div>商机</div>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane tab="合同" key="6">
|
||||||
|
<div>合同</div>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane tab="回款" key="7">
|
||||||
|
<div>回款</div>
|
||||||
|
</Tabs.TabPane>
|
||||||
|
<Tabs.TabPane tab="操作日志" key="8">
|
||||||
|
<OperateLog :log-list="logList" />
|
||||||
|
</Tabs.TabPane>
|
||||||
|
</Tabs>
|
||||||
|
</Card>
|
||||||
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -114,7 +114,8 @@ const [Modal, modalApi] = useVbenModal({
|
||||||
}
|
}
|
||||||
modalApi.lock();
|
modalApi.lock();
|
||||||
// 提交表单
|
// 提交表单
|
||||||
const data = (await formApi.getValues()) as CrmPermissionApi.Permission;
|
let data = (await formApi.getValues()) as CrmPermissionApi.Permission;
|
||||||
|
data = Object.assign(data, formData.value);
|
||||||
try {
|
try {
|
||||||
await (formData.value?.ids
|
await (formData.value?.ids
|
||||||
? updatePermission(data)
|
? updatePermission(data)
|
||||||
|
|
|
@ -33,6 +33,8 @@ const emits = defineEmits<{
|
||||||
(e: 'quitTeam'): void;
|
(e: 'quitTeam'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
|
const gridData = ref<CrmPermissionApi.Permission[]>([]);
|
||||||
|
|
||||||
const [FormModal, formModalApi] = useVbenModal({
|
const [FormModal, formModalApi] = useVbenModal({
|
||||||
connectedComponent: Form,
|
connectedComponent: Form,
|
||||||
destroyOnClose: true,
|
destroyOnClose: true,
|
||||||
|
@ -67,6 +69,14 @@ function handleCreate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleEdit() {
|
function handleEdit() {
|
||||||
|
if (checkedIds.value.length === 0) {
|
||||||
|
message.error('请先选择团队成员后操作!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (checkedIds.value.length > 1) {
|
||||||
|
message.error('只能选择一个团队成员进行编辑!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
formModalApi
|
formModalApi
|
||||||
.setData({
|
.setData({
|
||||||
bizType: props.bizType,
|
bizType: props.bizType,
|
||||||
|
@ -112,7 +122,7 @@ async function handleQuit() {
|
||||||
.getData()
|
.getData()
|
||||||
.find(
|
.find(
|
||||||
(item) =>
|
(item) =>
|
||||||
item.id === userStore.userInfo?.userId &&
|
item.id === userStore.userInfo?.id &&
|
||||||
item.level === PermissionLevelEnum.OWNER,
|
item.level === PermissionLevelEnum.OWNER,
|
||||||
);
|
);
|
||||||
if (permission) {
|
if (permission) {
|
||||||
|
@ -122,7 +132,7 @@ async function handleQuit() {
|
||||||
|
|
||||||
const userPermission = gridApi.grid
|
const userPermission = gridApi.grid
|
||||||
.getData()
|
.getData()
|
||||||
.find((item) => item.id === userStore.userInfo?.userId);
|
.find((item) => item.id === userStore.userInfo?.id);
|
||||||
if (!userPermission) {
|
if (!userPermission) {
|
||||||
message.warning('你不是团队成员!');
|
message.warning('你不是团队成员!');
|
||||||
return;
|
return;
|
||||||
|
@ -176,6 +186,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
bizId: props.bizId,
|
bizId: props.bizId,
|
||||||
bizType: props.bizType,
|
bizType: props.bizType,
|
||||||
});
|
});
|
||||||
|
gridData.value = res;
|
||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -201,19 +212,19 @@ defineExpose({
|
||||||
validateWrite,
|
validateWrite,
|
||||||
isPool,
|
isPool,
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => gridApi.grid.getData(),
|
() => gridData.value,
|
||||||
(data) => {
|
(data) => {
|
||||||
isPool.value = false;
|
isPool.value = false;
|
||||||
if (data.length > 0) {
|
if (data.length > 0) {
|
||||||
isPool.value = gridApi.grid
|
isPool.value = data.some(
|
||||||
.getData()
|
(item) => item.level === PermissionLevelEnum.OWNER,
|
||||||
.some((item) => item.level === PermissionLevelEnum.OWNER);
|
);
|
||||||
validateOwnerUser.value = false;
|
validateOwnerUser.value = false;
|
||||||
validateWrite.value = false;
|
validateWrite.value = false;
|
||||||
const userId = userStore.userInfo?.userId;
|
const userId = userStore.userInfo?.id;
|
||||||
gridApi.grid
|
gridData.value
|
||||||
.getData()
|
|
||||||
.filter((item) => item.userId === userId)
|
.filter((item) => item.userId === userId)
|
||||||
.forEach((item) => {
|
.forEach((item) => {
|
||||||
if (item.level === PermissionLevelEnum.OWNER) {
|
if (item.level === PermissionLevelEnum.OWNER) {
|
||||||
|
|
Loading…
Reference in New Issue