420 lines
12 KiB
Vue
420 lines
12 KiB
Vue
<template>
|
|
<view class="edit-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"
|
|
@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"
|
|
:customer-type-options="customerTypeOptions"
|
|
:source-options="sourceOptions"
|
|
:intent-options="intentOptions"
|
|
:intent-level-options="intentLevelOptions"
|
|
:customer-status-options="customerStatusOptions"
|
|
:work-wechat-options="workWechatOptions"
|
|
: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, nextTick } from 'vue';
|
|
import { onLoad } from '@dcloudio/uni-app';
|
|
import { updateCustomer, getCustomerDetail } from '@/common/api';
|
|
import { useUserStore } from '@/store/user';
|
|
import { useCustomerForm } from '@/composables/useCustomerForm';
|
|
import CustomerFormNavbar from '@/components/customer-form/CustomerFormNavbar.vue';
|
|
import CustomerBasicInfo from '@/components/customer-form/CustomerBasicInfo.vue';
|
|
import CustomerOtherInfo from '@/components/customer-form/CustomerOtherInfo.vue';
|
|
import CustomerPickers from '@/components/customer-form/CustomerPickers.vue';
|
|
|
|
// 使用共享逻辑
|
|
const {
|
|
customerTypeOptions,
|
|
sourceOptions,
|
|
intentOptions,
|
|
intentLevelOptions,
|
|
customerStatusOptions,
|
|
workWechatOptions,
|
|
addressList,
|
|
regionLoading,
|
|
loadDictData,
|
|
loadWechatList,
|
|
loadRegionTree,
|
|
handlePickValueDefault,
|
|
handleRegionChange,
|
|
handleRegionConfirm,
|
|
openRegionPicker
|
|
} = useCustomerForm();
|
|
|
|
// 客户ID
|
|
const customerId = ref('');
|
|
|
|
// 表单数据
|
|
const formData = ref({
|
|
id: null,
|
|
customerType: '',
|
|
name: '',
|
|
mobile: '',
|
|
wechat: '',
|
|
source: '',
|
|
intents: [],
|
|
intentLevel: '',
|
|
customerStatus: '',
|
|
region: '',
|
|
regionIds: [],
|
|
workWechat: '',
|
|
workWechatId: null,
|
|
remark: '',
|
|
concern: '',
|
|
pain: '',
|
|
attention: '',
|
|
demand: '',
|
|
nextFollowTime: ''
|
|
});
|
|
|
|
// 显示状态
|
|
const saving = ref(false);
|
|
const loading = 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 pickersRef = ref(null);
|
|
|
|
// 获取页面参数
|
|
onLoad((options) => {
|
|
if (options && options.id) {
|
|
customerId.value = options.id;
|
|
loadCustomerDetail();
|
|
}
|
|
});
|
|
|
|
// 加载客户详情
|
|
const loadCustomerDetail = async () => {
|
|
if (!customerId.value) return;
|
|
|
|
loading.value = true;
|
|
try {
|
|
const res = await getCustomerDetail(customerId.value);
|
|
if (res) {
|
|
console.log('客户详情数据:', res);
|
|
// 将后端数据转换为表单数据格式
|
|
formData.value = {
|
|
id: res.id,
|
|
customerType: res.type || '',
|
|
name: res.name || '',
|
|
mobile: res.mobile || '',
|
|
wechat: res.wechat ||'',
|
|
source: res.source || '',
|
|
intents: Array.isArray(res.intents) ? res.intents : (res.intents ? res.intents.split(',') : []),
|
|
intentLevel: res.intentLevel || '',
|
|
customerStatus: res.customerStatus || res.status || '',
|
|
region: res.region || res.regionName || '',
|
|
// 从后端返回的 provinceId, cityId, countyId 构建 regionIds 数组(用于前端显示和选择器)
|
|
regionIds: [res.provinceId, res.cityId, res.countyId],
|
|
workWechat: res.wechatId || '',
|
|
workWechatId: res.workWechatId || null,
|
|
remark: res.remark || '',
|
|
concern: res.concern || '',
|
|
pain: res.pain || '',
|
|
attention: res.attention || '',
|
|
demand: res.demand || '',
|
|
nextFollowTime: res.nextFollowTime || ''
|
|
};
|
|
console.log('表单数据:', formData.value);
|
|
// 数据加载完成后初始化地区数据
|
|
await nextTick();
|
|
if (formData.value.regionIds && formData.value.regionIds.length > 0 && pickersRef.value) {
|
|
handlePickValueDefault(formData.value, pickersRef.value);
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('加载客户详情失败:', error);
|
|
uni.showToast({
|
|
title: '加载客户详情失败',
|
|
icon: 'none'
|
|
});
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
};
|
|
|
|
|
|
// 打开选择器
|
|
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;
|
|
}
|
|
};
|
|
|
|
// 关闭选择器
|
|
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;
|
|
}
|
|
};
|
|
|
|
// uv-picker 的 change 事件处理(实现三级联动)
|
|
const onRegionChange = (e) => {
|
|
handleRegionChange(e, pickersRef.value);
|
|
};
|
|
|
|
// uv-picker 的 confirm 事件处理
|
|
const onRegionConfirm = (e) => {
|
|
handleRegionConfirm(e, formData.value);
|
|
};
|
|
|
|
// 取消
|
|
const handleCancel = () => {
|
|
uni.navigateBack();
|
|
};
|
|
|
|
// 组件挂载时加载数据
|
|
onMounted(async () => {
|
|
await Promise.all([
|
|
loadRegionTree(),
|
|
loadDictData(),
|
|
loadWechatList()
|
|
]);
|
|
// 如果客户详情已加载,初始化地区选择器
|
|
if (formData.value.regionIds && formData.value.regionIds.length > 0 && pickersRef.value) {
|
|
handlePickValueDefault(formData.value, pickersRef.value);
|
|
}
|
|
});
|
|
|
|
// 保存
|
|
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 userStore = useUserStore();
|
|
const userId = userStore.userInfo?.id || userStore.userInfo?.userId || '1';
|
|
|
|
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 || [];
|
|
|
|
const submitData = {
|
|
id: formData.value.id,
|
|
code: null,
|
|
name: formData.value.name.trim(),
|
|
status: formData.value.customerStatus || null,
|
|
intentLevel: formData.value.intentLevel || null,
|
|
mobile: formData.value.mobile.trim(),
|
|
wechat: (formData.value.wechat && formData.value.wechat.trim()) ? formData.value.wechat.trim() : null,
|
|
source: formData.value.source || null,
|
|
intents: intentsArray,
|
|
followId: userId,
|
|
remark: formData.value.remark.trim() || null,
|
|
type: formData.value.customerType || '2',
|
|
workWechatId: formData.value.workWechatId || null,
|
|
// 将 regionIds 数组转换为三个独立的字段传给后端
|
|
provinceId: (regionIdsArray[0] !== undefined && regionIdsArray[0] !== null) ? regionIdsArray[0] : null,
|
|
cityId: (regionIdsArray[1] !== undefined && regionIdsArray[1] !== null) ? regionIdsArray[1] : null,
|
|
countyId: (regionIdsArray[2] !== undefined && regionIdsArray[2] !== null) ? regionIdsArray[2] : null,
|
|
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
|
|
};
|
|
|
|
console.log('提交的数据:', submitData);
|
|
console.log('地区数据:', {
|
|
regionIds: regionIdsArray,
|
|
provinceId: submitData.provinceId,
|
|
cityId: submitData.cityId,
|
|
countyId: submitData.countyId
|
|
});
|
|
|
|
await updateCustomer(submitData);
|
|
|
|
uni.showToast({
|
|
title: '更新成功',
|
|
icon: 'success'
|
|
});
|
|
|
|
// 延迟返回,让用户看到成功提示
|
|
setTimeout(() => {
|
|
uni.navigateBack();
|
|
}, 1500);
|
|
} catch (error) {
|
|
console.error('更新客户失败:', error);
|
|
uni.showToast({
|
|
title: error.message || '更新失败,请重试',
|
|
icon: 'none'
|
|
});
|
|
} finally {
|
|
saving.value = false;
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.edit-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>
|
|
|