409 lines
11 KiB
Vue
409 lines
11 KiB
Vue
<template>
|
||
<view class="add-customer-page">
|
||
<!-- 自定义导航栏 -->
|
||
<CustomerFormNavbar title="客户信息" @cancel="handleCancel" />
|
||
|
||
<!-- 内容区域 -->
|
||
<scroll-view class="content-scroll" scroll-y>
|
||
<view class="scroll-content">
|
||
<!-- 客户信息部分 -->
|
||
<CustomerBasicInfo
|
||
:form-data="formData"
|
||
:customer-type-options="customerTypeOptions"
|
||
:intent-level-options="intentLevelOptions"
|
||
:customer-status-options="customerStatusOptions"
|
||
:lock-customer-type="true"
|
||
@update:form-data="formData = $event"
|
||
@open-picker="handleOpenPicker"
|
||
/>
|
||
|
||
<!-- 其他信息部分 -->
|
||
<CustomerOtherInfo
|
||
:form-data="formData"
|
||
@update:form-data="formData = $event"
|
||
@open-picker="handleOpenPicker"
|
||
/>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 保存按钮 -->
|
||
<view class="save-button-wrapper">
|
||
<button class="save-button" @click="handleSave" :disabled="saving">保存</button>
|
||
</view>
|
||
|
||
<!-- 选择器组件 -->
|
||
<CustomerPickers
|
||
:show-customer-type-picker="showCustomerTypePicker"
|
||
:show-source-picker="showSourcePicker"
|
||
:show-intent-picker="showIntentPicker"
|
||
:show-intent-level-picker="showIntentLevelPicker"
|
||
:show-customer-status-picker="showCustomerStatusPicker"
|
||
:show-work-wechat-picker="showWorkWechatPicker"
|
||
:show-next-follow-time-picker="showNextFollowTimePicker"
|
||
:show-follow-user-picker="showFollowUserPicker"
|
||
:customer-type-options="customerTypeOptions"
|
||
:source-options="sourceOptions"
|
||
:intent-options="intentOptions"
|
||
:intent-level-options="intentLevelOptions"
|
||
:customer-status-options="customerStatusOptions"
|
||
:work-wechat-options="workWechatOptions"
|
||
:follow-user-options="followUserOptions"
|
||
:address-list="addressList"
|
||
:region-loading="regionLoading"
|
||
:form-data="formData"
|
||
ref="pickersRef"
|
||
@update:form-data="formData = $event"
|
||
@close-picker="handleClosePicker"
|
||
@region-confirm="onRegionConfirm"
|
||
@region-change="onRegionChange"
|
||
/>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, onMounted } from 'vue';
|
||
import { createCustomer, getUserListAll } from '@/api';
|
||
import { useUserStore } from '@/store/user';
|
||
import { useCustomerForm } from '@/composables/useCustomerForm';
|
||
import CustomerFormNavbar from '@/components/customer/customer-form/CustomerFormNavbar.vue';
|
||
import CustomerBasicInfo from '@/components/customer/customer-form/CustomerBasicInfo.vue';
|
||
import CustomerOtherInfo from '@/components/customer/customer-form/CustomerOtherInfo.vue';
|
||
import CustomerPickers from '@/components/customer/customer-form/CustomerPickers.vue';
|
||
|
||
// 使用共享逻辑
|
||
const {
|
||
customerTypeOptions,
|
||
sourceOptions,
|
||
intentOptions,
|
||
intentLevelOptions,
|
||
customerStatusOptions,
|
||
workWechatOptions,
|
||
addressList,
|
||
regionLoading,
|
||
loadDictData,
|
||
loadWechatList,
|
||
loadRegionTree,
|
||
handleRegionChange,
|
||
handleRegionConfirm,
|
||
openRegionPicker
|
||
} = useCustomerForm();
|
||
|
||
// 表单数据
|
||
const formData = ref({
|
||
customerType: '2',
|
||
name: '',
|
||
mobile: '',
|
||
wechat: '',
|
||
source: '',
|
||
intents: [],
|
||
intentLevel: '',
|
||
customerStatus: '',
|
||
region: '',
|
||
regionIds: [],
|
||
workWechat: '',
|
||
workWechatId: null,
|
||
remark: '',
|
||
concern: '',
|
||
pain: '',
|
||
attention: '',
|
||
demand: '',
|
||
nextFollowTime: '',
|
||
followId: null,
|
||
followName: ''
|
||
});
|
||
|
||
// 显示状态
|
||
const saving = ref(false);
|
||
const showCustomerTypePicker = ref(false);
|
||
const showSourcePicker = ref(false);
|
||
const showIntentPicker = ref(false);
|
||
const showIntentLevelPicker = ref(false);
|
||
const showCustomerStatusPicker = ref(false);
|
||
const showWorkWechatPicker = ref(false);
|
||
const showNextFollowTimePicker = ref(false);
|
||
const showFollowUserPicker = ref(false);
|
||
|
||
// 用户列表
|
||
const followUserOptions = ref([]);
|
||
|
||
const pickersRef = ref(null);
|
||
|
||
// 打开选择器
|
||
const handleOpenPicker = (pickerType) => {
|
||
switch (pickerType) {
|
||
case 'customerType':
|
||
showCustomerTypePicker.value = true;
|
||
break;
|
||
case 'source':
|
||
showSourcePicker.value = true;
|
||
break;
|
||
case 'intent':
|
||
showIntentPicker.value = true;
|
||
break;
|
||
case 'intentLevel':
|
||
showIntentLevelPicker.value = true;
|
||
break;
|
||
case 'customerStatus':
|
||
showCustomerStatusPicker.value = true;
|
||
break;
|
||
case 'region':
|
||
openRegionPicker(formData.value, pickersRef.value);
|
||
break;
|
||
case 'workWechat':
|
||
showWorkWechatPicker.value = true;
|
||
break;
|
||
case 'nextFollowTime':
|
||
showNextFollowTimePicker.value = true;
|
||
break;
|
||
case 'followUser':
|
||
showFollowUserPicker.value = true;
|
||
break;
|
||
}
|
||
};
|
||
|
||
// 关闭选择器
|
||
const handleClosePicker = (pickerType) => {
|
||
switch (pickerType) {
|
||
case 'customerType':
|
||
showCustomerTypePicker.value = false;
|
||
break;
|
||
case 'source':
|
||
showSourcePicker.value = false;
|
||
break;
|
||
case 'intent':
|
||
showIntentPicker.value = false;
|
||
break;
|
||
case 'intentLevel':
|
||
showIntentLevelPicker.value = false;
|
||
break;
|
||
case 'customerStatus':
|
||
showCustomerStatusPicker.value = false;
|
||
break;
|
||
case 'workWechat':
|
||
showWorkWechatPicker.value = false;
|
||
break;
|
||
case 'nextFollowTime':
|
||
showNextFollowTimePicker.value = false;
|
||
break;
|
||
case 'followUser':
|
||
showFollowUserPicker.value = false;
|
||
break;
|
||
}
|
||
};
|
||
|
||
// uv-picker 的 change 事件处理(实现三级联动)
|
||
const onRegionChange = (e) => {
|
||
handleRegionChange(e, pickersRef.value);
|
||
};
|
||
|
||
// uv-picker 的 confirm 事件处理
|
||
const onRegionConfirm = (e) => {
|
||
handleRegionConfirm(e, formData.value);
|
||
};
|
||
|
||
// 取消
|
||
const handleCancel = () => {
|
||
uni.navigateBack();
|
||
};
|
||
|
||
// 加载用户列表
|
||
const loadUserList = async () => {
|
||
try {
|
||
const res = await getUserListAll();
|
||
if (res && res.data && Array.isArray(res.data)) {
|
||
followUserOptions.value = res.data;
|
||
} else if (res && Array.isArray(res)) {
|
||
followUserOptions.value = res;
|
||
} else {
|
||
followUserOptions.value = [];
|
||
}
|
||
} catch (error) {
|
||
console.error('加载用户列表失败:', error);
|
||
followUserOptions.value = [];
|
||
}
|
||
};
|
||
|
||
// 组件挂载时加载数据并设置默认值
|
||
onMounted(async () => {
|
||
await Promise.all([
|
||
loadRegionTree(),
|
||
loadDictData(),
|
||
loadWechatList(),
|
||
loadUserList()
|
||
]);
|
||
|
||
// 设置默认值:意向=电动车(按label),强度=中(按value),来源=抖音(按label),状态=意向(按value)
|
||
try {
|
||
// 客户意向(多选,组件使用的是 label)
|
||
const defaultIntentLabel = '电动车';
|
||
if (!formData.value.intents || formData.value.intents.length === 0) {
|
||
const existsIntent = intentOptions.value.some(opt => opt.label === defaultIntentLabel);
|
||
if (existsIntent) {
|
||
formData.value.intents = [defaultIntentLabel];
|
||
}
|
||
}
|
||
|
||
// 意向强度(组件使用的是 value)
|
||
const defaultIntentLevelLabel = '中';
|
||
if (!formData.value.intentLevel) {
|
||
const level = intentLevelOptions.value.find(opt => opt.label === defaultIntentLevelLabel);
|
||
if (level) {
|
||
formData.value.intentLevel = level.value;
|
||
}
|
||
}
|
||
|
||
// 客户来源(组件使用的是 label)
|
||
const defaultSourceLabel = '抖音';
|
||
if (!formData.value.source) {
|
||
const existsSource = sourceOptions.value.some(opt => opt.label === defaultSourceLabel);
|
||
if (existsSource) {
|
||
formData.value.source = defaultSourceLabel;
|
||
}
|
||
}
|
||
|
||
// 客户状态(组件使用的是 value)
|
||
const defaultStatusLabel = '高意向';
|
||
if (!formData.value.customerStatus) {
|
||
const status = customerStatusOptions.value.find(opt => opt.label === defaultStatusLabel);
|
||
if (status) {
|
||
formData.value.customerStatus = status.value;
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.warn('设置默认字典值失败:', e);
|
||
}
|
||
});
|
||
|
||
// 保存
|
||
const handleSave = async () => {
|
||
if (!formData.value.name || formData.value.name.trim() === '') {
|
||
uni.showToast({
|
||
title: '请输入客户名称',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (!formData.value.mobile || formData.value.mobile.trim() === '') {
|
||
uni.showToast({
|
||
title: '请输入联系电话',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
saving.value = true;
|
||
try {
|
||
const now = new Date();
|
||
const formatDateTime = (date) => {
|
||
const year = date.getFullYear();
|
||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||
const day = String(date.getDate()).padStart(2, '0');
|
||
const hours = String(date.getHours()).padStart(2, '0');
|
||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||
};
|
||
|
||
const intentsArray = Array.isArray(formData.value.intents) ? formData.value.intents : [];
|
||
const regionIdsArray = formData.value.regionIds || [];
|
||
|
||
// 使用选中的跟进人ID,如果没有选择则使用当前用户ID
|
||
const userStore = useUserStore();
|
||
const defaultUserId = userStore.userInfo?.id || userStore.userInfo?.userId || '1';
|
||
const followId = formData.value.followId || defaultUserId;
|
||
|
||
const submitData = {
|
||
id: null,
|
||
code: null,
|
||
name: formData.value.name.trim(),
|
||
status: null,
|
||
intentLevel: null,
|
||
mobile: formData.value.mobile.trim(),
|
||
wechat: formData.value.wechat.trim() || null,
|
||
source: formData.value.source || null,
|
||
intents: intentsArray,
|
||
followId: followId,
|
||
remark: formData.value.remark.trim() || null,
|
||
type: '2',
|
||
workWechatId: formData.value.workWechatId || null,
|
||
regionIds: regionIdsArray,
|
||
attention: formData.value.attention.trim() || null,
|
||
concern: formData.value.concern.trim() || null,
|
||
demand: formData.value.demand.trim() || null,
|
||
pain: formData.value.pain.trim() || null,
|
||
follow: {
|
||
followTime: formatDateTime(now),
|
||
nextFollowTime: formData.value.nextFollowTime || null,
|
||
customerIntentLevel: formData.value.intentLevel || null,
|
||
customerStatus: formData.value.customerStatus || null
|
||
},
|
||
nextFollowTime: formData.value.nextFollowTime || null,
|
||
customerIntentLevel: formData.value.intentLevel || null,
|
||
customerStatus: formData.value.customerStatus || null
|
||
};
|
||
|
||
await createCustomer(submitData);
|
||
|
||
uni.showToast({
|
||
title: '创建成功',
|
||
icon: 'success'
|
||
});
|
||
} catch (error) {
|
||
console.error('创建客户失败:', error);
|
||
uni.showToast({
|
||
title: error.message || '创建失败,请重试',
|
||
icon: 'none'
|
||
});
|
||
} finally {
|
||
saving.value = false;
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.add-customer-page {
|
||
display: flex;
|
||
flex-direction: column;
|
||
|
||
background-color: #f5f5f5;
|
||
}
|
||
|
||
.content-scroll {
|
||
flex: 1;
|
||
}
|
||
|
||
.scroll-content {
|
||
padding: 16px;
|
||
padding-bottom: 80px;
|
||
}
|
||
|
||
.save-button-wrapper {
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
padding: 12px 16px;
|
||
padding-bottom: calc(12px + env(safe-area-inset-bottom));
|
||
background-color: #fff;
|
||
border-top: 1px solid #eee;
|
||
z-index: 100;
|
||
}
|
||
|
||
.save-button {
|
||
width: 100%;
|
||
height: 44px;
|
||
background-color: #1976d2;
|
||
color: #fff;
|
||
font-size: 16px;
|
||
font-weight: 600;
|
||
border-radius: 6px;
|
||
border: none;
|
||
|
||
&:disabled {
|
||
background-color: #ccc;
|
||
opacity: 0.6;
|
||
}
|
||
}
|
||
</style>
|