CRM 客户管理
parent
293dd72420
commit
d9fe53ca5b
2
.env.dev
2
.env.dev
|
|
@ -4,7 +4,7 @@ NODE_ENV=production
|
||||||
VITE_DEV=true
|
VITE_DEV=true
|
||||||
|
|
||||||
# 请求路径
|
# 请求路径
|
||||||
VITE_BASE_URL='http://192.168.6.122:48080'
|
VITE_BASE_URL='http://www.sujieguanli.top:48080'
|
||||||
|
|
||||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
||||||
VITE_UPLOAD_TYPE=client
|
VITE_UPLOAD_TYPE=client
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ NODE_ENV=development
|
||||||
VITE_DEV=true
|
VITE_DEV=true
|
||||||
|
|
||||||
# 请求路径
|
# 请求路径
|
||||||
VITE_BASE_URL='http://www.woyaoshouchong.asia:48080'
|
VITE_BASE_URL='http://www.sujieguanli.top:48080'
|
||||||
|
|
||||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
|
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
|
||||||
VITE_UPLOAD_TYPE=client
|
VITE_UPLOAD_TYPE=client
|
||||||
|
|
|
||||||
|
|
@ -144,8 +144,7 @@ const formData = ref({
|
||||||
})
|
})
|
||||||
const formRules = reactive({
|
const formRules = reactive({
|
||||||
name: [{ required: true, message: '姓名不能为空', trigger: 'blur' }],
|
name: [{ required: true, message: '姓名不能为空', trigger: 'blur' }],
|
||||||
customerId: [{ required: true, message: '客户不能为空', trigger: 'blur' }],
|
customerId: [{ required: true, message: '客户不能为空', trigger: 'blur' }]
|
||||||
ownerUserId: [{ required: true, message: '负责人不能为空', trigger: 'blur' }]
|
|
||||||
})
|
})
|
||||||
const formRef = ref() // 表单 Ref
|
const formRef = ref() // 表单 Ref
|
||||||
const userOptions = ref<UserApi.UserVO[]>([]) // 用户列表
|
const userOptions = ref<UserApi.UserVO[]>([]) // 用户列表
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,10 @@ const message = useMessage()
|
||||||
const contractId = ref(0) // 编号
|
const contractId = ref(0) // 编号
|
||||||
const loading = ref(true) // 加载中
|
const loading = ref(true) // 加载中
|
||||||
const contract = ref<ContractApi.ContractVO>({} as ContractApi.ContractVO) // 详情
|
const contract = ref<ContractApi.ContractVO>({} as ContractApi.ContractVO) // 详情
|
||||||
const permissionListRef = ref<InstanceType<typeof PermissionList>>() // 团队成员列表 Ref
|
// 初始化
|
||||||
|
const permissionListRef = ref<InstanceType<typeof PermissionList>>(
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
/** 编辑 */
|
/** 编辑 */
|
||||||
const formRef = ref()
|
const formRef = ref()
|
||||||
|
|
|
||||||
|
|
@ -20,20 +20,22 @@
|
||||||
<el-descriptions-item label="成交状态:">
|
<el-descriptions-item label="成交状态:">
|
||||||
<dict-tag :type="DICT_TYPE.CRM_CUSTOMER_DEAL_STATUS" :value="customer.dealStatus" />
|
<dict-tag :type="DICT_TYPE.CRM_CUSTOMER_DEAL_STATUS" :value="customer.dealStatus" />
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item label="客户类别:">
|
||||||
|
<dict-tag :type="DICT_TYPE.CRM_CUSTOMER_INDUSTRY" :value="customer.industryId" />
|
||||||
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="负责人:">{{ customer.ownerUserName }}</el-descriptions-item>
|
<el-descriptions-item label="负责人:">{{ customer.ownerUserName }}</el-descriptions-item>
|
||||||
|
|
||||||
|
<el-descriptions-item label="下次联系时间:">
|
||||||
|
{{ formatDate(customer.contactNextTime, 'YYYY-MM-DD') }}
|
||||||
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="创建时间:">
|
<el-descriptions-item label="创建时间:">
|
||||||
{{ formatDate(customer.createTime) }}
|
{{ formatDate(customer.createTime) }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="地址:">
|
<el-descriptions-item label="地址:">
|
||||||
{{ customer.areaName }} {{ customer.detailAddress }}
|
{{ customer.areaName }} {{ customer.detailAddress }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="客户类别:">
|
|
||||||
<dict-tag :type="DICT_TYPE.CRM_CUSTOMER_INDUSTRY" :value="customer.industryId" />
|
<!-- <el-descriptions-item label="备注:">{{ customer.remark }}</el-descriptions-item> -->
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="下次联系时间:">
|
|
||||||
{{ formatDate(customer.contactNextTime, 'YYYY-MM-DD') }}
|
|
||||||
</el-descriptions-item>
|
|
||||||
<el-descriptions-item label="备注:">{{ customer.remark }}</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@
|
||||||
<ContractList :biz-id="customer.id!" :biz-type="BizTypeEnum.CRM_CUSTOMER" />
|
<ContractList :biz-id="customer.id!" :biz-type="BizTypeEnum.CRM_CUSTOMER" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
<el-tab-pane label="附件">
|
<el-tab-pane v-hasPermi="['crm:customer:file:query']" label="附件">
|
||||||
<FileList v-if="customerId" :customerId="customerId" />
|
<FileList v-if="customerId" :customerId="customerId" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="操作日志">
|
<el-tab-pane label="操作日志">
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,15 @@
|
||||||
<span style="margin: 0 8px;"> </span>
|
<span style="margin: 0 8px;"> </span>
|
||||||
</template>
|
</template>
|
||||||
<span class="meta-label">跟进方式:</span><dict-tag :type="DICT_TYPE.CRM_FOLLOW_UP_TYPE" :value="item.type" class="mr-10px" />
|
<span class="meta-label">跟进方式:</span><dict-tag :type="DICT_TYPE.CRM_FOLLOW_UP_TYPE" :value="item.type" class="mr-10px" />
|
||||||
|
</div>
|
||||||
|
<!-- 操作按钮统一放右上角 -->
|
||||||
|
<div class="followup-action-btns">
|
||||||
|
<el-button link class="followup-action-btn edit" @click="openForm('update', item.id)">
|
||||||
|
<Icon icon="ep:edit" class="mr-3px" /> 编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button link class="followup-action-btn delete" @click="handleDelete(item.id)">
|
||||||
|
<Icon icon="ep:delete" class="mr-3px" /> 删除
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<span class="follow-row" v-if="!/<[a-z][\s\S]*>/i.test(item.content)">跟进内容:{{ item.content }}</span>
|
<span class="follow-row" v-if="!/<[a-z][\s\S]*>/i.test(item.content)">跟进内容:{{ item.content }}</span>
|
||||||
<div class="follow-row" v-else v-html="'跟进内容:' + item.content"></div>
|
<div class="follow-row" v-else v-html="'跟进内容:' + item.content"></div>
|
||||||
|
|
@ -66,12 +74,6 @@
|
||||||
</el-link>
|
</el-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-button link type="primary" class="mr-10px followup-edit-btn" @click="openForm('update', item.id)">
|
|
||||||
<Icon icon="ep:edit" class="mr-3px" /> 编辑
|
|
||||||
</el-button>
|
|
||||||
<el-button link type="danger" class="mr-20px followup-delete-btn" @click="handleDelete(item.id)">
|
|
||||||
<Icon icon="ep:delete" class="mr-3px" /> 删除
|
|
||||||
</el-button>
|
|
||||||
<template #dot>
|
<template #dot>
|
||||||
<span style="background-color: #67C23A;" class="dot-node-style">
|
<span style="background-color: #67C23A;" class="dot-node-style">
|
||||||
{{ item.creatorName ? item.creatorName[0] : '' }}
|
{{ item.creatorName ? item.creatorName[0] : '' }}
|
||||||
|
|
@ -238,7 +240,7 @@ watch(
|
||||||
}
|
}
|
||||||
.dot-node-style {
|
.dot-node-style {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -5px;
|
left: 0px;
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
|
@ -272,23 +274,41 @@ watch(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.followup-update-btn {
|
.followup-action-btns {
|
||||||
color: #7492f3 !important;
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 16px;
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
.followup-action-btn {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
transition: background 0.2s, color 0.2s;
|
|
||||||
border: none;
|
border: none;
|
||||||
background: #fef0f0;
|
background: transparent;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 2px 10px;
|
padding: 2px 10px;
|
||||||
margin: 10px 0 0 0;
|
transition: background 0.2s, color 0.2s;
|
||||||
|
box-shadow: none;
|
||||||
|
&.edit {
|
||||||
|
color: #409eff !important;
|
||||||
|
&:hover {
|
||||||
|
color: #337ecc !important;
|
||||||
|
background: #ecf5ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.delete {
|
||||||
|
color: #f56c6c !important;
|
||||||
&:hover {
|
&:hover {
|
||||||
background: #fef0f0;
|
|
||||||
color: #c0392b !important;
|
color: #c0392b !important;
|
||||||
|
background: #fef0f0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.icon {
|
.icon {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,7 @@ const formData = ref({
|
||||||
estimatedPiles: 0,
|
estimatedPiles: 0,
|
||||||
siteStatus: undefined,
|
siteStatus: undefined,
|
||||||
siteType: undefined,
|
siteType: undefined,
|
||||||
|
ownerUserId: 0,
|
||||||
ownerId: undefined,
|
ownerId: undefined,
|
||||||
managementId: undefined,
|
managementId: undefined,
|
||||||
recommenderName: undefined,
|
recommenderName: undefined,
|
||||||
|
|
@ -212,6 +213,10 @@ const open = async (type: string, id?: number) => {
|
||||||
formLoading.value = false
|
formLoading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 默认新建时选中自己
|
||||||
|
if (formType.value === 'create') {
|
||||||
|
formData.value.ownerUserId = useUserStore().getUser.id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue