CRM: 跟进组件完善

pull/366/head
puhui999 2024-01-20 18:56:24 +08:00
parent f88b26e3c3
commit 9628517b8b
7 changed files with 183 additions and 92 deletions

View File

@ -31,7 +31,6 @@
/>
</el-form-item>
</el-col>
<!-- TODO @puhui999不搞富文本哈然后加个附件图片两个 form-item -->
<el-col :span="24">
<el-form-item label="跟进内容" prop="content">
<el-input v-model="formData.content" :rows="3" type="textarea" />
@ -72,13 +71,13 @@
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
<ContactTableSelect ref="contactTableSelectRef" v-model="formData.contactIds" />
<BusinessTableSelect ref="businessTableSelectRef" v-model="formData.businessIds" />
</template>
<script lang="ts" setup>
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { FollowUpRecordApi, FollowUpRecordVO } from '@/api/crm/followup'
import { BusinessList, ContactList } from './components'
import * as ContactApi from '@/api/crm/contact'
import * as BusinessApi from '@/api/crm/business'
import { BusinessList, BusinessTableSelect, ContactList, ContactTableSelect } from './components'
defineOptions({ name: 'FollowUpRecordForm' })
@ -97,8 +96,6 @@ const formRules = reactive({
})
const formRef = ref() // Ref
const allContactList = ref<ContactApi.ContactVO[]>([]) //
const allBusinessList = ref<BusinessApi.BusinessVO[]>([]) //
/** 打开弹窗 */
const open = async (bizType: number, bizId: number, type: string, id?: number) => {
@ -108,8 +105,6 @@ const open = async (bizType: number, bizId: number, type: string, id?: number) =
resetForm()
formData.value.bizType = bizType
formData.value.bizId = bizId
allContactList.value = await ContactApi.getSimpleContactList()
allBusinessList.value = await BusinessApi.getSimpleBusinessList()
//
if (id) {
formLoading.value = true
@ -146,8 +141,14 @@ const submitForm = async () => {
}
}
const handleAddContact = () => {}
const handleAddBusiness = () => {}
const contactTableSelectRef = ref<InstanceType<typeof ContactTableSelect>>()
const handleAddContact = () => {
contactTableSelectRef.value?.open()
}
const businessTableSelectRef = ref<InstanceType<typeof BusinessTableSelect>>()
const handleAddBusiness = () => {
businessTableSelectRef.value?.open()
}
/** 重置表单 */
const resetForm = () => {
formRef.value?.resetFields()

View File

@ -52,7 +52,7 @@ watch(
if (!val || val.length === 0) {
return
}
list.value = BusinessApi.getBusinessListByIds(val) as unknown as BusinessApi.BusinessVO[]
list.value = BusinessApi.getBusinessListByIds(unref(val)) as unknown as BusinessApi.BusinessVO[]
}
)
const emits = defineEmits<{

View File

@ -1,79 +0,0 @@
<template>
<Dialog v-model="dialogVisible" :title="dialogTitle" width="50%">
<el-row>
<el-col :span="12">
<el-form-item label="跟进类型" prop="type">
<el-select v-model="formData.type" placeholder="请选择跟进类型">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.CRM_FOLLOW_UP_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="下次联系时间" prop="nextTime">
<el-date-picker
v-model="formData.nextTime"
placeholder="选择下次联系时间"
type="date"
value-format="x"
/>
</el-form-item>
</el-col>
</el-row>
<template #footer>
<el-button :disabled="formLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
/** 跟进记录 表单 */
defineOptions({ name: 'BusinessListSelectForm' })
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formData = ref([])
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
//
if (id) {
formLoading.value = true
try {
formData.value = await FollowUpRecordApi.getFollowUpRecord(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
await formRef.value.validate()
//
formLoading.value = true
try {
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,84 @@
<template>
<Dialog v-model="dialogVisible" :appendToBody="true" title="选择商机" width="700">
<el-table
ref="multipleTableRef"
v-loading="loading"
:data="list"
:show-overflow-tooltip="true"
:stripe="true"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" />
<el-table-column align="center" label="商机名称" prop="name" />
<el-table-column align="center" label="客户名称" prop="customerName" />
<el-table-column align="center" label="商机金额" prop="price" />
<el-table-column
:formatter="dateFormatter"
align="center"
label="预计成交日期"
prop="dealTime"
width="180px"
/>
<el-table-column align="center" label="备注" prop="remark" />
</el-table>
<template #footer>
<el-button :disabled="formLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import * as BusinessApi from '@/api/crm/business'
import { dateFormatter } from '@/utils/formatTime'
import { ElTable } from 'element-plus'
defineOptions({ name: 'BusinessTableSelect' })
withDefaults(defineProps<{ modelValue: number[] }>(), { modelValue: () => [] })
const list = ref<BusinessApi.BusinessVO[]>([]) //
const loading = ref(false) //
const dialogVisible = ref(false) //
const formLoading = ref(false)
//
const emits = defineEmits<{
(e: 'update:modelValue', v: number[]): void
}>()
const multipleTableRef = ref<InstanceType<typeof ElTable>>()
const multipleSelection = ref<BusinessApi.BusinessVO[]>([])
const handleSelectionChange = (val: BusinessApi.BusinessVO[]) => {
multipleSelection.value = val
}
/** 触发 */
const submitForm = () => {
formLoading.value = true
try {
emits(
'update:modelValue',
multipleSelection.value.map((item) => item.id)
)
} finally {
formLoading.value = false
//
dialogVisible.value = false
}
}
const getList = async () => {
loading.value = true
try {
list.value = await BusinessApi.getSimpleBusinessList()
} finally {
loading.value = false
}
}
/** 打开弹窗 */
const open = async () => {
dialogVisible.value = true
await nextTick()
if (multipleSelection.value.length > 0) {
multipleTableRef.value!.clearSelection()
}
await getList()
}
defineExpose({ open }) // open
</script>

View File

@ -69,7 +69,7 @@ const props = withDefaults(defineProps<{ contactIds: number[] }>(), {
const list = ref<ContactApi.ContactVO[]>([] as ContactApi.ContactVO[])
const getContactList = async () => {
list.value = (await ContactApi.getContactListByIds(
props.contactIds
unref(props.contactIds)
)) as unknown as ContactApi.ContactVO[]
}
watch(

View File

@ -0,0 +1,83 @@
<template>
<Dialog v-model="dialogVisible" :appendToBody="true" title="选择联系人" width="700">
<el-table
ref="multipleTableRef"
v-loading="loading"
:data="list"
:show-overflow-tooltip="true"
:stripe="true"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" />
<el-table-column align="center" fixed="left" label="姓名" prop="name" width="140" />
<el-table-column
align="center"
fixed="left"
label="客户名称"
prop="customerName"
width="120"
/>
<el-table-column align="center" label="手机" prop="mobile" width="120" />
<el-table-column align="center" label="电话" prop="telephone" width="120" />
<el-table-column align="center" label="邮箱" prop="email" width="120" />
<el-table-column align="center" label="职位" prop="post" width="120" />
</el-table>
<template #footer>
<el-button :disabled="formLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import * as ContactApi from '@/api/crm/contact'
import { ElTable } from 'element-plus'
defineOptions({ name: 'ContactTableSelect' })
withDefaults(defineProps<{ modelValue: number[] }>(), { modelValue: () => [] })
const list = ref<ContactApi.ContactVO[]>([]) //
const loading = ref(false) //
const dialogVisible = ref(false) //
const formLoading = ref(false)
//
const emits = defineEmits<{
(e: 'update:modelValue', v: number[]): void
}>()
const multipleTableRef = ref<InstanceType<typeof ElTable>>()
const multipleSelection = ref<ContactApi.ContactVO[]>([])
const handleSelectionChange = (val: ContactApi.ContactVO[]) => {
multipleSelection.value = val
}
/** 触发 */
const submitForm = () => {
formLoading.value = true
try {
emits(
'update:modelValue',
multipleSelection.value.map((item) => item.id)
)
} finally {
formLoading.value = false
//
dialogVisible.value = false
}
}
const getList = async () => {
loading.value = true
try {
list.value = await ContactApi.getSimpleContactList()
} finally {
loading.value = false
}
}
/** 打开弹窗 */
const open = async () => {
dialogVisible.value = true
await nextTick()
if (multipleSelection.value.length > 0) {
multipleTableRef.value!.clearSelection()
}
await getList()
}
defineExpose({ open }) // open
</script>

View File

@ -1,4 +1,6 @@
import BusinessList from './BusinessList.vue'
import BusinessTableSelect from './BusinessTableSelect.vue'
import ContactList from './ContactList.vue'
import ContactTableSelect from './ContactTableSelect.vue'
export { BusinessList, ContactList }
export { BusinessList, BusinessTableSelect, ContactList, ContactTableSelect }