429 lines
14 KiB
Markdown
429 lines
14 KiB
Markdown
# 说明
|
||
|
||
|
||
## 基本概念
|
||
|
||
店铺和门店的关系可以从不同角度来理解,让我为您详细解释:
|
||
|
||
## 🏪 **店铺 vs 门店:概念解析**
|
||
|
||
### **1. 从层级关系理解**
|
||
|
||
#### **店铺(总店/品牌店)**
|
||
```mermaid
|
||
graph TD
|
||
A[品牌总部/总店] --> B1[门店A]
|
||
A --> B2[门店B]
|
||
A --> B3[门店C]
|
||
A --> B4[线上店铺]
|
||
|
||
B1 --> C1[分店A-1]
|
||
B1 --> C2[分店A-2]
|
||
B2 --> C3[分店B-1]
|
||
```
|
||
|
||
**店铺特征:**
|
||
- **管理层面**:品牌、总部、总店的概念
|
||
- **业务范围**:可能包含多个物理门店和线上渠道
|
||
- **功能定位**:战略决策、品牌管理、供应链控制
|
||
|
||
#### **门店(分店/实体店)**
|
||
```mermaid
|
||
graph LR
|
||
A[门店] --> B[具体营业场所]
|
||
A --> C[固定地址]
|
||
A --> D[面对面服务]
|
||
```
|
||
|
||
**门店特征:**
|
||
- **物理存在**:有具体的营业场所和地址
|
||
- **服务范围**:服务特定区域客户
|
||
- **运营独立**:相对独立的日常运营
|
||
|
||
### **2. 从业务模式区分**
|
||
|
||
| 维度 | 店铺(Shop) | 门店(Store) |
|
||
|------|-------------|--------------|
|
||
| **存在形式** | 可虚拟可实体 | 必须是实体 |
|
||
| **数量关系** | 1个店铺可有多门店 | 1个门店属于1个店铺 |
|
||
| **管理范围** | 品牌、战略、标准 | 日常运营、客户服务 |
|
||
| **系统关系** | 总部系统、ERP | POS系统、库存管理 |
|
||
|
||
### **3. 实际业务场景**
|
||
|
||
#### **场景1:连锁品牌**
|
||
```
|
||
店铺(总店)
|
||
├── 北京门店(朝阳区店)
|
||
├── 上海门店(浦东店)
|
||
├── 广州门店(天河店)
|
||
└── 线上官方店铺
|
||
```
|
||
|
||
#### **场景2:电商+实体结合**
|
||
```
|
||
店铺(品牌旗舰店)
|
||
├── 天猫官方店铺(线上)
|
||
├── 京东官方店铺(线上)
|
||
├── 线下体验门店(实体)
|
||
└── 微信小程序店铺(线上)
|
||
```
|
||
|
||
#### **场景3:单店经营**
|
||
```
|
||
店铺 = 门店(合二为一)
|
||
└── 既是品牌也是具体营业点
|
||
```
|
||
|
||
## 💼 **在智能客服系统中的数据建模**
|
||
|
||
### **1. 数据库设计**
|
||
|
||
```sql
|
||
-- 店铺表(总店/品牌)
|
||
CREATE TABLE shops (
|
||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||
name VARCHAR(100) NOT NULL, -- 店铺名称
|
||
brand_name VARCHAR(100), -- 品牌名称
|
||
type ENUM('single', 'chain', 'online'), -- 店铺类型
|
||
status ENUM('active', 'inactive'),
|
||
created_at TIMESTAMP
|
||
);
|
||
|
||
-- 门店表(分店/实体店)
|
||
CREATE TABLE stores (
|
||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||
shop_id INT, -- 所属店铺
|
||
name VARCHAR(100) NOT NULL, -- 门店名称
|
||
address TEXT, -- 具体地址
|
||
phone VARCHAR(20),
|
||
manager_id INT, -- 店长
|
||
business_hours JSON, -- 营业时间
|
||
latitude DECIMAL(10, 8), -- 纬度
|
||
longitude DECIMAL(11, 8), -- 经度
|
||
status ENUM('open', 'closed', 'maintenance'),
|
||
FOREIGN KEY (shop_id) REFERENCES shops(id)
|
||
);
|
||
|
||
-- 员工表(关联门店)
|
||
CREATE TABLE staff (
|
||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||
store_id INT, -- 所属门店
|
||
name VARCHAR(50),
|
||
role ENUM('manager', 'assistant', 'cashier'),
|
||
phone VARCHAR(20),
|
||
FOREIGN KEY (store_id) REFERENCES stores(id)
|
||
);
|
||
```
|
||
|
||
### **2. 业务逻辑实现**
|
||
|
||
```javascript
|
||
// 店铺管理类
|
||
class ShopManager {
|
||
constructor() {
|
||
this.shops = new Map();
|
||
this.stores = new Map();
|
||
}
|
||
|
||
// 创建店铺
|
||
createShop(shopData) {
|
||
const shop = {
|
||
id: this.generateId(),
|
||
name: shopData.name,
|
||
brand: shopData.brand,
|
||
type: shopData.type || 'single',
|
||
stores: [], // 下属门店
|
||
createdAt: new Date(),
|
||
status: 'active'
|
||
};
|
||
|
||
this.shops.set(shop.id, shop);
|
||
return shop;
|
||
}
|
||
|
||
// 添加门店到店铺
|
||
addStoreToShop(shopId, storeData) {
|
||
const shop = this.shops.get(shopId);
|
||
if (!shop) throw new Error('店铺不存在');
|
||
|
||
const store = {
|
||
id: this.generateId(),
|
||
shopId: shopId,
|
||
name: storeData.name,
|
||
address: storeData.address,
|
||
contact: storeData.contact,
|
||
coordinates: storeData.coordinates,
|
||
businessHours: storeData.businessHours,
|
||
staff: [],
|
||
createdAt: new Date()
|
||
};
|
||
|
||
shop.stores.push(store.id);
|
||
this.stores.set(store.id, store);
|
||
|
||
return store;
|
||
}
|
||
|
||
// 根据位置查找最近门店
|
||
findNearestStore(shopId, userLocation) {
|
||
const shop = this.shops.get(shopId);
|
||
if (!shop) return null;
|
||
|
||
let nearestStore = null;
|
||
let minDistance = Infinity;
|
||
|
||
shop.stores.forEach(storeId => {
|
||
const store = this.stores.get(storeId);
|
||
if (store && store.status === 'open') {
|
||
const distance = this.calculateDistance(
|
||
userLocation,
|
||
store.coordinates
|
||
);
|
||
|
||
if (distance < minDistance) {
|
||
minDistance = distance;
|
||
nearestStore = store;
|
||
}
|
||
}
|
||
});
|
||
|
||
return nearestStore;
|
||
}
|
||
|
||
// 计算距离(简化版)
|
||
calculateDistance(loc1, loc2) {
|
||
const R = 6371; // 地球半径公里
|
||
const dLat = this.deg2rad(loc2.lat - loc1.lat);
|
||
const dLon = this.deg2rad(loc2.lon - loc1.lon);
|
||
|
||
const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
|
||
Math.cos(this.deg2rad(loc1.lat)) * Math.cos(this.deg2rad(loc2.lat)) *
|
||
Math.sin(dLon/2) * Math.sin(dLon/2);
|
||
|
||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
|
||
return R * c;
|
||
}
|
||
|
||
deg2rad(deg) {
|
||
return deg * (Math.PI/180);
|
||
}
|
||
}
|
||
```
|
||
|
||
### **3. 在智能客服中的对话逻辑**
|
||
|
||
```javascript
|
||
// 店铺门店相关的对话处理
|
||
class StoreDialogHandler {
|
||
constructor(shopManager) {
|
||
this.shopManager = shopManager;
|
||
}
|
||
|
||
// 处理用户查询
|
||
handleStoreQuery(userMessage, userContext) {
|
||
const intent = this.detectIntent(userMessage);
|
||
|
||
switch(intent) {
|
||
case 'find_nearest':
|
||
return this.handleFindNearest(userMessage, userContext);
|
||
|
||
case 'store_hours':
|
||
return this.handleStoreHours(userMessage, userContext);
|
||
|
||
case 'store_contact':
|
||
return this.handleStoreContact(userMessage, userContext);
|
||
|
||
case 'all_stores':
|
||
return this.handleAllStores(userMessage, userContext);
|
||
|
||
default:
|
||
return this.handleGeneralQuery(userMessage, userContext);
|
||
}
|
||
}
|
||
|
||
// 查找最近门店
|
||
handleFindNearest(userMessage, userContext) {
|
||
const location = this.extractLocation(userMessage);
|
||
const shopId = userContext.currentShopId;
|
||
|
||
if (!location) {
|
||
return {
|
||
type: 'request_location',
|
||
message: '请问您当前在哪个位置?我可以帮您查找最近的门店。',
|
||
options: ['使用当前位置', '手动输入地址']
|
||
};
|
||
}
|
||
|
||
const nearestStore = this.shopManager.findNearestStore(shopId, location);
|
||
|
||
if (nearestStore) {
|
||
return {
|
||
type: 'store_info',
|
||
message: `离您最近的门店是:${nearestStore.name}`,
|
||
data: {
|
||
store: nearestStore,
|
||
distance: this.calculateDistance(location, nearestStore.coordinates),
|
||
estimatedTime: this.estimateTravelTime(nearestStore.coordinates, location)
|
||
},
|
||
actions: [
|
||
{ text: '查看详情', action: 'show_store_detail' },
|
||
{ text: '导航前往', action: 'navigate_to_store' },
|
||
{ text: '联系门店', action: 'contact_store' }
|
||
]
|
||
};
|
||
} else {
|
||
return {
|
||
type: 'no_store_found',
|
||
message: '在您附近没有找到我们的门店,建议您尝试线上服务或查看其他区域的门店。',
|
||
alternatives: this.findAlternativeStores(shopId)
|
||
};
|
||
}
|
||
}
|
||
|
||
// 处理营业时间查询
|
||
handleStoreHours(userMessage, userContext) {
|
||
const storeName = this.extractStoreName(userMessage);
|
||
const store = this.findStoreByName(storeName, userContext.currentShopId);
|
||
|
||
if (store) {
|
||
const hours = store.businessHours;
|
||
const currentStatus = this.getCurrentStatus(store);
|
||
|
||
return {
|
||
type: 'business_hours',
|
||
message: `${store.name}的营业时间:${this.formatBusinessHours(hours)}`,
|
||
data: {
|
||
store: store,
|
||
currentStatus: currentStatus,
|
||
todayHours: this.getTodayHours(hours)
|
||
}
|
||
};
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### **4. 响应消息模板**
|
||
|
||
```javascript
|
||
// 店铺门店信息响应模板
|
||
const StoreResponseTemplates = {
|
||
// 门店列表响应
|
||
storeList: (stores, options = {}) => {
|
||
return {
|
||
type: 'store_list',
|
||
layout: 'card',
|
||
title: options.title || '我们的门店',
|
||
items: stores.map(store => ({
|
||
title: store.name,
|
||
description: store.address,
|
||
image: store.image,
|
||
meta: {
|
||
distance: store.distance ? `${store.distance}km` : '',
|
||
status: store.status === 'open' ? '营业中' : '休息中',
|
||
hours: store.businessHours ? '查看营业时间' : ''
|
||
},
|
||
actions: [
|
||
{ text: '导航', action: 'navigate', data: { storeId: store.id } },
|
||
{ text: '电话', action: 'call', data: { phone: store.phone } },
|
||
{ text: '详情', action: 'detail', data: { storeId: store.id } }
|
||
]
|
||
})),
|
||
quickReplies: [
|
||
'找最近的门店',
|
||
'查看所有门店',
|
||
'联系客服'
|
||
]
|
||
};
|
||
},
|
||
|
||
// 单个门店详情
|
||
storeDetail: (store) => {
|
||
return {
|
||
type: 'store_detail',
|
||
layout: 'detail',
|
||
title: store.name,
|
||
sections: [
|
||
{
|
||
title: '📍 地址',
|
||
content: store.address,
|
||
action: { type: 'map', data: store.coordinates }
|
||
},
|
||
{
|
||
title: '📞 联系方式',
|
||
content: store.phone,
|
||
action: { type: 'call', data: store.phone }
|
||
},
|
||
{
|
||
title: '🕒 营业时间',
|
||
content: formatBusinessHours(store.businessHours),
|
||
action: { type: 'hours', data: store.businessHours }
|
||
},
|
||
{
|
||
title: '👥 门店服务',
|
||
content: store.services.join('、'),
|
||
action: { type: 'services', data: store.services }
|
||
}
|
||
],
|
||
actions: [
|
||
{ text: '分享门店', action: 'share' },
|
||
{ text: '收藏门店', action: 'favorite' },
|
||
{ text: '投诉建议', action: 'feedback' }
|
||
]
|
||
};
|
||
},
|
||
|
||
// 营业时间响应
|
||
businessHours: (store, currentStatus) => {
|
||
return {
|
||
type: 'business_hours',
|
||
message: `**${store.name}**\n\n` +
|
||
`当前状态:**${currentStatus}**\n\n` +
|
||
`营业时间:\n${formatBusinessHours(store.businessHours)}`,
|
||
quickActions: [
|
||
{ text: '明天营业时间', action: 'tomorrow_hours' },
|
||
{ text: '节假日安排', action: 'holiday_hours' },
|
||
{ text: '联系确认', action: 'confirm_hours' }
|
||
]
|
||
};
|
||
}
|
||
};
|
||
|
||
// 工具函数
|
||
function formatBusinessHours(hours) {
|
||
if (!hours) return '暂无信息';
|
||
|
||
const days = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
|
||
return days.map((day, index) => {
|
||
const dayHours = hours[index] || hours['default'];
|
||
return `${day}: ${dayHours || '休息'}`;
|
||
}).join('\n');
|
||
}
|
||
```
|
||
|
||
## 🎯 **总结:店铺与门店的关系**
|
||
|
||
### **核心关系**
|
||
1. **包含关系**:店铺包含门店(1:N)
|
||
2. **品牌关系**:店铺是品牌,门店是落地实体
|
||
3. **管理关系**:店铺管理门店的标准和运营
|
||
|
||
### **在智能客服中的应用**
|
||
- **用户说"我要找店铺"** → 理解为品牌/总店概念
|
||
- **用户说"找最近的门店"** → 理解为具体营业点
|
||
- **用户说"你们店在哪里"** → 需要区分是指品牌还是具体门店
|
||
|
||
### **数据处理建议**
|
||
```javascript
|
||
// 在客服系统中这样区分:
|
||
const customerQuery = {
|
||
"找苹果店": { type: "shop", brand: "apple" },
|
||
"找朝阳区的苹果店": { type: "store", brand: "apple", location: "朝阳区" },
|
||
"线上店铺": { type: "online_shop" },
|
||
"实体门店": { type: "physical_store" }
|
||
};
|
||
```
|
||
|
||
这样的区分让智能客服能够更精准地理解用户意图,提供更准确的店铺/门店信息服务。
|