添加用户消息记录接口;

This commit is contained in:
karlcarlo
2025-12-11 03:53:47 +08:00
parent 6029da058a
commit 420fed4bcf
49 changed files with 7574 additions and 426 deletions

546
frontend/web/index.html Normal file
View File

@@ -0,0 +1,546 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>企业微信 JSSDK 测试</title>
<!-- 引入企业微信 JSSDK -->
<script src="https://wwcdn.weixin.qq.com/node/open/js/wecom-jssdk-2.3.3.js"></script>
</head>
<body>
<h1>企业微信 JSSDK 测试页面</h1>
<p>此页面用于测试企业微信 JSSDK 是否加载成功。</p>
<p>如果 JSSDK 加载成功,将会显示 SDK 版本号。</p>
<h2>Access Token(自动获取)</h2>
<div>
<p style="color: #666; font-style: italic;">页面加载时自动获取Access Token...</p>
<div id="tokenResult" style="margin-top: 20px; padding: 10px; border: 1px solid #ccc; border-radius: 5px; background-color: #f9f9f9;">
<h3>Access Token 结果:</h3>
<pre id="tokenData">获取中...</pre>
</div>
</div>
<h2>JSAPI Ticket(自动获取)</h2>
<div>
<p style="color: #666; font-style: italic;">页面加载时自动获取JSAPI Ticket...</p>
<div id="ticketResult" style="margin-top: 20px; padding: 10px; border: 1px solid #ccc; border-radius: 5px; background-color: #f9f9f9;">
<h3>JSAPI Ticket 结果:</h3>
<pre id="ticketData">获取中...</pre>
</div>
</div>
<h2>获取页面场景</h2>
<div>
<button id="getContextBtn">获取页面场景</button>
<div id="contextResult" style="margin-top: 20px; padding: 10px; border: 1px solid #ccc; border-radius: 5px; background-color: #f9f9f9; display: none;">
<h3>页面场景结果:</h3>
<pre id="contextData"></pre>
</div>
</div>
<h2>获取当前客户ID</h2>
<div>
<button id="getCustomerBtn">获取当前客户ID</button>
<div id="customerResult" style="margin-top: 20px; padding: 10px; border: 1px solid #ccc; border-radius: 5px; background-color: #f9f9f9; display: none;">
<h3>当前客户ID结果:</h3>
<pre id="customerData"></pre>
</div>
</div>
<h2>发送消息到当前会话</h2>
<div>
<div style="margin-bottom: 15px;">
<label for="messageContent" style="display: block; margin-bottom: 5px; font-weight: bold;">消息内容:</label>
<textarea id="messageContent" rows="4" style="width: 100%; padding: 10px; border: 1px solid #ccc; border-radius: 5px; font-family: monospace;" placeholder="请输入要发送的消息内容...">你好,这是一条测试消息!</textarea>
</div>
<button id="sendMessageBtn">发送消息到当前会话</button>
<div id="messageResult" style="margin-top: 20px; padding: 10px; border: 1px solid #ccc; border-radius: 5px; background-color: #f9f9f9; display: none;">
<h3>消息发送结果:</h3>
<pre id="messageData"></pre>
</div>
</div>
<!-- 测试代码 -->
<script>
// 函数定义
async function getConfigSignature(url) {
// 根据 url 生成企业签名
// 生成方法参考 https://developer.work.weixin.qq.com/document/14924
// 暂时返回简单实现,主要关注应用签名
const timestamp = Math.floor(Date.now() / 1000);
const nonceStr = Math.random().toString(36).substring(2, 15);
return { timestamp, nonceStr, signature: 'temp_signature' };
}
async function getAgentConfigSignature(url) {
// 根据 url 生成应用签名
// 注意:企业微信要求url必须是调用JSAPI页面的完整URL,不包含#及其后面部分
try {
// 清理URL,移除#及其后面的部分
const cleanUrl = url.split('#')[0];
console.log('生成签名,原始URL:', url, '清理后URL:', cleanUrl);
// 使用线上地址
const apiBaseUrl = 'http://mp.yizhezhe.com';
const apiUrl = `${apiBaseUrl}/api/auth/signature`;
console.log('调用签名API:', apiUrl);
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
url: cleanUrl,
timestamp: Math.floor(Date.now() / 1000),
nonceStr: Math.random().toString(36).substring(2, 15)
})
});
const result = await response.json();
if (result.success) {
console.log('签名生成成功:', result.data);
console.log('签名详情:', {
url: cleanUrl,
timestamp: result.data.timestamp,
nonceStr: result.data.nonceStr,
signature: result.data.signature
});
return result.data;
} else {
console.error('签名生成失败:', result.message);
throw new Error(result.message);
}
} catch (error) {
console.error('调用签名API失败:', error);
// 返回一个简单的签名用于测试
const timestamp = Math.floor(Date.now() / 1000);
const nonceStr = Math.random().toString(36).substring(2, 15);
return { timestamp, nonceStr, signature: 'error_signature' };
}
}
// 自动获取 Access Token 函数
async function autoFetchAccessToken() {
console.log('开始自动获取 Access Token...');
const tokenDataElement = document.getElementById('tokenData');
const tokenResultElement = document.getElementById('tokenResult');
try {
// 更新状态
tokenDataElement.textContent = '正在获取...';
tokenDataElement.style.color = '#666';
// 获取 access_token 的 API 端点
const apiUrl = 'http://mp.yizhezhe.com/api/auth/token';
console.log('正在调用 API:', apiUrl);
// 使用 fetch 调用 API
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error(`HTTP 错误: ${response.status}`);
}
const data = await response.json();
console.log('Access Token 获取成功:', data);
// 更新页面显示
if (data.success === true) {
tokenDataElement.textContent = JSON.stringify(data, null, 2);
tokenDataElement.style.color = '#333';
console.log(`Access Token 获取成功!${data.message}`);
console.log('Access Token 数据:', JSON.stringify(data, null, 2));
// 添加成功样式
tokenResultElement.style.borderColor = '#4CAF50';
tokenResultElement.style.backgroundColor = '#f8fff8';
} else {
tokenDataElement.textContent = `获取失败: ${data.message}\n\n返回数据: ${JSON.stringify(data, null, 2)}`;
tokenDataElement.style.color = '#d32f2f';
console.error(`获取 Access Token 失败: ${data.message}`);
// 添加错误样式
tokenResultElement.style.borderColor = '#f44336';
tokenResultElement.style.backgroundColor = '#fff8f8';
}
return data;
} catch (error) {
console.error('获取 Access Token 失败:', error);
console.error('错误详情:', error.message);
// 更新页面显示错误
tokenDataElement.textContent = `错误: ${error.message}\n\n请检查网络连接或后端服务状态。`;
tokenDataElement.style.color = '#d32f2f';
// 添加错误样式
tokenResultElement.style.borderColor = '#f44336';
tokenResultElement.style.backgroundColor = '#fff8f8';
return null;
}
}
// 自动获取 JSAPI Ticket 函数
async function autoFetchJsapiTicket() {
console.log('开始自动获取 JSAPI Ticket...');
const ticketDataElement = document.getElementById('ticketData');
const ticketResultElement = document.getElementById('ticketResult');
try {
// 更新状态
ticketDataElement.textContent = '正在获取...';
ticketDataElement.style.color = '#666';
// 获取 jsapi_ticket 的 API 端点 - 使用线上地址
const apiUrl = 'http://mp.yizhezhe.com/api/auth/ticket';
console.log('正在调用 API:', apiUrl);
// 使用 fetch 调用 API
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error(`HTTP 错误: ${response.status}`);
}
const data = await response.json();
console.log('JSAPI Ticket 获取成功:', data);
// 更新页面显示
if (data.success === true) {
ticketDataElement.textContent = JSON.stringify(data, null, 2);
ticketDataElement.style.color = '#333';
console.log(`JSAPI Ticket 获取成功!${data.message}`);
console.log('JSAPI Ticket 数据:', JSON.stringify(data, null, 2));
// 添加成功样式
ticketResultElement.style.borderColor = '#4CAF50';
ticketResultElement.style.backgroundColor = '#f8fff8';
} else {
ticketDataElement.textContent = `获取失败: ${data.message}\n\n返回数据: ${JSON.stringify(data, null, 2)}`;
ticketDataElement.style.color = '#d32f2f';
console.error(`获取 JSAPI Ticket 失败: ${data.message}`);
// 添加错误样式
ticketResultElement.style.borderColor = '#f44336';
ticketResultElement.style.backgroundColor = '#fff8f8';
}
return data;
} catch (error) {
console.error('获取 JSAPI Ticket 失败:', error);
console.error('错误详情:', error.message);
// 更新页面显示错误
ticketDataElement.textContent = `错误: ${error.message}\n\n请检查网络连接或后端服务状态。`;
ticketDataElement.style.color = '#d32f2f';
// 添加错误样式
ticketResultElement.style.borderColor = '#f44336';
ticketResultElement.style.backgroundColor = '#fff8f8';
return null;
}
}
// DOMContentLoaded 事件处理
document.addEventListener('DOMContentLoaded', function() {
console.log('DOMContentLoaded: 开始初始化页面...');
// 1. 检查并注册 JSSDK
console.log('检查 JSSDK...');
if (typeof ww !== 'undefined') {
console.log('企业微信 JSSDK 版本:', ww.SDK_VERSION);
console.log('JSSDK 对象已加载:', ww);
// 注册 JSSDK(不等待回调,让 JSSDK 自行处理)
console.log('开始注册 JSSDK...');
ww.register({
corpId: 'ww45bb49a9d651b2bb', // 必填,当前用户企业所属企业ID,从.env文件获取
agentId: 1000061, // 必填,当前应用的AgentID,从.env文件获取
jsApiList: ['getContext', 'getCurExternalContact', 'sendChatMessage'], // 必填,需要使用的JSAPI列表
getConfigSignature, // 必填,根据url生成企业签名的回调函数
getAgentConfigSignature // 必填,根据url生成应用签名的回调函数
// 不设置 success 和 fail 回调,让按钮直接调用接口
});
console.log('JSSDK 注册调用完成');
// 2. 自动获取 Access Token 和 JSAPI Ticket
console.log('开始自动获取认证信息...');
autoFetchAccessToken();
autoFetchJsapiTicket();
} else {
console.error('错误: 企业微信 JSSDK 未加载成功!');
console.error('请检查网络或刷新页面。');
}
// 获取页面场景功能
const getContextBtn = document.getElementById('getContextBtn');
const contextResult = document.getElementById('contextResult');
const contextData = document.getElementById('contextData');
if (getContextBtn) {
console.log('找到获取页面场景按钮,绑定点击事件');
// 初始时直接启用按钮
getContextBtn.disabled = false;
getContextBtn.textContent = '获取页面场景';
getContextBtn.addEventListener('click', function() {
console.log('点击获取页面场景按钮');
// 直接调用,不检查注册状态
getContextBtn.disabled = true;
getContextBtn.textContent = '获取中...';
console.log('直接调用 ww.getContext()...');
console.log('检查 ww 对象:', typeof ww);
console.log('检查 ww.getContext:', typeof ww.getContext);
if (typeof ww === 'undefined') {
alert('错误: ww 对象未定义,JSSDK 未加载成功!');
getContextBtn.disabled = false;
getContextBtn.textContent = '获取页面场景';
return;
}
if (typeof ww.getContext !== 'function') {
alert('错误: ww.getContext 不是函数,请检查 jsApiList 是否包含 getContext');
getContextBtn.disabled = false;
getContextBtn.textContent = '获取页面场景';
return;
}
// 调用企业微信 JSSDK 的 getContext 方法
ww.getContext({
success: function(res) {
console.log('获取页面场景成功:', res);
// 显示结果
contextData.textContent = JSON.stringify(res, null, 2);
contextResult.style.display = 'block';
// 解析场景信息
let sceneInfo = '未知场景';
if (res.entry) {
sceneInfo = `入口: ${res.entry}`;
}
if (res.scene) {
sceneInfo += `, 场景: ${res.scene}`;
}
if (res.chatId) {
sceneInfo += `, 聊天ID: ${res.chatId}`;
}
alert(`获取页面场景成功!\n${sceneInfo}`);
},
fail: function(err) {
console.error('获取页面场景失败:', err);
contextData.textContent = `错误: ${JSON.stringify(err, null, 2)}`;
contextResult.style.display = 'block';
alert('获取页面场景失败: ' + (err.errMsg || '未知错误'));
},
complete: function() {
console.log('getContext 调用完成');
getContextBtn.disabled = false;
getContextBtn.textContent = '获取页面场景';
}
});
});
} else {
console.error('未找到获取页面场景按钮!');
}
// 获取当前客户ID功能
const getCustomerBtn = document.getElementById('getCustomerBtn');
const customerResult = document.getElementById('customerResult');
const customerData = document.getElementById('customerData');
if (getCustomerBtn) {
console.log('找到获取当前客户ID按钮,绑定点击事件');
// 初始时直接启用按钮
getCustomerBtn.disabled = false;
getCustomerBtn.textContent = '获取当前客户ID';
getCustomerBtn.addEventListener('click', function() {
console.log('点击获取当前客户ID按钮');
// 直接调用,不检查注册状态
getCustomerBtn.disabled = true;
getCustomerBtn.textContent = '获取中...';
console.log('准备调用 ww.getCurExternalContact()...');
console.log('检查 ww 对象:', typeof ww);
console.log('检查 ww.getCurExternalContact:', typeof ww.getCurExternalContact);
if (typeof ww === 'undefined') {
alert('错误: ww 对象未定义,JSSDK 未加载成功!');
getCustomerBtn.disabled = false;
getCustomerBtn.textContent = '获取当前客户ID';
return;
}
if (typeof ww.getCurExternalContact !== 'function') {
alert('错误: ww.getCurExternalContact 不是函数,请检查 jsApiList 是否包含 getCurExternalContact');
getCustomerBtn.disabled = false;
getCustomerBtn.textContent = '获取当前客户ID';
return;
}
// 调用企业微信 JSSDK 的 getCurExternalContact 方法
ww.getCurExternalContact({
success: function(res) {
console.log('获取当前客户ID成功:', res);
// 显示结果
customerData.textContent = JSON.stringify(res, null, 2);
customerResult.style.display = 'block';
// 解析客户信息
let customerInfo = '未知客户';
if (res.externalUserId) {
customerInfo = `客户ID: ${res.externalUserId}`;
}
if (res.nickname) {
customerInfo += `, 昵称: ${res.nickname}`;
}
if (res.avatar) {
customerInfo += `, 有头像`;
}
if (res.corpName) {
customerInfo += `, 企业: ${res.corpName}`;
}
alert(`获取当前客户ID成功!\n${customerInfo}`);
},
fail: function(err) {
console.error('获取当前客户ID失败:', err);
customerData.textContent = `错误: ${JSON.stringify(err, null, 2)}`;
customerResult.style.display = 'block';
alert('获取当前客户ID失败: ' + (err.errMsg || '未知错误'));
},
cancel: function() {
console.log('用户取消了获取当前客户ID操作');
alert('用户取消了获取当前客户ID操作');
getCustomerBtn.disabled = false;
getCustomerBtn.textContent = '获取当前客户ID';
},
complete: function() {
console.log('getCurExternalContact 调用完成');
getCustomerBtn.disabled = false;
getCustomerBtn.textContent = '获取当前客户ID';
}
});
});
} else {
console.error('未找到获取当前客户ID按钮!');
}
// 发送消息到当前会话功能
const sendMessageBtn = document.getElementById('sendMessageBtn');
const messageResult = document.getElementById('messageResult');
const messageData = document.getElementById('messageData');
const messageContent = document.getElementById('messageContent');
if (sendMessageBtn) {
console.log('找到发送消息按钮,绑定点击事件');
// 初始时直接启用按钮
sendMessageBtn.disabled = false;
sendMessageBtn.textContent = '发送消息到当前会话';
sendMessageBtn.addEventListener('click', function() {
console.log('点击发送消息按钮');
// 获取消息内容
const content = messageContent.value.trim();
if (!content) {
alert('错误: 消息内容不能为空!');
return;
}
// 直接调用,不检查注册状态
sendMessageBtn.disabled = true;
sendMessageBtn.textContent = '发送中...';
console.log('准备调用 ww.sendChatMessage()...');
console.log('检查 ww 对象:', typeof ww);
console.log('检查 ww.sendChatMessage:', typeof ww.sendChatMessage);
console.log('消息内容:', content);
if (typeof ww === 'undefined') {
alert('错误: ww 对象未定义,JSSDK 未加载成功!');
sendMessageBtn.disabled = false;
sendMessageBtn.textContent = '发送消息到当前会话';
return;
}
if (typeof ww.sendChatMessage !== 'function') {
alert('错误: ww.sendChatMessage 不是函数,请检查 jsApiList 是否包含 sendChatMessage');
sendMessageBtn.disabled = false;
sendMessageBtn.textContent = '发送消息到当前会话';
return;
}
// 调用企业微信 JSSDK 的 sendChatMessage 方法
ww.sendChatMessage({
msgtype: 'text',
text: {
content: content
},
success: function(res) {
console.log('发送消息成功:', res);
// 显示结果
messageData.textContent = JSON.stringify(res, null, 2);
messageResult.style.display = 'block';
// 解析发送结果
let resultInfo = '消息发送成功!';
if (res.errCode === 0) {
resultInfo = `消息发送成功!\n错误码: ${res.errCode}, 错误信息: ${res.errMsg || '无'}`;
} else {
resultInfo = `消息发送失败!\n错误码: ${res.errCode}, 错误信息: ${res.errMsg || '未知错误'}`;
}
alert(resultInfo);
},
fail: function(err) {
console.error('发送消息失败:', err);
messageData.textContent = `错误: ${JSON.stringify(err, null, 2)}`;
messageResult.style.display = 'block';
alert('发送消息失败: ' + (err.errMsg || '未知错误'));
},
cancel: function() {
console.log('用户取消了发送消息操作');
alert('用户取消了发送消息操作');
sendMessageBtn.disabled = false;
sendMessageBtn.textContent = '发送消息到当前会话';
},
complete: function() {
console.log('sendChatMessage 调用完成');
sendMessageBtn.disabled = false;
sendMessageBtn.textContent = '发送消息到当前会话';
}
});
});
} else {
console.error('未找到发送消息按钮!');
}
});
</script>
<footer>
<p>企业微信 JSSDK 测试 - 开发环境</p>
</footer>
</body>
</html>