diff --git a/App.vue b/App.vue
index 19f2151..1c56512 100644
--- a/App.vue
+++ b/App.vue
@@ -8,7 +8,7 @@
// 如果还没有 token,则设置一个测试 token
const token = uni.getStorageSync('token')
if (!token) {
- const testToken = 'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjJiNWZkNDAyLTFiYWQtNDI5YS04ZDFkLTllZGE0Y2VkOWIxMyJ9.2UEvAG6OtJ0WZoJxjPjGzGhdgxAclzEqqPl_K94kbcCVs9YplENwZe2AcdsLkdLsc7EnDbRif-xuhWlTKF78WQ'
+ const testToken = 'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImI4MDUzOGE0LThjNTQtNGZlMy04NmMwLThhYzhlZmMwMTg1ZCJ9.xalBJnQcnxHsHUVFn46XXamKBPA2RdDtvVvhRQwc7j-lARywOjKMfSqjUiSe8DbWMKt1iBZIz0Z0JDYX7IGb_g'
uni.setStorageSync('token', testToken)
console.log('已设置测试 token:', testToken)
}
diff --git a/common/api/customer.js b/common/api/customer.js
index fe5f598..73256db 100644
--- a/common/api/customer.js
+++ b/common/api/customer.js
@@ -166,6 +166,37 @@ export const createCustomer = (data) => {
});
};
+/**
+ * 更新客户
+ * @param {Object} data 客户数据(必须包含id)
+ * @param {string} data.id 客户ID
+ * @param {string} data.type 类型
+ * @param {string} data.name 客户名
+ * @param {string} data.mobile 手机号
+ * @param {string} data.wechat 微信号
+ * @param {string} data.source 来源
+ * @param {string} data.intents 意向的设备,逗号分离
+ * @param {string} data.status 状态(1潜在2意向3成交4失效)
+ * @param {string} data.intentLevel 意向强度
+ * @param {string} data.customerStatus 客户状态
+ * @param {string} data.customerIntentLevel 客户意向强度
+ * @param {string} data.nextFollowTime 下次跟进时间
+ * @param {string} data.followId 跟进人id
+ * @param {string} data.remark 备注
+ * @param {string} data.concern 顾虑点
+ * @param {string} data.pain 痛点
+ * @param {string} data.attention 关注点
+ * @param {string} data.demand 需求点
+ * @returns {Promise} 返回更新结果
+ */
+export const updateCustomer = (data) => {
+ return uni.$uv.http.put(`bst/customer`, data, {
+ custom: {
+ auth: true
+ }
+ });
+};
+
/**
* 获取客户意向字典数据
* @returns {Promise} 返回字典数据数组,包含 dictLabel 和 dictValue
diff --git a/components/customer-form/CustomerBasicInfo.vue b/components/customer-form/CustomerBasicInfo.vue
new file mode 100644
index 0000000..700ceb7
--- /dev/null
+++ b/components/customer-form/CustomerBasicInfo.vue
@@ -0,0 +1,203 @@
+
+
+ 客户信息
+
+
+
+ {{ getCustomerTypeText(formData.customerType) }}
+ 选择客户类型
+ ›
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formData.source }}
+ 选择客户来源
+ ›
+
+
+
+
+ {{ formData.intents.join('、') }}
+ 选择客户意向(可多选)
+ ›
+
+
+
+
+ {{ getIntentLevelText(formData.intentLevel) }}
+ 选择意向强度
+ ›
+
+
+
+
+ {{ getCustomerStatusText(formData.customerStatus) }}
+ 选择客户状态
+ ›
+
+
+
+
+ {{ formData.region }}
+ 选择客户地区
+ ›
+
+
+
+
+ {{ formData.workWechat }}
+ 选择工作微信
+ ›
+
+
+
+
+
+
+
+
diff --git a/components/customer-form/CustomerFormNavbar.vue b/components/customer-form/CustomerFormNavbar.vue
new file mode 100644
index 0000000..ff11cf2
--- /dev/null
+++ b/components/customer-form/CustomerFormNavbar.vue
@@ -0,0 +1,54 @@
+
+
+
+ ‹
+ {{ title }}
+ 占位
+
+
+
+
+
+
+
+
diff --git a/components/customer-form/CustomerOtherInfo.vue b/components/customer-form/CustomerOtherInfo.vue
new file mode 100644
index 0000000..7af45b1
--- /dev/null
+++ b/components/customer-form/CustomerOtherInfo.vue
@@ -0,0 +1,196 @@
+
+
+ 其他信息
+
+
+
+ 客户星级
+
+ ★
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ formData.nextFollowTime }}
+ 选择下次跟进时间(可选)
+ ›
+
+
+
+
+
+
+
+
diff --git a/components/customer-form/CustomerPickers.vue b/components/customer-form/CustomerPickers.vue
new file mode 100644
index 0000000..6b0d481
--- /dev/null
+++ b/components/customer-form/CustomerPickers.vue
@@ -0,0 +1,489 @@
+
+
+
+
+ 选择客户类型
+
+
+ {{ item.label }}
+ ✓
+
+
+
+
+
+
+
+
+
+
+
+
+ 选择客户来源
+
+
+ {{ item.label }}
+ ✓
+
+
+
+
+
+
+
+
+
+
+
+
+ 选择客户意向(可多选)
+
+
+ {{ item.label }}
+ ✓
+
+
+
+
+
+
+
+
+
+
+
+
+ 选择意向强度
+
+
+ {{ item.label }}
+ ✓
+
+
+
+
+
+
+
+
+
+
+
+
+ 选择客户状态
+
+
+ {{ item.label }}
+ ✓
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 选择工作微信
+
+
+ {{ item.label }}
+ ✓
+
+
+
+
+
+
+
+
+
+
+
+
+ 选择下次跟进时间
+
+
+ 日期: {{ tempNextFollowDate || '请选择日期' }}
+
+
+ 时间: {{ tempNextFollowTime || '请选择时间' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/composables/useCustomerForm.js b/composables/useCustomerForm.js
new file mode 100644
index 0000000..b06a293
--- /dev/null
+++ b/composables/useCustomerForm.js
@@ -0,0 +1,263 @@
+import { ref, computed } from 'vue';
+import {
+ getRegionTree,
+ getCustomerIntentDict,
+ getCustomerIntentLevelDict,
+ getCustomerSourceDict,
+ getCustomerTypeDict,
+ getCustomerStatusDict,
+ getWechatList
+} from '@/common/api';
+
+/**
+ * 客户表单共享逻辑
+ */
+export function useCustomerForm() {
+ // 字典数据
+ const customerTypeOptions = ref([]);
+ const sourceOptions = ref([]);
+ const intentOptions = ref([]);
+ const intentLevelOptions = ref([]);
+ const customerStatusOptions = ref([]);
+ const workWechatOptions = ref([]);
+
+ // 地区数据
+ const provinces = ref([]);
+ const citys = ref([]);
+ const areas = ref([]);
+ const regionLoading = ref(true);
+
+ // 计算属性:返回地址列表
+ const addressList = computed(() => {
+ return [provinces.value, citys.value, areas.value];
+ });
+
+ // 加载字典数据
+ const loadDictData = async () => {
+ try {
+ const [typeRes, sourceRes, intentRes, intentLevelRes, statusRes] = await Promise.all([
+ getCustomerTypeDict(),
+ getCustomerSourceDict(),
+ getCustomerIntentDict(),
+ getCustomerIntentLevelDict(),
+ getCustomerStatusDict()
+ ]);
+
+ customerTypeOptions.value = (typeRes || []).map(item => ({
+ label: item.dictLabel,
+ value: item.dictValue
+ }));
+
+ sourceOptions.value = (sourceRes || []).map(item => ({
+ label: item.dictLabel,
+ value: item.dictValue
+ }));
+
+ intentOptions.value = (intentRes || []).map(item => ({
+ label: item.dictLabel,
+ value: item.dictValue
+ }));
+
+ intentLevelOptions.value = (intentLevelRes || []).map(item => ({
+ label: item.dictLabel,
+ value: item.dictValue
+ }));
+
+ customerStatusOptions.value = (statusRes || []).map(item => ({
+ label: item.dictLabel,
+ value: item.dictValue
+ }));
+ } catch (err) {
+ console.error('加载字典数据失败:', err);
+ uni.showToast({
+ title: '加载字典数据失败',
+ icon: 'none'
+ });
+ }
+ };
+
+ // 加载微信列表数据
+ const loadWechatList = async () => {
+ try {
+ const res = await getWechatList();
+ const rows = res?.rows || [];
+
+ workWechatOptions.value = rows.map(item => ({
+ label: item.nickName ? `${item.nickName} (${item.wechatId})` : item.wechatId,
+ value: String(item.id),
+ id: item.id,
+ wechatId: item.wechatId
+ }));
+ } catch (err) {
+ console.error('加载微信列表失败:', err);
+ uni.showToast({
+ title: '加载微信列表失败',
+ icon: 'none'
+ });
+ }
+ };
+
+ // 加载地区树数据
+ const loadRegionTree = async () => {
+ try {
+ const res = await getRegionTree();
+ const regionTree = res;
+
+ provinces.value = regionTree.sort((left, right) =>
+ (Number(left.code || left.id) > Number(right.code || right.id) ? 1 : -1)
+ );
+
+ if (provinces.value.length > 0) {
+ citys.value = provinces.value[0]?.children || [];
+ if (citys.value.length > 0) {
+ areas.value = citys.value[0]?.children || [];
+ }
+ }
+
+ setTimeout(() => {
+ regionLoading.value = false;
+ }, 200);
+ } catch (err) {
+ console.error('加载地区树失败:', err);
+ regionLoading.value = false;
+ uni.showToast({
+ title: '加载地区数据失败',
+ icon: 'none'
+ });
+ }
+ };
+
+ // 根据已选择的ID设置默认选中项
+ const handlePickValueDefault = (formData, pickersRef) => {
+ if (!formData.regionIds || formData.regionIds.length === 0) {
+ return;
+ }
+
+ const [provinceId, cityId, districtId] = formData.regionIds;
+
+ const provinceIndex = provinces.value.findIndex(item => Number(item.id) === Number(provinceId));
+ if (provinceIndex >= 0) {
+ citys.value = provinces.value[provinceIndex]?.children || [];
+ const cityIndex = citys.value.findIndex(item => Number(item.id) === Number(cityId));
+ if (cityIndex >= 0) {
+ areas.value = citys.value[cityIndex]?.children || [];
+ const districtIndex = areas.value.findIndex(item => Number(item.id) === Number(districtId));
+ if (districtIndex >= 0 && pickersRef) {
+ pickersRef.setRegionIndexs([provinceIndex, cityIndex, districtIndex]);
+ }
+ }
+ }
+ };
+
+ // 处理地区选择器change事件
+ const handleRegionChange = (e, pickersRef) => {
+ if (regionLoading.value) return;
+
+ const { columnIndex, index, indexs } = e;
+
+ if (columnIndex === 0) {
+ citys.value = provinces.value[index]?.children || [];
+ areas.value = citys.value[0]?.children || [];
+ if (pickersRef) {
+ pickersRef.setRegionIndexs([index, 0, 0]);
+ }
+ } else if (columnIndex === 1) {
+ areas.value = citys.value[index]?.children || [];
+ if (pickersRef) {
+ pickersRef.setRegionIndexs(indexs);
+ }
+ }
+ };
+
+ // 处理地区选择器confirm事件
+ const handleRegionConfirm = (e, formData) => {
+ const { value } = e;
+
+ if (value && value.length > 0) {
+ const province = value[0];
+ const city = value[1];
+ const district = value[2];
+
+ const regionNames = [];
+ const regionIds = [];
+
+ if (province) {
+ regionNames.push(province.name);
+ regionIds.push(province.id);
+
+ if (city) {
+ regionNames.push(city.name);
+ regionIds.push(city.id);
+
+ if (district) {
+ regionNames.push(district.name);
+ regionIds.push(district.id);
+ }
+ }
+ }
+
+ formData.region = regionNames.join('/');
+ formData.regionIds = regionIds;
+ } else {
+ formData.region = '';
+ formData.regionIds = [];
+ }
+ };
+
+ // 打开地区选择器
+ const openRegionPicker = (formData, pickersRef) => {
+ if (regionLoading.value || provinces.value.length === 0) {
+ uni.showToast({
+ title: '地区数据加载中,请稍候',
+ icon: 'none'
+ });
+ return;
+ }
+
+ if (formData.regionIds && formData.regionIds.length > 0) {
+ handlePickValueDefault(formData, pickersRef);
+ } else {
+ if (citys.value.length === 0 && provinces.value.length > 0) {
+ citys.value = provinces.value[0]?.children || [];
+ if (citys.value.length > 0) {
+ areas.value = citys.value[0]?.children || [];
+ }
+ }
+ }
+
+ if (pickersRef) {
+ pickersRef.openRegionPicker();
+ if (!formData.regionIds || formData.regionIds.length === 0) {
+ setTimeout(() => {
+ if (pickersRef) {
+ pickersRef.setRegionIndexs([0, 0, 0]);
+ }
+ }, 100);
+ }
+ }
+ };
+
+ return {
+ // 数据
+ customerTypeOptions,
+ sourceOptions,
+ intentOptions,
+ intentLevelOptions,
+ customerStatusOptions,
+ workWechatOptions,
+ provinces,
+ citys,
+ areas,
+ regionLoading,
+ addressList,
+ // 方法
+ loadDictData,
+ loadWechatList,
+ loadRegionTree,
+ handlePickValueDefault,
+ handleRegionChange,
+ handleRegionConfirm,
+ openRegionPicker
+ };
+}
+
diff --git a/pages.json b/pages.json
index 13c9cdb..f787ed3 100644
--- a/pages.json
+++ b/pages.json
@@ -82,6 +82,13 @@
"navigationBarTitleText": "客户信息",
"navigationStyle": "custom"
}
+ },
+ {
+ "path": "pages/customer/edit/index",
+ "style": {
+ "navigationBarTitleText": "编辑客户",
+ "navigationStyle": "custom"
+ }
}
],
diff --git a/pages/customer/add/index.vue b/pages/customer/add/index.vue
index a0fa8a6..d32939e 100644
--- a/pages/customer/add/index.vue
+++ b/pages/customer/add/index.vue
@@ -1,182 +1,27 @@
-
-
- ‹
- 客户信息
- 占位
-
-
+
-
- 客户信息
-
-
-
- {{ getCustomerTypeText(formData.customerType) }}
- 选择客户类型
- ›
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ formData.source }}
- 选择客户来源
- ›
-
-
-
-
- {{ formData.intents.join('、') }}
- 选择客户意向(可多选)
- ›
-
-
-
-
- {{ getIntentLevelText(formData.intentLevel) }}
- 选择意向强度
- ›
-
-
-
-
- {{ getCustomerStatusText(formData.customerStatus) }}
- 选择客户状态
- ›
-
-
-
-
- {{ formData.region }}
- 选择客户地区
- ›
-
-
-
-
- {{ formData.workWechat }}
- 选择工作微信
- ›
-
-
+
-
- 其他信息
-
-
-
- 客户星级
-
- ★
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ formData.nextFollowTime }}
- 选择下次跟进时间(可选)
- ›
-
-
+
@@ -185,219 +30,82 @@
-
-
-
- 选择客户类型
-
-
- {{ item.label }}
- ✓
-
-
-
-
-
-
-
-
-
-
-
-
- 选择客户来源
-
-
- {{ item.label }}
- ✓
-
-
-
-
-
-
-
-
-
-
-
-
- 选择客户意向(可多选)
-
-
- {{ item.label }}
- ✓
-
-
-
-
-
-
-
-
-
-
-
-
- 选择意向强度
-
-
- {{ item.label }}
- ✓
-
-
-
-
-
-
-
-
-
-
-
-
- 选择客户状态
-
-
- {{ item.label }}
- ✓
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 选择工作微信
-
-
- {{ item.label }}
- ✓
-
-
-
-
-
-
-
-
-
-
-
-
- 选择下次跟进时间
-
-
- 日期: {{ tempNextFollowDate || '请选择日期' }}
-
-
- 时间: {{ tempNextFollowTime || '请选择时间' }}
-
-
-
-
-
-
-
-
-
+
+
+