refactor(db): 移除测试相关代码并优化消息列表数据结构
移除数据库测试页面和示例代码,清理测试路由配置 新增MessageListData接口支持微信群组和联系人两种数据类型 优化数据库表结构和服务导出
This commit is contained in:
@@ -1,596 +0,0 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Statistic,
|
||||
Row,
|
||||
Col,
|
||||
Alert,
|
||||
Typography,
|
||||
Space,
|
||||
Spin,
|
||||
Modal,
|
||||
message,
|
||||
} from "antd";
|
||||
import {
|
||||
UserOutlined,
|
||||
TeamOutlined,
|
||||
ContactsOutlined,
|
||||
FolderOutlined,
|
||||
PlayCircleOutlined,
|
||||
DeleteOutlined,
|
||||
ReloadOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { DatabaseExamples } from "@/utils/db-examples";
|
||||
import {
|
||||
db,
|
||||
kfUserService,
|
||||
weChatGroupService,
|
||||
contractService,
|
||||
DatabaseService,
|
||||
} from "@/utils/db";
|
||||
import { testDatabaseUpgrade, resetDatabase } from "@/utils/db-test";
|
||||
|
||||
const { Title, Text } = Typography;
|
||||
|
||||
interface LogEntry {
|
||||
id: number;
|
||||
timestamp: string;
|
||||
type: "info" | "success" | "error";
|
||||
message: string;
|
||||
}
|
||||
|
||||
const DatabaseTestPage: React.FC = () => {
|
||||
const [logs, setLogs] = useState<LogEntry[]>([]);
|
||||
const [isRunning, setIsRunning] = useState(false);
|
||||
const [dbStats, setDbStats] = useState({
|
||||
kfUsers: 0,
|
||||
groups: 0,
|
||||
contracts: 0,
|
||||
newContactList: 0,
|
||||
});
|
||||
|
||||
const addLog = (type: LogEntry["type"], msg: string) => {
|
||||
const newLog: LogEntry = {
|
||||
id: Date.now(),
|
||||
timestamp: new Date().toLocaleTimeString(),
|
||||
type,
|
||||
message: msg,
|
||||
};
|
||||
setLogs(prev => [newLog, ...prev].slice(0, 100)); // 保留最新100条日志
|
||||
|
||||
// 使用 Ant Design 的 message 组件显示通知
|
||||
if (type === "success") {
|
||||
message.success(msg);
|
||||
} else if (type === "error") {
|
||||
message.error(msg);
|
||||
} else {
|
||||
message.info(msg);
|
||||
}
|
||||
};
|
||||
|
||||
const updateStats = async () => {
|
||||
try {
|
||||
const newContactListService = new DatabaseService(db.newContractList);
|
||||
const stats = {
|
||||
kfUsers: await kfUserService.count(),
|
||||
groups: await weChatGroupService.count(),
|
||||
contracts: await contractService.count(),
|
||||
newContactList: await newContactListService.count(),
|
||||
};
|
||||
setDbStats(stats);
|
||||
} catch (error) {
|
||||
addLog("error", `统计数据更新失败: ${error}`);
|
||||
}
|
||||
};
|
||||
|
||||
const initDatabase = async () => {
|
||||
try {
|
||||
const result = await testDatabaseUpgrade();
|
||||
if (result.success) {
|
||||
addLog(
|
||||
"success",
|
||||
`数据库初始化成功 - 版本: ${result.version}, 表: ${result.tables?.join(", ")}`,
|
||||
);
|
||||
await updateStats();
|
||||
} else {
|
||||
addLog("error", `数据库初始化失败: ${result.error}`);
|
||||
}
|
||||
} catch (error) {
|
||||
addLog("error", `数据库初始化失败: ${error}`);
|
||||
}
|
||||
};
|
||||
|
||||
const runKfUserExample = async () => {
|
||||
setIsRunning(true);
|
||||
addLog("info", "开始客服用户操作示例...");
|
||||
|
||||
try {
|
||||
// 模拟从接口获取的客服用户数据(包含服务器ID)
|
||||
const serverKfUser = {
|
||||
id: Date.now(), // 模拟服务器返回的ID
|
||||
tenantId: 1,
|
||||
wechatId: `test_${Date.now()}`,
|
||||
nickname: "测试客服",
|
||||
alias: "客服小王",
|
||||
avatar: "https://example.com/avatar.jpg",
|
||||
gender: 1,
|
||||
region: "北京",
|
||||
signature: "专业客服,为您服务",
|
||||
bindQQ: "123456789",
|
||||
bindEmail: "test@example.com",
|
||||
bindMobile: "13800138000",
|
||||
createTime: new Date().toISOString(),
|
||||
currentDeviceId: 1,
|
||||
isDeleted: false,
|
||||
deleteTime: "",
|
||||
groupId: 1,
|
||||
memo: "优秀客服",
|
||||
wechatVersion: "8.0.0",
|
||||
labels: ["VIP客服", "专业"],
|
||||
lastUpdateTime: new Date().toISOString(),
|
||||
isOnline: true,
|
||||
};
|
||||
|
||||
const userId = await kfUserService.createWithServerId(serverKfUser);
|
||||
addLog(
|
||||
"success",
|
||||
`创建客服用户成功,本地ID: ${userId}, 服务器ID: ${serverKfUser.id}`,
|
||||
);
|
||||
|
||||
// 查询用户(按本地ID)
|
||||
const user = await kfUserService.findById(userId);
|
||||
addLog("info", `查询到用户: ${user?.nickname}`);
|
||||
|
||||
// 根据服务器ID查询
|
||||
const userByServerId = await kfUserService.findByServerId(
|
||||
serverKfUser.id,
|
||||
);
|
||||
addLog("info", `根据服务器ID查询到用户: ${userByServerId?.nickname}`);
|
||||
|
||||
// 更新用户
|
||||
await kfUserService.update(userId, {
|
||||
nickname: "更新后的昵称",
|
||||
lastUpdateTime: new Date().toISOString(),
|
||||
});
|
||||
addLog("success", "用户信息更新成功");
|
||||
|
||||
await updateStats();
|
||||
} catch (error) {
|
||||
addLog("error", `客服用户操作失败: ${error}`);
|
||||
} finally {
|
||||
setIsRunning(false);
|
||||
}
|
||||
};
|
||||
|
||||
const runGroupExample = async () => {
|
||||
setIsRunning(true);
|
||||
addLog("info", "开始群组操作示例...");
|
||||
|
||||
try {
|
||||
// 模拟从接口获取的群组数据
|
||||
const serverGroup = {
|
||||
id: Date.now(), // 模拟服务器返回的ID
|
||||
wechatAccountId: 1,
|
||||
tenantId: 1,
|
||||
accountId: 1,
|
||||
chatroomId: `chatroom_${Date.now()}`,
|
||||
chatroomOwner: "owner_001",
|
||||
conRemark: "测试群组",
|
||||
nickname: "产品讨论群",
|
||||
chatroomAvatar: "https://example.com/group-avatar.jpg",
|
||||
groupId: 1,
|
||||
config: {
|
||||
chat: true,
|
||||
},
|
||||
unreadCount: 0,
|
||||
notice: "欢迎加入产品讨论群",
|
||||
selfDisplyName: "群管理员",
|
||||
};
|
||||
|
||||
const groupId = await weChatGroupService.createWithServerId(serverGroup);
|
||||
addLog(
|
||||
"success",
|
||||
`创建群组成功,本地ID: ${groupId}, 服务器ID: ${serverGroup.id}`,
|
||||
);
|
||||
|
||||
// 更新群组
|
||||
await weChatGroupService.update(groupId, {
|
||||
unreadCount: 5,
|
||||
notice: "更新的群公告",
|
||||
});
|
||||
addLog("success", "群组信息更新成功");
|
||||
|
||||
await updateStats();
|
||||
} catch (error) {
|
||||
addLog("error", `群组操作失败: ${error}`);
|
||||
} finally {
|
||||
setIsRunning(false);
|
||||
}
|
||||
};
|
||||
|
||||
const runContractExample = async () => {
|
||||
setIsRunning(true);
|
||||
addLog("info", "开始联系人操作示例...");
|
||||
|
||||
try {
|
||||
// 模拟从接口获取的联系人数据
|
||||
const serverContract = {
|
||||
id: Date.now(), // 模拟服务器返回的ID
|
||||
wechatAccountId: 1,
|
||||
wechatId: `contact_${Date.now()}`,
|
||||
alias: "张三",
|
||||
conRemark: "重要客户",
|
||||
nickname: "张总",
|
||||
quanPin: "zhangsan",
|
||||
avatar: "https://example.com/contact-avatar.jpg",
|
||||
gender: 1,
|
||||
region: "上海",
|
||||
addFrom: 1,
|
||||
phone: "13900139000",
|
||||
labels: ["VIP客户", "重点关注"],
|
||||
signature: "专业人士",
|
||||
accountId: 1,
|
||||
extendFields: null,
|
||||
city: "上海",
|
||||
lastUpdateTime: new Date().toISOString(),
|
||||
isPassed: true,
|
||||
tenantId: 1,
|
||||
groupId: 1,
|
||||
thirdParty: null,
|
||||
additionalPicture: "",
|
||||
desc: "优质客户",
|
||||
config: {
|
||||
chat: true,
|
||||
},
|
||||
lastMessageTime: Date.now(),
|
||||
unreadCount: 0,
|
||||
duplicate: false,
|
||||
};
|
||||
|
||||
const contractId =
|
||||
await contractService.createWithServerId(serverContract);
|
||||
addLog(
|
||||
"success",
|
||||
`创建联系人成功,本地ID: ${contractId}, 服务器ID: ${serverContract.id}`,
|
||||
);
|
||||
|
||||
// 查询联系人
|
||||
const searchResults = await contractService.findWhereStartsWith(
|
||||
"nickname",
|
||||
"张",
|
||||
);
|
||||
addLog("info", `找到姓张的联系人: ${searchResults.length} 个`);
|
||||
|
||||
await updateStats();
|
||||
} catch (error) {
|
||||
addLog("error", `联系人操作失败: ${error}`);
|
||||
} finally {
|
||||
setIsRunning(false);
|
||||
}
|
||||
};
|
||||
|
||||
const runBatchExample = async () => {
|
||||
setIsRunning(true);
|
||||
addLog("info", "开始批量操作示例...");
|
||||
|
||||
try {
|
||||
// 模拟从接口获取的批量联系人数据
|
||||
const batchServerContacts = Array.from({ length: 5 }, (_, i) => ({
|
||||
id: Date.now() + i, // 模拟服务器返回的ID
|
||||
wechatAccountId: 1,
|
||||
wechatId: `batch_${Date.now()}_${i}`,
|
||||
alias: `批量用户${i + 1}`,
|
||||
conRemark: "批量导入",
|
||||
nickname: `用户${i + 1}`,
|
||||
quanPin: `yonghu${i + 1}`,
|
||||
gender: (i % 2) + 1,
|
||||
region: i % 2 === 0 ? "北京" : "上海",
|
||||
addFrom: 3,
|
||||
phone: `1380000000${i}`,
|
||||
labels: ["批量导入"],
|
||||
signature: "",
|
||||
accountId: 1,
|
||||
extendFields: null,
|
||||
lastUpdateTime: new Date().toISOString(),
|
||||
isPassed: true,
|
||||
tenantId: 1,
|
||||
groupId: 1,
|
||||
thirdParty: null,
|
||||
additionalPicture: "",
|
||||
desc: "批量导入的用户",
|
||||
lastMessageTime: Date.now(),
|
||||
unreadCount: 0,
|
||||
duplicate: false,
|
||||
}));
|
||||
|
||||
const batchIds =
|
||||
await contractService.createManyWithServerId(batchServerContacts);
|
||||
addLog(
|
||||
"success",
|
||||
`批量创建联系人成功,创建了 ${batchIds.length} 个联系人`,
|
||||
);
|
||||
|
||||
await updateStats();
|
||||
} catch (error) {
|
||||
addLog("error", `批量操作失败: ${error}`);
|
||||
} finally {
|
||||
setIsRunning(false);
|
||||
}
|
||||
};
|
||||
|
||||
const clearAllData = async () => {
|
||||
Modal.confirm({
|
||||
title: "确认清空数据",
|
||||
content: "确定要清空所有测试数据吗?此操作不可恢复!",
|
||||
okText: "确定",
|
||||
cancelText: "取消",
|
||||
onOk: async () => {
|
||||
setIsRunning(true);
|
||||
addLog("info", "开始清空数据...");
|
||||
try {
|
||||
await db.transaction(
|
||||
"rw",
|
||||
[db.kfUsers, db.weChatGroups, db.contracts, db.newContractList],
|
||||
async () => {
|
||||
await db.kfUsers.clear();
|
||||
await db.weChatGroups.clear();
|
||||
await db.contracts.clear();
|
||||
await db.newContractList.clear();
|
||||
},
|
||||
);
|
||||
|
||||
addLog("success", "所有数据清空成功");
|
||||
await updateStats();
|
||||
} catch (error) {
|
||||
addLog("error", `清空数据失败: ${error}`);
|
||||
} finally {
|
||||
setIsRunning(false);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const runAllExamples = async () => {
|
||||
setIsRunning(true);
|
||||
addLog("info", "开始运行所有示例...");
|
||||
|
||||
try {
|
||||
await DatabaseExamples.runAllExamples();
|
||||
addLog("success", "所有示例运行完成");
|
||||
await updateStats();
|
||||
} catch (error) {
|
||||
addLog("error", `运行示例失败: ${error}`);
|
||||
} finally {
|
||||
setIsRunning(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
initDatabase();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ padding: "24px", maxWidth: "1200px", margin: "0 auto" }}>
|
||||
<Title level={2} style={{ textAlign: "center", marginBottom: "32px" }}>
|
||||
数据库操作演示
|
||||
</Title>
|
||||
|
||||
{/* 数据统计 */}
|
||||
<Row gutter={[16, 16]} style={{ marginBottom: "32px" }}>
|
||||
<Col xs={12} sm={6}>
|
||||
<Card>
|
||||
<Statistic
|
||||
title="客服用户"
|
||||
value={dbStats.kfUsers}
|
||||
prefix={<UserOutlined />}
|
||||
valueStyle={{ color: "#1890ff" }}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col xs={12} sm={6}>
|
||||
<Card>
|
||||
<Statistic
|
||||
title="群组"
|
||||
value={dbStats.groups}
|
||||
prefix={<TeamOutlined />}
|
||||
valueStyle={{ color: "#52c41a" }}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col xs={12} sm={6}>
|
||||
<Card>
|
||||
<Statistic
|
||||
title="联系人"
|
||||
value={dbStats.contracts}
|
||||
prefix={<ContactsOutlined />}
|
||||
valueStyle={{ color: "#faad14" }}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col xs={12} sm={6}>
|
||||
<Card>
|
||||
<Statistic
|
||||
title="联系人分组"
|
||||
value={dbStats.newContactList}
|
||||
prefix={<FolderOutlined />}
|
||||
valueStyle={{ color: "#722ed1" }}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{/* 操作按钮 */}
|
||||
<Card title="数据库操作" style={{ marginBottom: "24px" }}>
|
||||
<Space wrap size="middle">
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<UserOutlined />}
|
||||
onClick={runKfUserExample}
|
||||
loading={isRunning}
|
||||
size="large"
|
||||
>
|
||||
客服用户示例
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<TeamOutlined />}
|
||||
onClick={runGroupExample}
|
||||
loading={isRunning}
|
||||
size="large"
|
||||
style={{ backgroundColor: "#52c41a", borderColor: "#52c41a" }}
|
||||
>
|
||||
群组操作示例
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<ContactsOutlined />}
|
||||
onClick={runContractExample}
|
||||
loading={isRunning}
|
||||
size="large"
|
||||
style={{ backgroundColor: "#faad14", borderColor: "#faad14" }}
|
||||
>
|
||||
联系人示例
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<FolderOutlined />}
|
||||
onClick={runBatchExample}
|
||||
loading={isRunning}
|
||||
size="large"
|
||||
style={{ backgroundColor: "#722ed1", borderColor: "#722ed1" }}
|
||||
>
|
||||
批量操作示例
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlayCircleOutlined />}
|
||||
onClick={runAllExamples}
|
||||
loading={isRunning}
|
||||
size="large"
|
||||
style={{ backgroundColor: "#13c2c2", borderColor: "#13c2c2" }}
|
||||
>
|
||||
运行所有示例
|
||||
</Button>
|
||||
<Button
|
||||
danger
|
||||
icon={<DeleteOutlined />}
|
||||
onClick={clearAllData}
|
||||
loading={isRunning}
|
||||
size="large"
|
||||
>
|
||||
清空所有数据
|
||||
</Button>
|
||||
<Button
|
||||
danger
|
||||
icon={<ReloadOutlined />}
|
||||
onClick={async () => {
|
||||
Modal.confirm({
|
||||
title: "确认重置数据库",
|
||||
content:
|
||||
"确定要重置数据库吗?这将删除所有数据并重新创建数据库!",
|
||||
okText: "确定",
|
||||
cancelText: "取消",
|
||||
onOk: async () => {
|
||||
setIsRunning(true);
|
||||
try {
|
||||
const result = await resetDatabase();
|
||||
if (result.success) {
|
||||
addLog(
|
||||
"success",
|
||||
`数据库重置成功 - 版本: ${result.version}, 表: ${result.tables?.join(", ")}`,
|
||||
);
|
||||
await updateStats();
|
||||
} else {
|
||||
addLog("error", `数据库重置失败: ${result.error}`);
|
||||
}
|
||||
} catch (error) {
|
||||
addLog("error", `数据库重置失败: ${error}`);
|
||||
} finally {
|
||||
setIsRunning(false);
|
||||
}
|
||||
},
|
||||
});
|
||||
}}
|
||||
loading={isRunning}
|
||||
size="large"
|
||||
>
|
||||
重置数据库
|
||||
</Button>
|
||||
</Space>
|
||||
</Card>
|
||||
|
||||
{/* 运行状态 */}
|
||||
{isRunning && (
|
||||
<Alert
|
||||
message="操作进行中..."
|
||||
type="info"
|
||||
showIcon
|
||||
icon={<Spin />}
|
||||
style={{ marginBottom: "24px" }}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 日志显示 */}
|
||||
<Card
|
||||
title="操作日志"
|
||||
extra={
|
||||
<Button
|
||||
type="text"
|
||||
icon={<ReloadOutlined />}
|
||||
onClick={() => setLogs([])}
|
||||
size="small"
|
||||
>
|
||||
清空日志
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<div style={{ maxHeight: "400px", overflowY: "auto" }}>
|
||||
{logs.length === 0 ? (
|
||||
<div
|
||||
style={{ textAlign: "center", padding: "40px 0", color: "#999" }}
|
||||
>
|
||||
<Text type="secondary">暂无日志</Text>
|
||||
</div>
|
||||
) : (
|
||||
<Space direction="vertical" style={{ width: "100%" }} size="small">
|
||||
{logs.map(log => (
|
||||
<Alert
|
||||
key={log.id}
|
||||
message={
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "flex-start",
|
||||
}}
|
||||
>
|
||||
<span style={{ flex: 1 }}>{log.message}</span>
|
||||
<Text
|
||||
type="secondary"
|
||||
style={{ fontSize: "12px", marginLeft: "8px" }}
|
||||
>
|
||||
{log.timestamp}
|
||||
</Text>
|
||||
</div>
|
||||
}
|
||||
type={
|
||||
log.type === "success"
|
||||
? "success"
|
||||
: log.type === "error"
|
||||
? "error"
|
||||
: "info"
|
||||
}
|
||||
showIcon
|
||||
style={{ margin: 0 }}
|
||||
/>
|
||||
))}
|
||||
</Space>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DatabaseTestPage;
|
||||
@@ -1,3 +1,54 @@
|
||||
// 消息列表数据接口 - 支持weChatGroup和contracts两种数据类型
|
||||
export interface MessageListData {
|
||||
serverId: number | string; // 服务器ID作为主键
|
||||
id?: number; // 接口数据的原始ID字段
|
||||
|
||||
// 数据类型标识
|
||||
dataType: "weChatGroup" | "contracts"; // 数据类型:微信群组或联系人
|
||||
|
||||
// 通用字段(两种类型都有的字段)
|
||||
wechatAccountId: number; // 微信账号ID
|
||||
tenantId: number; // 租户ID
|
||||
accountId: number; // 账号ID
|
||||
nickname: string; // 昵称
|
||||
avatar?: string; // 头像
|
||||
groupId: number; // 分组ID
|
||||
config?: {
|
||||
chat: boolean;
|
||||
}; // 配置信息
|
||||
labels?: string[]; // 标签列表
|
||||
unreadCount: number; // 未读消息数
|
||||
|
||||
// 联系人特有字段(当dataType为'contracts'时使用)
|
||||
wechatId?: string; // 微信ID
|
||||
alias?: string; // 别名
|
||||
conRemark?: string; // 备注
|
||||
quanPin?: string; // 全拼
|
||||
gender?: number; // 性别
|
||||
region?: string; // 地区
|
||||
addFrom?: number; // 添加来源
|
||||
phone?: string; // 电话
|
||||
signature?: string; // 签名
|
||||
extendFields?: any; // 扩展字段
|
||||
city?: string; // 城市
|
||||
lastUpdateTime?: string; // 最后更新时间
|
||||
isPassed?: boolean; // 是否通过
|
||||
thirdParty?: any; // 第三方
|
||||
additionalPicture?: string; // 附加图片
|
||||
desc?: string; // 描述
|
||||
lastMessageTime?: number; // 最后消息时间
|
||||
duplicate?: boolean; // 是否重复
|
||||
|
||||
// 微信群组特有字段(当dataType为'weChatGroup'时使用)
|
||||
chatroomId?: string; // 群聊ID
|
||||
chatroomOwner?: string; // 群主
|
||||
chatroomAvatar?: string; // 群头像
|
||||
notice?: string; // 群公告
|
||||
selfDisplyName?: string; // 自己在群里的显示名称
|
||||
|
||||
[key: string]: any; // 兼容其他字段
|
||||
}
|
||||
|
||||
//联系人标签分组
|
||||
export interface ContactGroupByLabel {
|
||||
id: number;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import SelectTest from "@/pages/mobile/test/select";
|
||||
import TestIndex from "@/pages/mobile/test/index";
|
||||
import UploadTest from "@/pages/mobile/test/upload";
|
||||
import DbTest from "@/pages/mobile/test/db";
|
||||
import UpdateNotificationTest from "@/pages/mobile/test/update-notification";
|
||||
import IframeDebugPage from "@/pages/iframe";
|
||||
import { DEV_FEATURES } from "@/utils/env";
|
||||
@@ -34,11 +33,6 @@ const componentTestRoutes = DEV_FEATURES.SHOW_TEST_PAGES
|
||||
element: <IframeDebugPage />,
|
||||
auth: false, // 不需要认证,方便调试
|
||||
},
|
||||
{
|
||||
path: "/test/db",
|
||||
element: <DbTest />,
|
||||
auth: false, // 不需要认证,方便调试
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
|
||||
@@ -1,534 +0,0 @@
|
||||
import {
|
||||
db,
|
||||
kfUserService,
|
||||
weChatGroupService,
|
||||
contractService,
|
||||
DatabaseService,
|
||||
NewContactListData,
|
||||
} from "./db";
|
||||
import {
|
||||
KfUserListData,
|
||||
weChatGroup,
|
||||
ContractData,
|
||||
} from "@/pages/pc/ckbox/data";
|
||||
|
||||
// 创建 newContractList 服务实例
|
||||
const newContactListService = new DatabaseService(db.newContractList);
|
||||
|
||||
/**
|
||||
* 数据库使用示例
|
||||
*/
|
||||
export class DatabaseExamples {
|
||||
/**
|
||||
* 初始化数据库
|
||||
*/
|
||||
static async initDatabase() {
|
||||
try {
|
||||
await db.open();
|
||||
console.log("数据库初始化成功");
|
||||
} catch (error) {
|
||||
console.error("数据库初始化失败:", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 客服用户操作示例
|
||||
*/
|
||||
static async kfUserExamples() {
|
||||
console.log("=== 客服用户操作示例 ===");
|
||||
|
||||
// 模拟从接口获取的数据(包含服务器ID)
|
||||
const serverKfUser = {
|
||||
id: 1001, // 服务器返回的ID
|
||||
tenantId: 1,
|
||||
wechatId: "test_wechat_001",
|
||||
nickname: "测试客服",
|
||||
alias: "客服小王",
|
||||
avatar: "https://example.com/avatar.jpg",
|
||||
gender: 1,
|
||||
region: "北京",
|
||||
signature: "专业客服,为您服务",
|
||||
bindQQ: "123456789",
|
||||
bindEmail: "test@example.com",
|
||||
bindMobile: "13800138000",
|
||||
createTime: new Date().toISOString(),
|
||||
currentDeviceId: 1,
|
||||
isDeleted: false,
|
||||
deleteTime: "",
|
||||
groupId: 1,
|
||||
memo: "优秀客服",
|
||||
wechatVersion: "8.0.0",
|
||||
labels: ["VIP客服", "专业"],
|
||||
lastUpdateTime: new Date().toISOString(),
|
||||
isOnline: true,
|
||||
};
|
||||
|
||||
try {
|
||||
// 使用新方法添加客服用户(处理服务器ID映射)
|
||||
const userId = await kfUserService.createWithServerId(serverKfUser);
|
||||
console.log(
|
||||
"创建客服用户成功,本地ID:",
|
||||
userId,
|
||||
"服务器ID:",
|
||||
serverKfUser.id,
|
||||
);
|
||||
|
||||
// 查询单个用户(按本地ID)
|
||||
const user = await kfUserService.findById(userId);
|
||||
console.log("查询用户:", user);
|
||||
|
||||
// 根据服务器ID查询
|
||||
const userByServerId = await kfUserService.findByServerId(1001);
|
||||
console.log("根据服务器ID查询用户:", userByServerId);
|
||||
|
||||
// 按条件查询
|
||||
const onlineUsers = await kfUserService.findWhere("isOnline", true);
|
||||
console.log("在线用户数量:", onlineUsers.length);
|
||||
|
||||
// 按租户查询
|
||||
const tenantUsers = await kfUserService.findWhere("tenantId", 1);
|
||||
console.log("租户用户数量:", tenantUsers.length);
|
||||
|
||||
// 更新用户信息
|
||||
await kfUserService.update(userId, {
|
||||
nickname: "更新后的昵称",
|
||||
lastUpdateTime: new Date().toISOString(),
|
||||
});
|
||||
console.log("更新用户成功");
|
||||
|
||||
// 分页查询
|
||||
const paginatedUsers = await kfUserService.findWithPagination(1, 5);
|
||||
console.log("分页查询结果:", paginatedUsers);
|
||||
} catch (error) {
|
||||
console.error("客服用户操作失败:", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 群组操作示例
|
||||
*/
|
||||
static async groupExamples() {
|
||||
console.log("=== 群组操作示例 ===");
|
||||
|
||||
// 模拟从接口获取的群组数据
|
||||
const serverGroup = {
|
||||
id: 2001, // 服务器返回的ID
|
||||
wechatAccountId: 1,
|
||||
tenantId: 1,
|
||||
accountId: 1,
|
||||
chatroomId: "chatroom_001",
|
||||
chatroomOwner: "owner_001",
|
||||
conRemark: "测试群组",
|
||||
nickname: "产品讨论群",
|
||||
chatroomAvatar: "https://example.com/group-avatar.jpg",
|
||||
groupId: 1,
|
||||
config: {
|
||||
chat: true,
|
||||
},
|
||||
unreadCount: 0,
|
||||
notice: "欢迎加入产品讨论群",
|
||||
selfDisplyName: "群管理员",
|
||||
};
|
||||
|
||||
try {
|
||||
// 使用新方法创建群组
|
||||
const groupId = await weChatGroupService.createWithServerId(serverGroup);
|
||||
console.log(
|
||||
"创建群组成功,本地ID:",
|
||||
groupId,
|
||||
"服务器ID:",
|
||||
serverGroup.id,
|
||||
);
|
||||
|
||||
// 查询群组
|
||||
const groups = await weChatGroupService.findWhere("tenantId", 1);
|
||||
console.log("租户群组数量:", groups.length);
|
||||
|
||||
// 查询有未读消息的群组
|
||||
const unreadGroups = await weChatGroupService.findWhereGreaterThan(
|
||||
"unreadCount",
|
||||
0,
|
||||
);
|
||||
console.log("有未读消息的群组:", unreadGroups.length);
|
||||
|
||||
// 批量更新群组
|
||||
await weChatGroupService.updateMany([
|
||||
{
|
||||
id: groupId,
|
||||
data: { unreadCount: 5, notice: "更新的群公告" },
|
||||
},
|
||||
]);
|
||||
console.log("批量更新群组成功");
|
||||
} catch (error) {
|
||||
console.error("群组操作失败:", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 联系人操作示例
|
||||
*/
|
||||
static async contractExamples() {
|
||||
console.log("=== 联系人操作示例 ===");
|
||||
|
||||
// 模拟从接口获取的联系人数据
|
||||
const serverContract = {
|
||||
id: 3001, // 服务器返回的ID
|
||||
wechatAccountId: 1,
|
||||
wechatId: "contact_001",
|
||||
alias: "张三",
|
||||
conRemark: "重要客户",
|
||||
nickname: "张总",
|
||||
quanPin: "zhangsan",
|
||||
avatar: "https://example.com/contact-avatar.jpg",
|
||||
gender: 1,
|
||||
region: "上海",
|
||||
addFrom: 1,
|
||||
phone: "13900139000",
|
||||
labels: ["VIP客户", "重点关注"],
|
||||
signature: "专业人士",
|
||||
accountId: 1,
|
||||
extendFields: null,
|
||||
city: "上海",
|
||||
lastUpdateTime: new Date().toISOString(),
|
||||
isPassed: true,
|
||||
tenantId: 1,
|
||||
groupId: 1,
|
||||
thirdParty: null,
|
||||
additionalPicture: "",
|
||||
desc: "优质客户",
|
||||
config: {
|
||||
chat: true,
|
||||
},
|
||||
lastMessageTime: Date.now(),
|
||||
unreadCount: 0,
|
||||
duplicate: false,
|
||||
};
|
||||
|
||||
try {
|
||||
// 使用新方法创建联系人
|
||||
const contractId =
|
||||
await contractService.createWithServerId(serverContract);
|
||||
console.log(
|
||||
"创建联系人成功,本地ID:",
|
||||
contractId,
|
||||
"服务器ID:",
|
||||
serverContract.id,
|
||||
);
|
||||
|
||||
// 模糊查询(按昵称开头)
|
||||
const searchResults = await contractService.findWhereStartsWith(
|
||||
"nickname",
|
||||
"张",
|
||||
);
|
||||
console.log("姓张的联系人:", searchResults.length);
|
||||
|
||||
// 多条件查询
|
||||
const vipContacts = await contractService.findWhereMultiple([
|
||||
{ field: "tenantId", operator: "equals", value: 1 },
|
||||
{ field: "isPassed", operator: "equals", value: true },
|
||||
]);
|
||||
console.log("VIP联系人数量:", vipContacts.length);
|
||||
|
||||
// 按更新时间排序
|
||||
const sortedContacts = await contractService.findAllSorted(
|
||||
"lastUpdateTime",
|
||||
"desc",
|
||||
);
|
||||
console.log("最近更新的联系人:", sortedContacts.slice(0, 3));
|
||||
|
||||
// 统计联系人数量
|
||||
const totalCount = await contractService.count();
|
||||
const tenantCount = await contractService.countWhere("tenantId", 1);
|
||||
console.log(`总联系人数: ${totalCount}, 租户联系人数: ${tenantCount}`);
|
||||
} catch (error) {
|
||||
console.error("联系人操作失败:", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新联系人列表操作示例
|
||||
*/
|
||||
static async newContactListExamples() {
|
||||
console.log("=== 新联系人列表操作示例 ===");
|
||||
|
||||
// 模拟从接口获取的联系人分组数据
|
||||
const serverContactGroup = {
|
||||
id: 4001, // 服务器返回的ID
|
||||
groupName: "已购买",
|
||||
contacts: [
|
||||
{
|
||||
id: 3002, // 联系人的服务器ID
|
||||
wechatAccountId: 1,
|
||||
wechatId: "buyer_001",
|
||||
alias: "李四",
|
||||
conRemark: "已购买客户",
|
||||
nickname: "李总",
|
||||
quanPin: "lisi",
|
||||
gender: 1,
|
||||
region: "深圳",
|
||||
addFrom: 2,
|
||||
phone: "13700137000",
|
||||
labels: ["已购买"],
|
||||
signature: "企业家",
|
||||
accountId: 1,
|
||||
extendFields: null,
|
||||
lastUpdateTime: new Date().toISOString(),
|
||||
isPassed: true,
|
||||
tenantId: 1,
|
||||
groupId: 2,
|
||||
thirdParty: null,
|
||||
additionalPicture: "",
|
||||
desc: "已购买产品的客户",
|
||||
lastMessageTime: Date.now(),
|
||||
unreadCount: 0,
|
||||
duplicate: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
try {
|
||||
// 使用新方法创建联系人分组
|
||||
const groupId =
|
||||
await newContactListService.createWithServerId(serverContactGroup);
|
||||
console.log(
|
||||
"创建联系人分组成功,本地ID:",
|
||||
groupId,
|
||||
"服务器ID:",
|
||||
serverContactGroup.id,
|
||||
);
|
||||
|
||||
// 查询所有分组
|
||||
const allGroups = await newContactListService.findAll();
|
||||
console.log("所有联系人分组:", allGroups);
|
||||
|
||||
// 按分组名称查询
|
||||
const purchasedGroups = await newContactListService.findWhere(
|
||||
"groupName",
|
||||
"已购买",
|
||||
);
|
||||
console.log("已购买分组:", purchasedGroups);
|
||||
|
||||
// 更新分组(添加更多联系人)
|
||||
const updatedContacts = [
|
||||
...serverContactGroup.contacts,
|
||||
{
|
||||
id: 3003,
|
||||
wechatAccountId: 1,
|
||||
conRemark: "已购买客户",
|
||||
quanPin: "wangwu",
|
||||
gender: 1,
|
||||
region: "广州",
|
||||
addFrom: 2,
|
||||
phone: "13800000003",
|
||||
labels: ["已购买"],
|
||||
signature: "企业家",
|
||||
accountId: 1,
|
||||
extendFields: null,
|
||||
lastUpdateTime: new Date().toISOString(),
|
||||
isPassed: true,
|
||||
tenantId: 1,
|
||||
groupId: 2,
|
||||
thirdParty: null,
|
||||
additionalPicture: "",
|
||||
desc: "已购买产品的客户",
|
||||
lastMessageTime: Date.now(),
|
||||
unreadCount: 0,
|
||||
duplicate: false,
|
||||
wechatId: "buyer_002",
|
||||
alias: "王五",
|
||||
nickname: "王总",
|
||||
} as ContractData,
|
||||
];
|
||||
|
||||
await newContactListService.update(groupId, {
|
||||
contacts: updatedContacts,
|
||||
});
|
||||
console.log("更新联系人分组成功");
|
||||
} catch (error) {
|
||||
console.error("新联系人列表操作失败:", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 高级查询示例
|
||||
*/
|
||||
static async advancedQueryExamples() {
|
||||
console.log("=== 高级查询示例 ===");
|
||||
|
||||
try {
|
||||
// 范围查询:查询最近一周更新的联系人
|
||||
const oneWeekAgo = new Date(
|
||||
Date.now() - 7 * 24 * 60 * 60 * 1000,
|
||||
).toISOString();
|
||||
const now = new Date().toISOString();
|
||||
const recentContacts = await contractService.findWhereBetween(
|
||||
"lastUpdateTime",
|
||||
oneWeekAgo,
|
||||
now,
|
||||
);
|
||||
console.log("最近一周更新的联系人:", recentContacts.length);
|
||||
|
||||
// IN 查询:查询指定租户的数据
|
||||
const tenantIds = [1, 2, 3];
|
||||
const multiTenantUsers = await kfUserService.findWhereIn(
|
||||
"tenantId",
|
||||
tenantIds,
|
||||
);
|
||||
console.log("多租户用户数量:", multiTenantUsers.length);
|
||||
|
||||
// 不等于查询:查询非删除状态的用户
|
||||
const activeUsers = await kfUserService.findWhereNot("isDeleted", true);
|
||||
console.log("活跃用户数量:", activeUsers.length);
|
||||
|
||||
// 复合条件查询:在线且有分组的用户
|
||||
const onlineGroupUsers = await kfUserService.findWhereMultiple([
|
||||
{ field: "isOnline", operator: "equals", value: true },
|
||||
{ field: "groupId", operator: "above", value: 0 },
|
||||
]);
|
||||
console.log("在线且有分组的用户:", onlineGroupUsers.length);
|
||||
} catch (error) {
|
||||
console.error("高级查询失败:", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量操作示例
|
||||
*/
|
||||
static async batchOperationExamples() {
|
||||
console.log("=== 批量操作示例 ===");
|
||||
|
||||
try {
|
||||
// 模拟从接口获取的批量联系人数据
|
||||
const batchServerContacts = [
|
||||
{
|
||||
id: 3003, // 服务器ID
|
||||
wechatAccountId: 1,
|
||||
wechatId: "batch_001",
|
||||
alias: "批量用户1",
|
||||
conRemark: "批量导入",
|
||||
nickname: "用户1",
|
||||
quanPin: "yonghu1",
|
||||
gender: 1,
|
||||
region: "北京",
|
||||
addFrom: 3,
|
||||
phone: "13800000001",
|
||||
labels: ["批量导入"],
|
||||
signature: "",
|
||||
accountId: 1,
|
||||
extendFields: null,
|
||||
lastUpdateTime: new Date().toISOString(),
|
||||
isPassed: true,
|
||||
tenantId: 1,
|
||||
groupId: 1,
|
||||
thirdParty: null,
|
||||
additionalPicture: "",
|
||||
desc: "批量导入的用户",
|
||||
lastMessageTime: Date.now(),
|
||||
unreadCount: 0,
|
||||
duplicate: false,
|
||||
},
|
||||
{
|
||||
id: 3004, // 服务器ID
|
||||
wechatAccountId: 1,
|
||||
wechatId: "batch_002",
|
||||
alias: "批量用户2",
|
||||
conRemark: "批量导入",
|
||||
nickname: "用户2",
|
||||
quanPin: "yonghu2",
|
||||
gender: 2,
|
||||
region: "上海",
|
||||
addFrom: 3,
|
||||
phone: "13800000002",
|
||||
labels: ["批量导入"],
|
||||
signature: "",
|
||||
accountId: 1,
|
||||
extendFields: null,
|
||||
lastUpdateTime: new Date().toISOString(),
|
||||
isPassed: true,
|
||||
tenantId: 1,
|
||||
groupId: 1,
|
||||
thirdParty: null,
|
||||
additionalPicture: "",
|
||||
desc: "批量导入的用户",
|
||||
lastMessageTime: Date.now(),
|
||||
unreadCount: 0,
|
||||
duplicate: false,
|
||||
},
|
||||
];
|
||||
|
||||
const batchIds =
|
||||
await contractService.createManyWithServerId(batchServerContacts);
|
||||
console.log("批量创建联系人成功,本地IDs:", batchIds);
|
||||
|
||||
// 批量更新
|
||||
const updateData = batchIds.map(id => ({
|
||||
id,
|
||||
data: {
|
||||
desc: "批量更新的描述",
|
||||
lastUpdateTime: new Date().toISOString(),
|
||||
},
|
||||
}));
|
||||
|
||||
await contractService.updateMany(updateData);
|
||||
console.log("批量更新成功");
|
||||
} catch (error) {
|
||||
console.error("批量操作失败:", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据清理示例
|
||||
*/
|
||||
static async dataCleanupExamples() {
|
||||
console.log("=== 数据清理示例 ===");
|
||||
|
||||
try {
|
||||
// 清理测试数据(谨慎使用)
|
||||
const testUsers = await kfUserService.findWhereStartsWith(
|
||||
"wechatId",
|
||||
"test_",
|
||||
);
|
||||
console.log("找到测试用户:", testUsers.length);
|
||||
|
||||
// 删除特定测试数据
|
||||
for (const user of testUsers) {
|
||||
if (user.id) {
|
||||
await kfUserService.delete(user.id);
|
||||
}
|
||||
}
|
||||
console.log("清理测试用户完成");
|
||||
|
||||
// 统计清理后的数据
|
||||
const remainingCount = await kfUserService.count();
|
||||
console.log("剩余用户数量:", remainingCount);
|
||||
} catch (error) {
|
||||
console.error("数据清理失败:", error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行所有示例
|
||||
*/
|
||||
static async runAllExamples() {
|
||||
console.log("开始运行数据库操作示例...");
|
||||
|
||||
await this.initDatabase();
|
||||
await this.kfUserExamples();
|
||||
await this.groupExamples();
|
||||
await this.contractExamples();
|
||||
await this.newContactListExamples();
|
||||
await this.advancedQueryExamples();
|
||||
await this.batchOperationExamples();
|
||||
// await this.dataCleanupExamples(); // 谨慎使用
|
||||
|
||||
console.log("所有示例运行完成!");
|
||||
}
|
||||
}
|
||||
|
||||
// 导出便捷方法
|
||||
export const runDatabaseExamples = () => DatabaseExamples.runAllExamples();
|
||||
|
||||
// 如果直接运行此文件,执行示例
|
||||
if (typeof window !== "undefined" && (window as any).__RUN_DB_EXAMPLES__) {
|
||||
runDatabaseExamples();
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
KfUserListData,
|
||||
weChatGroup,
|
||||
ContractData,
|
||||
MessageListData,
|
||||
} from "@/pages/pc/ckbox/data";
|
||||
|
||||
// 数据类型定义,使用serverId作为主键
|
||||
@@ -57,17 +58,6 @@ export interface NewContactListData {
|
||||
weChatGroup: weChatGroup[];
|
||||
}
|
||||
|
||||
// 消息列表数据接口
|
||||
export interface MessageListData extends Omit<ContractData, "id"> {
|
||||
serverId: number | string; // 服务器ID作为主键
|
||||
id?: number; // 接口数据的原始ID字段
|
||||
wechatAccountId: number; // 微信账号ID
|
||||
chatroomAvatar?: string; // 群头像
|
||||
chatroomName?: string; // 群名称
|
||||
chatroomId?: number; // 群ID
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
// 数据库类
|
||||
class CunkebaoDatabase extends Dexie {
|
||||
kfUsers!: Table<KfUserWithServerId>;
|
||||
@@ -88,6 +78,8 @@ class CunkebaoDatabase extends Dexie {
|
||||
contracts:
|
||||
"serverId, id, wechatAccountId, wechatId, alias, conRemark, nickname, quanPin, avatar, gender, region, addFrom, phone, signature, accountId, extendFields, city, lastUpdateTime, isPassed, tenantId, groupId, thirdParty, additionalPicture, desc, config, lastMessageTime, unreadCount, duplicate",
|
||||
newContractList: "serverId, id, groupName, contacts",
|
||||
messageList:
|
||||
"serverId, id, dataType, wechatAccountId, tenantId, accountId, nickname, avatar, groupId, config, labels, unreadCount, wechatId, alias, conRemark, quanPin, gender, region, addFrom, phone, signature, extendFields, city, lastUpdateTime, isPassed, thirdParty, additionalPicture, desc, lastMessageTime, duplicate, chatroomId, chatroomOwner, chatroomAvatar, notice, selfDisplyName",
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -330,6 +322,8 @@ export class DatabaseService<T> {
|
||||
export const kfUserService = new DatabaseService(db.kfUsers);
|
||||
export const weChatGroupService = new DatabaseService(db.weChatGroup);
|
||||
export const contractService = new DatabaseService(db.contracts);
|
||||
export const newContactListService = new DatabaseService(db.newContractList);
|
||||
export const messageListService = new DatabaseService(db.messageList);
|
||||
|
||||
// 默认导出数据库实例
|
||||
export default db;
|
||||
|
||||
Reference in New Issue
Block a user