整理:清除无用结构
This commit is contained in:
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"version": 1,
|
|
||||||
"isRoot": true,
|
|
||||||
"tools": {
|
|
||||||
"dotnet-ef": {
|
|
||||||
"version": "9.0.10",
|
|
||||||
"commands": [
|
|
||||||
"dotnet-ef"
|
|
||||||
],
|
|
||||||
"rollForward": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
35
WxCheckApi/.vscode/launch.json
vendored
35
WxCheckApi/.vscode/launch.json
vendored
@@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
// 使用 IntelliSense 找出 C# 调试存在哪些属性
|
|
||||||
// 将悬停用于现有属性的说明
|
|
||||||
// 有关详细信息,请访问 https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md。
|
|
||||||
"name": ".NET Core Launch (web)",
|
|
||||||
"type": "coreclr",
|
|
||||||
"request": "launch",
|
|
||||||
"preLaunchTask": "build",
|
|
||||||
// 如果已更改目标框架,请确保更新程序路径。
|
|
||||||
"program": "${workspaceFolder}/bin/Debug/net8.0/WxCheckApi.dll",
|
|
||||||
"args": [],
|
|
||||||
"cwd": "${workspaceFolder}",
|
|
||||||
"stopAtEntry": false,
|
|
||||||
// 启用在启动 ASP.NET Core 时启动 Web 浏览器。有关详细信息: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
|
|
||||||
"serverReadyAction": {
|
|
||||||
"action": "openExternally",
|
|
||||||
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
|
|
||||||
},
|
|
||||||
"env": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
},
|
|
||||||
"sourceFileMap": {
|
|
||||||
"/Views": "${workspaceFolder}/Views"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": ".NET Core Attach",
|
|
||||||
"type": "coreclr",
|
|
||||||
"request": "attach"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
41
WxCheckApi/.vscode/tasks.json
vendored
41
WxCheckApi/.vscode/tasks.json
vendored
@@ -1,41 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "2.0.0",
|
|
||||||
"tasks": [
|
|
||||||
{
|
|
||||||
"label": "build",
|
|
||||||
"command": "dotnet",
|
|
||||||
"type": "process",
|
|
||||||
"args": [
|
|
||||||
"build",
|
|
||||||
"${workspaceFolder}/WxCheckApi.csproj",
|
|
||||||
"/property:GenerateFullPaths=true",
|
|
||||||
"/consoleloggerparameters:NoSummary;ForceNoAlign"
|
|
||||||
],
|
|
||||||
"problemMatcher": "$msCompile"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "publish",
|
|
||||||
"command": "dotnet",
|
|
||||||
"type": "process",
|
|
||||||
"args": [
|
|
||||||
"publish",
|
|
||||||
"${workspaceFolder}/WxCheckApi.csproj",
|
|
||||||
"/property:GenerateFullPaths=true",
|
|
||||||
"/consoleloggerparameters:NoSummary;ForceNoAlign"
|
|
||||||
],
|
|
||||||
"problemMatcher": "$msCompile"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "watch",
|
|
||||||
"command": "dotnet",
|
|
||||||
"type": "process",
|
|
||||||
"args": [
|
|
||||||
"watch",
|
|
||||||
"run",
|
|
||||||
"--project",
|
|
||||||
"${workspaceFolder}/WxCheckApi.csproj"
|
|
||||||
],
|
|
||||||
"problemMatcher": "$msCompile"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,766 +0,0 @@
|
|||||||
# 微信小程序:语音信息打卡 API 接口文档
|
|
||||||
|
|
||||||
本文档详细描述了WxCheck项目中Login控制器和Check控制器的所有API接口,包括接口功能、请求参数、响应格式以及调用示例。
|
|
||||||
|
|
||||||
## 基础信息
|
|
||||||
|
|
||||||
- **API基础路径**:`https://wx-xcx-check.blv-oa.com:4433/api/[controller]/[action]`
|
|
||||||
- **请求方式**:POST
|
|
||||||
|
|
||||||
## 统一响应格式
|
|
||||||
|
|
||||||
所有接口返回以下统一格式的JSON响应:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true/false,
|
|
||||||
"message": "操作结果描述",
|
|
||||||
"data": {...}, // 可选,返回的具体数据
|
|
||||||
"error": "错误信息" // 可选,错误时返回
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 1. Login控制器接口
|
|
||||||
|
|
||||||
### 1.1 用户注册接口
|
|
||||||
|
|
||||||
#### 接口描述
|
|
||||||
用户信息更新功能,根据传入的UserKey更新用户的UserName、WeChatName和PhoneNumber信息。
|
|
||||||
|
|
||||||
#### 接口路径
|
|
||||||
`/api/Login/Register`
|
|
||||||
|
|
||||||
#### 请求参数
|
|
||||||
|
|
||||||
| 参数名 | 类型 | 必填 | 描述 |
|
|
||||||
|--------|------|------|------|
|
|
||||||
| UserName | string | 否 | 用户名(可以为空) |
|
|
||||||
| UserKey | string | 是 | 用户唯一标识键 |
|
|
||||||
| WeChatName | string | 否 | 微信名称 |
|
|
||||||
| PhoneNumber | string | 否 | 电话号码 |
|
|
||||||
| AvatarUrl | string | 否 | 头像地址 |
|
|
||||||
|
|
||||||
#### 请求示例
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"UserName": "张三",
|
|
||||||
"UserKey": "openid_from_wechat",
|
|
||||||
"WeChatName": "张三的微信",
|
|
||||||
"PhoneNumber": "13800138000",
|
|
||||||
"AvatarUrl": "https://example.com/avatar.jpg"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 响应示例
|
|
||||||
|
|
||||||
**成功响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"data": {
|
|
||||||
"Id": 1,
|
|
||||||
"UserName": "张三",
|
|
||||||
"UserKey": "openid_from_wechat",
|
|
||||||
"WeChatName": "张三的微信",
|
|
||||||
"PhoneNumber": "13800138000",
|
|
||||||
"AvatarUrl": "https://example.com/avatar.jpg",
|
|
||||||
"FirstLoginTime": "2023-10-31T10:00:00",
|
|
||||||
"IsDisabled": false,
|
|
||||||
"CreateTime": "2023-10-31T10:00:00",
|
|
||||||
"UpdateTime": "2023-10-31T15:30:00",
|
|
||||||
"Token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**失败响应:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "用户不存在"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "更新用户信息失败",
|
|
||||||
"error": "数据库连接错误"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.2 用户登录接口
|
|
||||||
|
|
||||||
#### 接口描述
|
|
||||||
用户登录功能,将微信小程序code转换为OpenID并验证用户身份。如果用户不存在,则自动创建新用户记录。无论用户是否存在,都返回完整的用户信息和Token。
|
|
||||||
|
|
||||||
#### 接口路径
|
|
||||||
`/api/Login/Login`
|
|
||||||
|
|
||||||
#### 请求参数
|
|
||||||
|
|
||||||
| 参数名 | 类型 | 必填 | 描述 |
|
|
||||||
|--------|------|------|------|
|
|
||||||
| Code | string | 是 | 微信小程序登录凭证code,用于获取OpenID |
|
|
||||||
|
|
||||||
#### 请求示例
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"Code": "wx_login_code_here"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 响应示例
|
|
||||||
|
|
||||||
**成功响应(已存在用户):**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"data": {
|
|
||||||
"Id": 1,
|
|
||||||
"UserName": "张三",
|
|
||||||
"UserKey": "openid_from_wechat",
|
|
||||||
"WeChatName": "张三的微信",
|
|
||||||
"PhoneNumber": "13800138000",
|
|
||||||
"AvatarUrl": "https://example.com/avatar.jpg",
|
|
||||||
"FirstLoginTime": "2023-10-31T10:00:00",
|
|
||||||
"IsDisabled": false,
|
|
||||||
"CreateTime": "2023-10-31T10:00:00",
|
|
||||||
"UpdateTime": "2023-10-31T10:00:00",
|
|
||||||
"Token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**成功响应(新用户自动注册):**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"data": {
|
|
||||||
"Id": 2,
|
|
||||||
"UserName": "",
|
|
||||||
"UserKey": "new_openid_from_wechat",
|
|
||||||
"WeChatName": "",
|
|
||||||
"PhoneNumber": "",
|
|
||||||
"AvatarUrl": "",
|
|
||||||
"FirstLoginTime": "2023-10-31T16:00:00",
|
|
||||||
"IsDisabled": false,
|
|
||||||
"CreateTime": "2023-10-31T16:00:00",
|
|
||||||
"UpdateTime": "2023-10-31T16:00:00",
|
|
||||||
"Token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**失败响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "用户已被禁用"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "获取微信OpenID失败",
|
|
||||||
"error": "微信API调用失败"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 2. Check控制器接口
|
|
||||||
|
|
||||||
### 2.1 检查地址接口
|
|
||||||
|
|
||||||
#### 接口描述
|
|
||||||
根据会话记录的GUID查询经纬度信息,并转换为详细地址更新到数据库中。
|
|
||||||
|
|
||||||
#### 接口路径
|
|
||||||
`/api/Check/CheckAddress`
|
|
||||||
|
|
||||||
#### 请求参数
|
|
||||||
|
|
||||||
| 参数名 | 类型 | 必填 | 描述 |
|
|
||||||
|--------|------|------|------|
|
|
||||||
| Guid | string | 是 | 会话唯一标识 |
|
|
||||||
|
|
||||||
#### 请求示例
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"Guid": "会话唯一标识"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 响应示例
|
|
||||||
|
|
||||||
**成功响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"message": "地址更新成功",
|
|
||||||
"address": "北京市海淀区中关村南大街5号"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**失败响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "记录不存在或已被删除"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "更新失败",
|
|
||||||
"error": "数据库操作错误"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.2 添加会话记录接口
|
|
||||||
|
|
||||||
#### 接口描述
|
|
||||||
添加新的会话记录到系统中。
|
|
||||||
|
|
||||||
#### 接口路径
|
|
||||||
`/api/Check/AddConversation`
|
|
||||||
|
|
||||||
#### 请求参数
|
|
||||||
|
|
||||||
| 参数名 | 类型 | 必填 | 描述 |
|
|
||||||
|--------|------|------|------|
|
|
||||||
| UserKey | string | 是 | 用户唯一标识键 |
|
|
||||||
| ConversationContent | string | 是 | 会话内容 |
|
|
||||||
| SendMethod | string | 是 | 发送方式 |
|
|
||||||
| UserLocation | string | 否 | 用户定位信息(经纬度格式:"纬度,经度") |
|
|
||||||
| MessageType | int | 否 | 1:公有消息,2:私有消息 |
|
|
||||||
| Guid | string | 否 | 会话唯一标识(不提供则系统自动生成) |
|
|
||||||
|
|
||||||
#### 请求示例
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"UserKey": "user_123456",
|
|
||||||
"ConversationContent": "这是一条测试消息",
|
|
||||||
"SendMethod": "文本",
|
|
||||||
"UserLocation": "39.9087,116.3975",
|
|
||||||
"MessageType": 1
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 响应示例
|
|
||||||
|
|
||||||
**成功响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"message": "收到!",
|
|
||||||
"conversationGuid": "会话唯一标识",
|
|
||||||
"receivedTime": "2023-10-31 10:05:00"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**失败响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "发送失败",
|
|
||||||
"error": "数据库操作错误"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.3 查询会话记录接口
|
|
||||||
|
|
||||||
#### 接口描述
|
|
||||||
根据用户唯一标识键查询该用户的所有会话记录。
|
|
||||||
|
|
||||||
#### 接口路径
|
|
||||||
`https://wx-xcx-check.blv-oa.com/api/Check/GetConversations`
|
|
||||||
|
|
||||||
#### 请求参数
|
|
||||||
|
|
||||||
| 参数名 | 类型 | 必填 | 描述 |
|
|
||||||
|--------|------|------|------|
|
|
||||||
| UserKey | string | 是 | 用户唯一标识键 |
|
|
||||||
| MessageType | int | 否 | 0:不判断消息类型(默认),1:只返回公有消息,2:只返回私有消息 |
|
|
||||||
|
|
||||||
#### 请求示例
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"UserKey": "user_123456",
|
|
||||||
"MessageType": 0
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 响应示例
|
|
||||||
|
|
||||||
**成功响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"Id": 1,
|
|
||||||
"Guid": "会话唯一标识",
|
|
||||||
"UserKey": "user_123456",
|
|
||||||
"ConversationContent": "这是一条测试消息",
|
|
||||||
"SendMethod": "文本",
|
|
||||||
"UserLocation": "北京市海淀区",
|
|
||||||
"Latitude": "39.9087",
|
|
||||||
"Longitude": "116.3975",
|
|
||||||
"RecordTime": "2023-10-31T10:05:00",
|
|
||||||
"RecordTimeUTCStamp": 1698732300000,
|
|
||||||
"IsDeleted": false,
|
|
||||||
"CreateTime": "2023-10-31T10:05:00",
|
|
||||||
"MessageType": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 2,
|
|
||||||
"Guid": "会话唯一标识",
|
|
||||||
"UserKey": "user_123456",
|
|
||||||
"ConversationContent": "这是第二条测试消息",
|
|
||||||
"SendMethod": "图片",
|
|
||||||
"UserLocation": "北京市朝阳区",
|
|
||||||
"Latitude": "39.9180",
|
|
||||||
"Longitude": "116.4272",
|
|
||||||
"RecordTime": "2023-10-31T10:06:00",
|
|
||||||
"RecordTimeUTCStamp": 1698732360000,
|
|
||||||
"IsDeleted": false,
|
|
||||||
"CreateTime": "2023-10-31T10:06:00",
|
|
||||||
"MessageType": 2
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**失败响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "查询失败",
|
|
||||||
"error": "数据库连接错误"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.4 分页查询会话记录接口
|
|
||||||
|
|
||||||
#### 接口描述
|
|
||||||
分页查询用户的会话记录,每页默认10条,按时间戳从**最新到最旧**排序,支持根据消息类型进行过滤。
|
|
||||||
|
|
||||||
#### 接口路径
|
|
||||||
`https://wx-xcx-check.blv-oa.com:4433/api/Check/GetConversationsByPage`
|
|
||||||
|
|
||||||
#### 请求参数
|
|
||||||
|
|
||||||
| 参数名 | 类型 | 必填 | 描述 |
|
|
||||||
|--------|------|------|------|
|
|
||||||
| UserKey | string | 是 | 用户唯一标识键 |
|
|
||||||
| Page | int | 否 | 页码,默认为1,小于1时自动设为1 |
|
|
||||||
| PageSize | int | 否 | 每页数量,默认为10,最大100,小于1时自动设为10 |
|
|
||||||
| MessageType | int | 否 | 0:不判断消息类型(默认),1:只返回公有消息,2:只返回私有消息 |
|
|
||||||
|
|
||||||
#### 请求示例
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"UserKey": "user_123456",
|
|
||||||
"Page": 1,
|
|
||||||
"PageSize": 10,
|
|
||||||
"MessageType": 0
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 响应示例
|
|
||||||
|
|
||||||
**成功响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"data": {
|
|
||||||
"conversations": [
|
|
||||||
{
|
|
||||||
"Id": 1,
|
|
||||||
"Guid": "会话唯一标识",
|
|
||||||
"UserKey": "user_123456",
|
|
||||||
"ConversationContent": "这是一条测试消息",
|
|
||||||
"SendMethod": "文本",
|
|
||||||
"UserLocation": "北京市海淀区",
|
|
||||||
"Latitude": "39.9087",
|
|
||||||
"Longitude": "116.3975",
|
|
||||||
"RecordTime": "2023-10-31T10:00:00",
|
|
||||||
"RecordTimeUTCStamp": 1698727200000,
|
|
||||||
"IsDeleted": false,
|
|
||||||
"CreateTime": "2023-10-31T10:00:00",
|
|
||||||
"MessageType": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Id": 2,
|
|
||||||
"Guid": "会话唯一标识",
|
|
||||||
"UserKey": "user_123456",
|
|
||||||
"ConversationContent": "这是一条私有消息",
|
|
||||||
"SendMethod": "文本",
|
|
||||||
"UserLocation": "北京市朝阳区",
|
|
||||||
"Latitude": "39.9180",
|
|
||||||
"Longitude": "116.4272",
|
|
||||||
"RecordTime": "2023-10-31T09:55:00",
|
|
||||||
"RecordTimeUTCStamp": 1698724500000,
|
|
||||||
"IsDeleted": false,
|
|
||||||
"CreateTime": "2023-10-31T09:55:00",
|
|
||||||
"MessageType": 2
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"totalCount": 25,
|
|
||||||
"page": 1,
|
|
||||||
"pageSize": 10,
|
|
||||||
"totalPages": 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**失败响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "查询失败",
|
|
||||||
"error": "数据库操作错误"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.5 根据GUID查询会话记录接口
|
|
||||||
|
|
||||||
#### 接口描述
|
|
||||||
根据会话唯一标识(GUID)查询会话记录详情,不考虑IsDeleted状态。
|
|
||||||
|
|
||||||
#### 接口路径
|
|
||||||
`/api/Check/GetConversationByGuid`
|
|
||||||
|
|
||||||
#### 请求参数
|
|
||||||
|
|
||||||
| 参数名 | 类型 | 必填 | 描述 |
|
|
||||||
|--------|------|------|------|
|
|
||||||
| Guid | string | 是 | 会话唯一标识 |
|
|
||||||
|
|
||||||
#### 请求示例
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"Guid": "会话唯一标识"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 响应示例
|
|
||||||
|
|
||||||
**成功响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"message": "查询成功",
|
|
||||||
"data": {
|
|
||||||
"Id": 1,
|
|
||||||
"Guid": "会话唯一标识",
|
|
||||||
"UserKey": "user_123456",
|
|
||||||
"ConversationContent": "这是一条测试消息",
|
|
||||||
"SendMethod": "文本",
|
|
||||||
"UserLocation": "北京市海淀区",
|
|
||||||
"Latitude": "39.9087",
|
|
||||||
"Longitude": "116.3975",
|
|
||||||
"RecordTime": "2023-10-31T10:05:00",
|
|
||||||
"RecordTimeUTCStamp": 1698732300000,
|
|
||||||
"IsDeleted": false,
|
|
||||||
"CreateTime": "2023-10-31T10:05:00",
|
|
||||||
"MessageType": 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**失败响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "未找到该记录"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "查询失败",
|
|
||||||
"error": "数据库操作错误"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.6 更新会话记录接口
|
|
||||||
|
|
||||||
#### 接口描述
|
|
||||||
更新指定GUID的会话记录,需要验证UserKey的权限。每次更新时,RecordTime会自动更新为当前时间。
|
|
||||||
|
|
||||||
#### 接口路径
|
|
||||||
`/api/Check/UpdateConversation`
|
|
||||||
|
|
||||||
#### 请求参数
|
|
||||||
|
|
||||||
| 参数名 | 类型 | 必填 | 描述 |
|
|
||||||
|--------|------|------|------|
|
|
||||||
| Guid | string | 是 | 会话唯一标识 |
|
|
||||||
| UserKey | string | 是 | 用户唯一标识键(用于权限验证) |
|
|
||||||
| ConversationContent | string | 是 | 新的会话内容 |
|
|
||||||
| SendMethod | string | 是 | 新的发送方式 |
|
|
||||||
| UserLocation | string | 否 | 新的用户定位信息 |
|
|
||||||
| MessageType | int | 否 | 1:公有消息,2:私有消息 |
|
|
||||||
|
|
||||||
#### 请求示例
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"Guid": "会话唯一标识",
|
|
||||||
"UserKey": "user_123456",
|
|
||||||
"ConversationContent": "更新后的会话内容",
|
|
||||||
"SendMethod": "文本",
|
|
||||||
"UserLocation": "北京市西城区",
|
|
||||||
"MessageType": 1
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 响应示例
|
|
||||||
|
|
||||||
**成功响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"message": "更新成功",
|
|
||||||
"receivedTime": "2023-10-31 10:10:00"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**失败响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "记录不存在或无权限修改"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "更新失败",
|
|
||||||
"error": "数据库操作错误"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.7 删除会话记录接口
|
|
||||||
|
|
||||||
#### 接口描述
|
|
||||||
软删除会话记录(将IsDeleted标记为1),需要验证UserKey的权限。
|
|
||||||
|
|
||||||
#### 接口路径
|
|
||||||
`/api/Check/DeleteConversation`
|
|
||||||
|
|
||||||
#### 请求参数
|
|
||||||
|
|
||||||
| 参数名 | 类型 | 必填 | 描述 |
|
|
||||||
|--------|------|------|------|
|
|
||||||
| Guid | string | 是 | 会话唯一标识 |
|
|
||||||
| UserKey | string | 是 | 用户唯一标识键(用于权限验证) |
|
|
||||||
|
|
||||||
#### 请求示例
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"Guid": "会话唯一标识",
|
|
||||||
"UserKey": "user_123456"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 响应示例
|
|
||||||
|
|
||||||
**成功响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"message": "删除成功"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**失败响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "记录不存在或已被删除"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "删除失败",
|
|
||||||
"error": "数据库操作错误"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.8 从Redis Stream读取消息接口
|
|
||||||
|
|
||||||
#### 接口描述
|
|
||||||
从Redis Stream读取新的会话消息。
|
|
||||||
|
|
||||||
#### 接口路径
|
|
||||||
`/api/Check/ReadMessageFromRedis`
|
|
||||||
|
|
||||||
#### 请求参数
|
|
||||||
|
|
||||||
| 参数名 | 类型 | 必填 | 描述 |
|
|
||||||
|--------|------|------|------|
|
|
||||||
| GroupName | string | 否 | 消费组名称,默认:xcx_group |
|
|
||||||
| ConsumerName | string | 否 | 消费者名称,默认:consumer_时间戳 |
|
|
||||||
| Count | int | 否 | 读取消息数量,默认:1 |
|
|
||||||
|
|
||||||
#### 请求示例
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"GroupName": "xcx_group",
|
|
||||||
"ConsumerName": "consumer_1",
|
|
||||||
"Count": 5
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 响应示例
|
|
||||||
|
|
||||||
**成功响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": true,
|
|
||||||
"message": "成功读取消息",
|
|
||||||
"data": [
|
|
||||||
{
|
|
||||||
"MessageId": "1635739200000-0",
|
|
||||||
"Id": "1",
|
|
||||||
"Guid": "会话唯一标识",
|
|
||||||
"UserKey": "user_123456",
|
|
||||||
"ConversationContent": "测试消息",
|
|
||||||
"SendMethod": "文本",
|
|
||||||
"UserLocation": "北京市海淀区",
|
|
||||||
"Latitude": "39.9087",
|
|
||||||
"Longitude": "116.3975",
|
|
||||||
"RecordTime": "2023-10-31T10:00:00",
|
|
||||||
"RecordTimeUTCStamp": "1698727200000",
|
|
||||||
"IsDeleted": "false",
|
|
||||||
"CreateTime": "2023-10-31T10:00:00",
|
|
||||||
"MessageType": "1",
|
|
||||||
"UserName": "张三",
|
|
||||||
"WeChatName": "张三的微信",
|
|
||||||
"PhoneNumber": "13800138000",
|
|
||||||
"AvatarUrl": "https://example.com/avatar.jpg"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**失败响应:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"success": false,
|
|
||||||
"message": "读取消息失败",
|
|
||||||
"error": "Redis操作错误"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 3. 接口调用说明
|
|
||||||
|
|
||||||
### 3.1 HTTP客户端调用示例(JavaScript)
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// 封装API请求函数
|
|
||||||
async function callApi(endpoint, data) {
|
|
||||||
try {
|
|
||||||
const response = await fetch(`http://your-api-domain/api${endpoint}`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify(data)
|
|
||||||
});
|
|
||||||
|
|
||||||
const result = await response.json();
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('API调用失败:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户信息更新示例
|
|
||||||
async function updateUser() {
|
|
||||||
const result = await callApi('/Login/Register', {
|
|
||||||
UserName: '张三',
|
|
||||||
UserKey: 'openid_from_wechat',
|
|
||||||
WeChatName: '张三的微信',
|
|
||||||
PhoneNumber: '13800138000'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
console.log('用户信息更新成功');
|
|
||||||
} else {
|
|
||||||
console.log('用户信息更新失败:', result.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户登录示例
|
|
||||||
async function loginUser() {
|
|
||||||
const result = await callApi('/Login/Login', {
|
|
||||||
Code: 'wx_login_code_here'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
console.log('登录成功,用户信息:', result.data);
|
|
||||||
// 保存用户信息和Token到本地存储
|
|
||||||
localStorage.setItem('userInfo', JSON.stringify(result.data));
|
|
||||||
localStorage.setItem('token', result.data.Token);
|
|
||||||
} else {
|
|
||||||
console.log('登录失败:', result.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加会话示例
|
|
||||||
async function addConversation() {
|
|
||||||
const result = await callApi('/Check/AddConversation', {
|
|
||||||
UserKey: 'user_123456',
|
|
||||||
ConversationContent: '测试会话内容',
|
|
||||||
SendMethod: '文本',
|
|
||||||
UserLocation: '北京',
|
|
||||||
MessageType: 0
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
console.log('会话添加成功');
|
|
||||||
} else {
|
|
||||||
console.log('会话添加失败:', result.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3.2 常见错误处理
|
|
||||||
|
|
||||||
1. **数据库连接错误**:检查数据库服务是否正常运行,连接字符串是否正确
|
|
||||||
2. **权限验证失败**:确保提供的UserKey与操作资源匹配
|
|
||||||
3. **记录不存在**:在更新或删除前确认记录ID和UserKey的正确性
|
|
||||||
4. **网络错误**:检查API服务是否正常运行,网络连接是否稳定
|
|
||||||
|
|
||||||
## 4. 安全注意事项
|
|
||||||
|
|
||||||
1. **参数验证**:所有接口都应在前端进行基本的数据格式验证
|
|
||||||
2. **UserKey保护**:UserKey作为用户身份标识,应妥善保护,避免泄露
|
|
||||||
3. **错误信息处理**:生产环境中应避免返回详细的错误信息,防止信息泄露
|
|
||||||
4. **请求频率限制**:建议在生产环境中对API接口实施请求频率限制,防止滥用
|
|
||||||
|
|
||||||
## 5. 接口维护信息
|
|
||||||
|
|
||||||
- **最后更新时间**:2023-11-01
|
|
||||||
- **维护人员**:系统管理员
|
|
||||||
- **版本号**:v1.2.0
|
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
using CSRedis;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Configuration;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using static CSRedis.CSRedisClient;
|
|
||||||
|
|
||||||
namespace Common
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Redis缓存辅助类
|
|
||||||
/// </summary>
|
|
||||||
public class CSRedisCacheHelper
|
|
||||||
{
|
|
||||||
public static CSRedisClient? redis;
|
|
||||||
public static CSRedisClient? redis14;
|
|
||||||
public static CSRedisClient? redis15;
|
|
||||||
|
|
||||||
private const string ip = "127.0.0.1";
|
|
||||||
//private const string port = "6379";
|
|
||||||
private const string port = "6800";
|
|
||||||
static CSRedisCacheHelper()
|
|
||||||
{
|
|
||||||
var redisHostStr = string.Format("{0}:{1}", ip, port);
|
|
||||||
if (!string.IsNullOrEmpty(redisHostStr))
|
|
||||||
{
|
|
||||||
redis = new CSRedisClient(redisHostStr + ",password=,defaultDatabase=0");
|
|
||||||
redis15 = new CSRedisClient(redisHostStr + ",password=,defaultDatabase=15");
|
|
||||||
var DingYueMsg = ("CellCorelDRAWUser", new Action<SubscribeMessageEventArgs>(async (args) =>
|
|
||||||
{
|
|
||||||
string body = args.Body;
|
|
||||||
}));
|
|
||||||
|
|
||||||
CSRedisCacheHelper.redis.Subscribe(DingYueMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// 添加缓存
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T"></typeparam>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <param name="value"></param>
|
|
||||||
public static void Set<T>(string key, T value, int ExpireTime)
|
|
||||||
{
|
|
||||||
redis?.Set(key, value, ExpireTime * 60);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static T Get<T>(string key)
|
|
||||||
{
|
|
||||||
return redis.Get<T>(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Forever<T>(string key, T value)
|
|
||||||
{
|
|
||||||
redis.Set(key, value, -1);
|
|
||||||
}
|
|
||||||
public static void Del(string key)
|
|
||||||
{
|
|
||||||
redis.Del(key);
|
|
||||||
}
|
|
||||||
public static void ListPush<T>(string key, T value)
|
|
||||||
{
|
|
||||||
redis.LPush(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 判断是否存在
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
|
|
||||||
public static bool Contains(string key)
|
|
||||||
{
|
|
||||||
bool result = redis.Exists(key);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string? XAdd(string key, params (string, string)[] fieldValues)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var result = redis.XAdd(key, fieldValues);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
System.Diagnostics.Debug.WriteLine($"XAdd error: {ex.Message}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string? XReadGroup(string key, string group, string consumer, int count = 1, string id = null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
id = id ?? ">";
|
|
||||||
var result = redis.XReadGroup(group, consumer, count, 0, (key, id));
|
|
||||||
|
|
||||||
if (result != null && result.Length > 0)
|
|
||||||
{
|
|
||||||
// 处理消息
|
|
||||||
var messages = new List<Dictionary<string, object>>();
|
|
||||||
|
|
||||||
foreach (var streamResult in result)
|
|
||||||
{
|
|
||||||
foreach (var entry in streamResult.data)
|
|
||||||
{
|
|
||||||
var message = new Dictionary<string, object>
|
|
||||||
{
|
|
||||||
["Id"] = entry.id,
|
|
||||||
["Values"] = entry.items
|
|
||||||
};
|
|
||||||
|
|
||||||
messages.Add(message);
|
|
||||||
|
|
||||||
// 确认消息已处理
|
|
||||||
redis.XAck(key, group, entry.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return System.Text.Json.JsonSerializer.Serialize(messages);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
System.Diagnostics.Debug.WriteLine($"XReadGroup error: {ex.Message}");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static (string key, (string id, string items)[] data)[] XReadGroup(string group, string consumer, long count, long block, params (string key, string id)[] streams)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var result = redis.XReadGroup(group, consumer, count, block, streams);
|
|
||||||
|
|
||||||
if (result != null && result.Length > 0)
|
|
||||||
{
|
|
||||||
// 处理消息并确认已处理
|
|
||||||
var processedResults = new List<(string key, (string id, string items)[] data)>();
|
|
||||||
|
|
||||||
foreach (var streamResult in result)
|
|
||||||
{
|
|
||||||
var messages = new List<(string id, string items)>();
|
|
||||||
|
|
||||||
foreach (var entry in streamResult.data)
|
|
||||||
{
|
|
||||||
// 确认消息已处理
|
|
||||||
redis.XAck(streamResult.key, group, entry.id);
|
|
||||||
|
|
||||||
// entry是一个元组 (string id, string[] items)
|
|
||||||
// 我们需要将string[] items转换为string items
|
|
||||||
var itemsArray = entry.items;
|
|
||||||
var itemsString = string.Join(",", itemsArray);
|
|
||||||
messages.Add((entry.id, itemsString));
|
|
||||||
}
|
|
||||||
|
|
||||||
processedResults.Add((streamResult.key, messages.ToArray()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return processedResults.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Array.Empty<(string key, (string id, string items)[] data)>();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
System.Diagnostics.Debug.WriteLine($"XReadGroup error: {ex.Message}");
|
|
||||||
return Array.Empty<(string key, (string id, string items)[] data)>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool XGroupCreate(string key, string group, string id = "0")
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
redis.XGroupCreate(key, group, id, true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 发布消息
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="Topic"></param>
|
|
||||||
/// <param name="Payload"></param>
|
|
||||||
public static void Publish(string Topic, string Payload)
|
|
||||||
{
|
|
||||||
CSRedisCacheHelper.redis.PublishNoneMessageId(Topic, Payload);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,869 +0,0 @@
|
|||||||
using Common;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.IdentityModel.Tokens;
|
|
||||||
using MySql.Data.MySqlClient;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Web;
|
|
||||||
|
|
||||||
namespace WxCheckApi.Controllers
|
|
||||||
{
|
|
||||||
[Route("api/[controller]/[action]")]
|
|
||||||
[ApiController]
|
|
||||||
public class CheckController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly MySqlConnection _connection;
|
|
||||||
private readonly HttpClient _httpClient;
|
|
||||||
private readonly IConfiguration _configuration;
|
|
||||||
|
|
||||||
public CheckController(MySqlConnection connection, IHttpClientFactory httpClientFactory, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
_connection = connection;
|
|
||||||
_httpClient = httpClientFactory.CreateClient();
|
|
||||||
_configuration = configuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将经纬度转换为地址信息
|
|
||||||
public async Task<string> ConvertCoordinatesToAddress(string longitude,string latitude)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 使用高德地图API进行逆地理编码
|
|
||||||
string apiKey = _configuration["AmapApi:ApiKey"] ?? "4d5cb7818664ada68ae5f68783b8bd4c";
|
|
||||||
string url = $"https://restapi.amap.com/v3/geocode/regeo?output=json&location={longitude},{latitude}&key={apiKey}&radius=1000&extensions=all";
|
|
||||||
|
|
||||||
var response = await _httpClient.GetStringAsync(url);
|
|
||||||
var jsonDoc = JsonDocument.Parse(response);
|
|
||||||
var root = jsonDoc.RootElement;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (root.GetProperty("status").GetString() == "1" && root.TryGetProperty("regeocode", out var regeocodeElement) && regeocodeElement.ValueKind != JsonValueKind.Null)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (regeocodeElement.TryGetProperty("formatted_address", out var formatted_address))
|
|
||||||
{
|
|
||||||
return formatted_address.ToString();
|
|
||||||
}
|
|
||||||
if (regeocodeElement.TryGetProperty("addressComponent", out var addressComponent))
|
|
||||||
{
|
|
||||||
string province = addressComponent.TryGetProperty("province", out var provinceElement) && provinceElement.ValueKind == JsonValueKind.String ? provinceElement.GetString() : "";
|
|
||||||
string city = addressComponent.TryGetProperty("city", out var cityElement) && cityElement.ValueKind == JsonValueKind.String ? cityElement.GetString() : "";
|
|
||||||
string district = addressComponent.TryGetProperty("district", out var districtElement) && districtElement.ValueKind == JsonValueKind.String ? districtElement.GetString() : "";
|
|
||||||
string township = addressComponent.TryGetProperty("township", out var townshipElement) && townshipElement.ValueKind == JsonValueKind.String ? townshipElement.GetString() : "";
|
|
||||||
|
|
||||||
// 获取街道和门牌号信息
|
|
||||||
string street = "";
|
|
||||||
string streetNumber = "";
|
|
||||||
double distance = 0;
|
|
||||||
|
|
||||||
// 方法1:从addressComponent获取街道信息
|
|
||||||
if (addressComponent.TryGetProperty("streetNumber", out var streetNumberElement) && streetNumberElement.ValueKind == JsonValueKind.Object)
|
|
||||||
{
|
|
||||||
street = streetNumberElement.TryGetProperty("street", out var streetElement) && streetElement.ValueKind == JsonValueKind.String ? streetElement.GetString() : "";
|
|
||||||
streetNumber = streetNumberElement.TryGetProperty("number", out var numberElement) && numberElement.ValueKind == JsonValueKind.String ? numberElement.GetString() : "";
|
|
||||||
|
|
||||||
// 获取距离信息
|
|
||||||
if (streetNumberElement.TryGetProperty("distance", out var distanceElement) && distanceElement.ValueKind == JsonValueKind.String)
|
|
||||||
{
|
|
||||||
double.TryParse(distanceElement.GetString(), out distance);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 方法2:如果方法1没有获取到街道信息,尝试从aoi信息中获取
|
|
||||||
if (string.IsNullOrEmpty(street) && regeocodeElement.TryGetProperty("aois", out var aoisElement) && aoisElement.ValueKind == JsonValueKind.Array)
|
|
||||||
{
|
|
||||||
var aoisArray = aoisElement.EnumerateArray();
|
|
||||||
foreach (var aoi in aoisArray)
|
|
||||||
{
|
|
||||||
if (aoi.TryGetProperty("name", out var aoiNameElement) && aoiNameElement.ValueKind == JsonValueKind.String)
|
|
||||||
{
|
|
||||||
street = aoiNameElement.GetString();
|
|
||||||
break; // 取第一个AOI作为街道信息
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 方法3:如果前两种方法都没有获取到街道信息,尝试从pois信息中获取
|
|
||||||
if (string.IsNullOrEmpty(street) && regeocodeElement.TryGetProperty("pois", out var poisElement) && poisElement.ValueKind == JsonValueKind.Array)
|
|
||||||
{
|
|
||||||
var poisArray = poisElement.EnumerateArray();
|
|
||||||
foreach (var poi in poisArray)
|
|
||||||
{
|
|
||||||
if (poi.TryGetProperty("name", out var poiNameElement) && poiNameElement.ValueKind == JsonValueKind.String)
|
|
||||||
{
|
|
||||||
street = poiNameElement.GetString();
|
|
||||||
break; // 取第一个POI作为街道信息
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 方法4:如果以上方法都没有获取到街道信息,尝试从formatted_address中解析
|
|
||||||
if (string.IsNullOrEmpty(street) && regeocodeElement.TryGetProperty("formatted_address", out var formattedAddressElement) && formattedAddressElement.ValueKind == JsonValueKind.String)
|
|
||||||
{
|
|
||||||
string formattedAddress = formattedAddressElement.GetString();
|
|
||||||
// 尝试从格式化地址中提取街道信息
|
|
||||||
// 格式化地址通常格式为:省 市 区 街道 具体地址
|
|
||||||
|
|
||||||
// 使用字符串数组作为分隔符
|
|
||||||
string[] separators = { " ", "省", "市", "区", "县", "镇", "街道", "路", "巷", "号" };
|
|
||||||
var addressParts = formattedAddress.Split(separators, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
|
|
||||||
// 查找可能包含街道信息的部分
|
|
||||||
for (int i = 0; i < addressParts.Length; i++)
|
|
||||||
{
|
|
||||||
var part = addressParts[i];
|
|
||||||
// 如果部分包含"路"、"街"、"巷"等关键词,可能是街道信息
|
|
||||||
if (part.Contains("路") || part.Contains("街") || part.Contains("巷") || part.Contains("道"))
|
|
||||||
{
|
|
||||||
street = part;
|
|
||||||
// 如果下一个部分存在且不是区县名称,可能是门牌号
|
|
||||||
if (i + 1 < addressParts.Length &&
|
|
||||||
!addressParts[i + 1].Contains("区") &&
|
|
||||||
!addressParts[i + 1].Contains("县"))
|
|
||||||
{
|
|
||||||
streetNumber = addressParts[i + 1];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 方法5:如果仍然没有获取到街道信息,尝试从nearestRoad信息中获取
|
|
||||||
if (string.IsNullOrEmpty(street) && regeocodeElement.TryGetProperty("streetNumber", out var nearestStreetElement) &&
|
|
||||||
nearestStreetElement.ValueKind == JsonValueKind.Object)
|
|
||||||
{
|
|
||||||
if (nearestStreetElement.TryGetProperty("street", out var nearestStreetNameElement) && nearestStreetNameElement.ValueKind == JsonValueKind.String)
|
|
||||||
{
|
|
||||||
street = nearestStreetNameElement.GetString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建详细地址字符串
|
|
||||||
string address = "";
|
|
||||||
if (!string.IsNullOrEmpty(province))
|
|
||||||
{
|
|
||||||
address += province;
|
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(city) && city != province)
|
|
||||||
{
|
|
||||||
address += " " + city;
|
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(district))
|
|
||||||
{
|
|
||||||
address += " " + district;
|
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(township))
|
|
||||||
{
|
|
||||||
address += " " + township;
|
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(street))
|
|
||||||
{
|
|
||||||
address += " " + street;
|
|
||||||
}
|
|
||||||
if (!string.IsNullOrEmpty(streetNumber))
|
|
||||||
{
|
|
||||||
address += " " + streetNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果有距离信息,添加到地址后面
|
|
||||||
if (distance > 0)
|
|
||||||
{
|
|
||||||
address += $" {distance:F1}米";
|
|
||||||
}
|
|
||||||
if (string.IsNullOrEmpty(address))
|
|
||||||
{
|
|
||||||
return "未获取到位置信息(高德返回值为空) " + latitude + "," + longitude;
|
|
||||||
}
|
|
||||||
return address.Trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return latitude + "," + longitude; ; // 如果API调用失败,返回原始值
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
return latitude + "," + longitude; ; // 如果发生异常,返回原始值
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<IActionResult> CheckAddress([FromBody] CheckAddressRequest request)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_connection.State != ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.OpenAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从数据库查询经纬度信息
|
|
||||||
string latitude = "";
|
|
||||||
string longitude = "";
|
|
||||||
|
|
||||||
using (MySqlCommand cmd = new MySqlCommand("SELECT Latitude, Longitude FROM xcx_conversation WHERE Guid = @Guid AND IsDeleted = 0", _connection))
|
|
||||||
{
|
|
||||||
cmd.Parameters.AddWithValue("@Guid", request.Guid);
|
|
||||||
|
|
||||||
using (var reader = await cmd.ExecuteReaderAsync())
|
|
||||||
{
|
|
||||||
if (await reader.ReadAsync())
|
|
||||||
{
|
|
||||||
latitude = reader.IsDBNull(0) ? "" : reader.GetString(0);
|
|
||||||
longitude = reader.IsDBNull(1) ? "" : reader.GetString(1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return NotFound(new { success = false, message = "记录不存在或已被删除" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换经纬度为地址
|
|
||||||
var address = await ConvertCoordinatesToAddress(longitude, latitude);
|
|
||||||
|
|
||||||
// 更新数据库中的UserLocation字段
|
|
||||||
using (MySqlCommand cmd = new MySqlCommand("UPDATE xcx_conversation SET UserLocation = @UserLocation WHERE Guid = @Guid AND IsDeleted = 0", _connection))
|
|
||||||
{
|
|
||||||
cmd.Parameters.AddWithValue("@Guid", request.Guid);
|
|
||||||
cmd.Parameters.AddWithValue("@UserLocation", address);
|
|
||||||
|
|
||||||
int rowsAffected = await cmd.ExecuteNonQueryAsync();
|
|
||||||
|
|
||||||
if (rowsAffected == 0)
|
|
||||||
{
|
|
||||||
return NotFound(new { success = false, message = "记录不存在或已被删除" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(new { success = true, message = "地址更新成功", address = address });
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return StatusCode(500, new { success = false, message = "更新失败", error = ex.Message });
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (_connection.State == ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.CloseAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 添加会话记录
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<IActionResult> AddConversation([FromBody] ConversationRequest request)
|
|
||||||
{
|
|
||||||
DateTime nowtime = DateTime.Now;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_connection.State != ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.OpenAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析经纬度并转换为地址
|
|
||||||
string address = "";
|
|
||||||
string latitude = "";
|
|
||||||
string longitude = "";
|
|
||||||
|
|
||||||
// 否则尝试从UserLocation字段解析
|
|
||||||
if (!string.IsNullOrEmpty(request.UserLocation))
|
|
||||||
{
|
|
||||||
string[] parts = request.UserLocation.Split(',');
|
|
||||||
if (parts.Length == 2)
|
|
||||||
{
|
|
||||||
if (double.TryParse(parts[0], out double lat) && double.TryParse(parts[1], out double lng))
|
|
||||||
{
|
|
||||||
longitude = lng.ToString();
|
|
||||||
latitude = lat.ToString();
|
|
||||||
address = "";// await ConvertCoordinatesToAddress(latitude, longitude);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成GUID
|
|
||||||
string conversationGuid = string.IsNullOrEmpty(request.Guid) ? Guid.NewGuid().ToString("N") : request.Guid;
|
|
||||||
long conversationId = 0;
|
|
||||||
using (MySqlCommand cmd = new MySqlCommand("INSERT INTO xcx_conversation (UserKey, ConversationContent, SendMethod, UserLocation, Latitude, Longitude, RecordTime, RecordTimeUTCStamp, IsDeleted, CreateTime, MessageType, Guid, SpeakingTime) VALUES (@UserKey, @ConversationContent, @SendMethod, @UserLocation, @Latitude, @Longitude, @RecordTime, @RecordTimeUTCStamp, @IsDeleted, @CreateTime, @MessageType, @Guid, @SpeakingTime); SELECT LAST_INSERT_ID();", _connection))
|
|
||||||
{
|
|
||||||
cmd.Parameters.AddWithValue("@UserKey", request.UserKey);
|
|
||||||
cmd.Parameters.AddWithValue("@MessageType", request.MessageType);
|
|
||||||
cmd.Parameters.AddWithValue("@ConversationContent", request.ConversationContent);
|
|
||||||
cmd.Parameters.AddWithValue("@SendMethod", request.SendMethod);
|
|
||||||
cmd.Parameters.AddWithValue("@UserLocation", address);
|
|
||||||
cmd.Parameters.AddWithValue("@Latitude", latitude);
|
|
||||||
cmd.Parameters.AddWithValue("@Longitude", longitude);
|
|
||||||
cmd.Parameters.AddWithValue("@RecordTime", nowtime);
|
|
||||||
cmd.Parameters.AddWithValue("@CreateTime", nowtime);
|
|
||||||
cmd.Parameters.AddWithValue("@RecordTimeUTCStamp", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds());
|
|
||||||
cmd.Parameters.AddWithValue("@IsDeleted", 0);
|
|
||||||
cmd.Parameters.AddWithValue("@Guid", conversationGuid);
|
|
||||||
cmd.Parameters.AddWithValue("@SpeakingTime", request.SpeakingTime);
|
|
||||||
|
|
||||||
object result = await cmd.ExecuteScalarAsync();
|
|
||||||
conversationId = Convert.ToInt64(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询刚插入的记录,并左连接用户表
|
|
||||||
if (conversationId > 0)
|
|
||||||
{
|
|
||||||
string query = @"SELECT convs.Id, convs.Guid, convs.UserKey, convs.ConversationContent, convs.SendMethod,
|
|
||||||
convs.UserLocation, convs.Latitude, convs.Longitude, convs.RecordTime,
|
|
||||||
convs.RecordTimeUTCStamp, convs.IsDeleted, convs.CreateTime, convs.MessageType, convs.SpeakingTime,
|
|
||||||
users.UserName, users.WeChatName, users.PhoneNumber, users.AvatarUrl
|
|
||||||
FROM xcx_conversation AS convs
|
|
||||||
LEFT JOIN xcx_users AS users ON convs.UserKey = users.UserKey
|
|
||||||
WHERE convs.Guid = @Guid";
|
|
||||||
|
|
||||||
using (MySqlCommand cmd = new MySqlCommand(query, _connection))
|
|
||||||
{
|
|
||||||
cmd.Parameters.AddWithValue("@Guid", conversationGuid);
|
|
||||||
using (var reader = await cmd.ExecuteReaderAsync())
|
|
||||||
{
|
|
||||||
if (await reader.ReadAsync())
|
|
||||||
{
|
|
||||||
// 构建要发送到Redis的数据
|
|
||||||
var messageData = new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
["Id"] = reader.GetInt64(0).ToString(),
|
|
||||||
["Guid"] = reader.IsDBNull(1) ? "" : reader.GetString(1),
|
|
||||||
["UserKey"] = reader.GetString(2),
|
|
||||||
["ConversationContent"] = reader.GetString(3),
|
|
||||||
["SendMethod"] = reader.GetString(4),
|
|
||||||
["UserLocation"] = reader.IsDBNull(5) ? "" : reader.GetString(5),
|
|
||||||
["Latitude"] = reader.IsDBNull(6) ? "" : reader.GetString(6),
|
|
||||||
["Longitude"] = reader.IsDBNull(7) ? "" : reader.GetString(7),
|
|
||||||
["RecordTime"] = reader.GetDateTime(8).ToString("yyyy-MM-dd HH:mm:ss"),
|
|
||||||
["RecordTimeUTCStamp"] = reader.GetInt64(9).ToString(),
|
|
||||||
["IsDeleted"] = reader.GetBoolean(10).ToString(),
|
|
||||||
["CreateTime"] = reader.GetDateTime(11).ToString("yyyy-MM-dd HH:mm:ss"),
|
|
||||||
["MessageType"] = reader.GetInt32(12).ToString(),
|
|
||||||
["SpeakingTime"] = reader.IsDBNull(13) ? "" : reader.GetInt32(13).ToString(),
|
|
||||||
["UserName"] = reader.IsDBNull(14) ? "" : reader.GetString(14),
|
|
||||||
["WeChatName"] = reader.IsDBNull(15) ? "" : reader.GetString(15),
|
|
||||||
["PhoneNumber"] = reader.IsDBNull(16) ? "" : reader.GetString(16),
|
|
||||||
["AvatarUrl"] = reader.IsDBNull(17) ? "" : reader.GetString(17)
|
|
||||||
};
|
|
||||||
|
|
||||||
// 发送到Redis Stream
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 确保Stream和Group存在
|
|
||||||
CSRedisCacheHelper.XGroupCreate("xcx_msg", "xcx_group", "0");
|
|
||||||
|
|
||||||
// 将Dictionary转换为params (string, string)[]格式
|
|
||||||
var fieldValues = messageData.SelectMany(kvp => new (string, string)[] { (kvp.Key, kvp.Value) }).ToArray();
|
|
||||||
|
|
||||||
// 添加消息到Stream
|
|
||||||
string messageId = CSRedisCacheHelper.XAdd("xcx_msg", fieldValues);
|
|
||||||
|
|
||||||
// 记录日志(可选)
|
|
||||||
System.Diagnostics.Debug.WriteLine($"消息已发送到Redis Stream: {messageId}");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
// 记录错误但不影响主流程
|
|
||||||
System.Diagnostics.Debug.WriteLine($"发送到Redis Stream失败: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(new { success = true, message = "收到!", conversationGuid, receivedTime = nowtime.ToString("yyyy-MM-dd HH:mm:ss") });
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return StatusCode(500, new { success = false, message = "发送失败", error = ex.Message });
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (_connection.State == ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.CloseAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据UserKey查询会话记录
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<IActionResult> GetConversations([FromBody] UserKeyRequest request)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_connection.State != ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.OpenAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ConversationResponse> conversations = new List<ConversationResponse>();
|
|
||||||
|
|
||||||
// 构建查询SQL,根据MessageType参数决定是否添加过滤条件
|
|
||||||
string query = "SELECT Id, Guid, UserKey, ConversationContent, SendMethod, UserLocation, Latitude, Longitude, RecordTime, RecordTimeUTCStamp, IsDeleted, CreateTime, MessageType, SpeakingTime FROM xcx_conversation WHERE UserKey = @UserKey AND IsDeleted = 0";
|
|
||||||
if (request.MessageType == 1)
|
|
||||||
{
|
|
||||||
query += " AND MessageType = @MessageType";
|
|
||||||
}
|
|
||||||
query += " ORDER BY RecordTimeUTCStamp DESC";
|
|
||||||
|
|
||||||
using (MySqlCommand cmd = new MySqlCommand(query, _connection))
|
|
||||||
{
|
|
||||||
cmd.Parameters.AddWithValue("@UserKey", request.UserKey);
|
|
||||||
|
|
||||||
using (var reader = await cmd.ExecuteReaderAsync())
|
|
||||||
{
|
|
||||||
while (await reader.ReadAsync())
|
|
||||||
{
|
|
||||||
conversations.Add(new ConversationResponse
|
|
||||||
{
|
|
||||||
Id = reader.GetInt64(0),
|
|
||||||
Guid = reader.IsDBNull(1) ? "" : reader.GetString(1),
|
|
||||||
UserKey = reader.GetString(2),
|
|
||||||
ConversationContent = reader.GetString(3),
|
|
||||||
SendMethod = reader.GetString(4),
|
|
||||||
UserLocation = reader.IsDBNull(5) ? "" : reader.GetString(5),
|
|
||||||
Latitude = reader.IsDBNull(6) ? "" : reader.GetString(6),
|
|
||||||
Longitude = reader.IsDBNull(7) ? "" : reader.GetString(7),
|
|
||||||
RecordTime = reader.GetDateTime(8),
|
|
||||||
RecordTimeUTCStamp = reader.GetInt64(9),
|
|
||||||
IsDeleted = reader.GetBoolean(10),
|
|
||||||
CreateTime = reader.GetDateTime(11),
|
|
||||||
MessageType = reader.GetInt32(12),
|
|
||||||
SpeakingTime = reader.IsDBNull(13) ? null : reader.GetInt32(13)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(new { success = true, data = conversations.OrderBy(z => z.RecordTimeUTCStamp) });
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return StatusCode(500, new { success = false, message = "查询失败", error = ex.Message });
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (_connection.State == ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.CloseAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新会话记录
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<IActionResult> UpdateConversation([FromBody] UpdateConversationRequest request)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_connection.State != ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.OpenAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
DateTime nowtime = DateTime.Now;
|
|
||||||
using (MySqlCommand cmd = new MySqlCommand("UPDATE xcx_conversation SET ConversationContent = @ConversationContent, SendMethod = @SendMethod, UserLocation = @UserLocation, MessageType = @MessageType, RecordTime = @RecordTime WHERE Guid = @Guid AND UserKey = @UserKey", _connection))
|
|
||||||
{
|
|
||||||
cmd.Parameters.AddWithValue("@Guid", request.Guid);
|
|
||||||
cmd.Parameters.AddWithValue("@UserKey", request.UserKey);
|
|
||||||
cmd.Parameters.AddWithValue("@ConversationContent", request.ConversationContent);
|
|
||||||
cmd.Parameters.AddWithValue("@SendMethod", request.SendMethod);
|
|
||||||
cmd.Parameters.AddWithValue("@UserLocation", request.UserLocation ?? "");
|
|
||||||
cmd.Parameters.AddWithValue("@MessageType", request.MessageType);
|
|
||||||
cmd.Parameters.AddWithValue("@RecordTime", nowtime);
|
|
||||||
|
|
||||||
int rowsAffected = await cmd.ExecuteNonQueryAsync();
|
|
||||||
|
|
||||||
if (rowsAffected == 0)
|
|
||||||
{
|
|
||||||
return NotFound(new { success = false, message = "记录不存在或无权限修改" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(new { success = true, message = "更新成功" , receivedTime = nowtime.ToString("yyyy-MM-dd HH:mm:ss") });
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return StatusCode(500, new { success = false, message = "更新失败", error = ex.Message });
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (_connection.State == ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.CloseAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 软删除会话记录
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<IActionResult> DeleteConversation([FromBody] DeleteConversationRequest request)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_connection.State != ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.OpenAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
using (MySqlCommand cmd = new MySqlCommand("UPDATE xcx_conversation SET IsDeleted = 1 WHERE Guid = @Guid AND UserKey = @UserKey AND IsDeleted = 0", _connection))
|
|
||||||
{
|
|
||||||
cmd.Parameters.AddWithValue("@Guid", request.Guid);
|
|
||||||
cmd.Parameters.AddWithValue("@UserKey", request.UserKey);
|
|
||||||
|
|
||||||
int rowsAffected = await cmd.ExecuteNonQueryAsync();
|
|
||||||
|
|
||||||
if (rowsAffected == 0)
|
|
||||||
{
|
|
||||||
return NotFound(new { success = false, message = "记录不存在或已被删除" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(new { success = true, message = "删除成功" });
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return StatusCode(500, new { success = false, message = "删除失败", error = ex.Message });
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (_connection.State == ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.CloseAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 根据GUID查询会话记录(不考虑IsDeleted状态)
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<IActionResult> GetConversationByGuid([FromBody] GetConversationByGuidRequest request)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_connection.State != ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.OpenAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询记录,不考虑IsDeleted状态
|
|
||||||
string query = @"SELECT Id, Guid, UserKey, ConversationContent, SendMethod, UserLocation,
|
|
||||||
Latitude, Longitude, RecordTime, RecordTimeUTCStamp, IsDeleted, CreateTime, MessageType, SpeakingTime
|
|
||||||
FROM xcx_conversation
|
|
||||||
WHERE Guid = @Guid";
|
|
||||||
|
|
||||||
using (MySqlCommand cmd = new MySqlCommand(query, _connection))
|
|
||||||
{
|
|
||||||
cmd.Parameters.AddWithValue("@Guid", request.Guid);
|
|
||||||
|
|
||||||
using (var reader = await cmd.ExecuteReaderAsync())
|
|
||||||
{
|
|
||||||
if (await reader.ReadAsync())
|
|
||||||
{
|
|
||||||
var conversation = new ConversationResponse
|
|
||||||
{
|
|
||||||
Id = reader.GetInt64(0),
|
|
||||||
Guid = reader.IsDBNull(1) ? "" : reader.GetString(1),
|
|
||||||
UserKey = reader.GetString(2),
|
|
||||||
ConversationContent = reader.GetString(3),
|
|
||||||
SendMethod = reader.GetString(4),
|
|
||||||
UserLocation = reader.IsDBNull(5) ? "" : reader.GetString(5),
|
|
||||||
Latitude = reader.IsDBNull(6) ? "" : reader.GetString(6),
|
|
||||||
Longitude = reader.IsDBNull(7) ? "" : reader.GetString(7),
|
|
||||||
RecordTime = reader.GetDateTime(8),
|
|
||||||
RecordTimeUTCStamp = reader.GetInt64(9),
|
|
||||||
IsDeleted = reader.GetBoolean(10),
|
|
||||||
CreateTime = reader.GetDateTime(11),
|
|
||||||
MessageType = reader.GetInt32(12),
|
|
||||||
SpeakingTime = reader.IsDBNull(13) ? null : reader.GetInt32(13)
|
|
||||||
};
|
|
||||||
|
|
||||||
return Ok(new { success = true, message = "查询成功", data = conversation });
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return NotFound(new { success = false, message = "未找到该记录" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return StatusCode(500, new { success = false, message = "查询失败", error = ex.Message });
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (_connection.State == ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.CloseAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页查询会话记录
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<IActionResult> GetConversationsByPage([FromBody] PaginationRequest request)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_connection.State != ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.OpenAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证并设置默认值
|
|
||||||
if (request.Page < 1) request.Page = 1;
|
|
||||||
if (request.PageSize < 1 || request.PageSize > 100) request.PageSize = 10;
|
|
||||||
|
|
||||||
int offset = (request.Page - 1) * request.PageSize;
|
|
||||||
|
|
||||||
List<ConversationResponse> conversations = new List<ConversationResponse>();
|
|
||||||
|
|
||||||
// 构建分页查询SQL,根据MessageType参数决定是否添加过滤条件
|
|
||||||
string query = @"SELECT Id, Guid, UserKey, ConversationContent, SendMethod, UserLocation, Latitude, Longitude, RecordTime, RecordTimeUTCStamp, IsDeleted, CreateTime, MessageType, SpeakingTime
|
|
||||||
FROM xcx_conversation
|
|
||||||
WHERE UserKey = @UserKey AND IsDeleted = 0";
|
|
||||||
if (request.MessageType == 1)
|
|
||||||
{
|
|
||||||
query += " AND MessageType = @MessageType";
|
|
||||||
}
|
|
||||||
query += " ORDER BY RecordTimeUTCStamp DESC LIMIT @Offset, @Limit";
|
|
||||||
|
|
||||||
using (MySqlCommand cmd = new MySqlCommand(query, _connection))
|
|
||||||
{
|
|
||||||
cmd.Parameters.AddWithValue("@UserKey", request.UserKey);
|
|
||||||
if (request.MessageType == 1)
|
|
||||||
{
|
|
||||||
cmd.Parameters.AddWithValue("@MessageType", request.MessageType);
|
|
||||||
}
|
|
||||||
cmd.Parameters.AddWithValue("@Offset", offset);
|
|
||||||
cmd.Parameters.AddWithValue("@Limit", request.PageSize);
|
|
||||||
|
|
||||||
using (var reader = await cmd.ExecuteReaderAsync())
|
|
||||||
{
|
|
||||||
while (await reader.ReadAsync())
|
|
||||||
{
|
|
||||||
conversations.Add(new ConversationResponse
|
|
||||||
{
|
|
||||||
Id = reader.GetInt64(0),
|
|
||||||
Guid = reader.IsDBNull(1) ? "" : reader.GetString(1),
|
|
||||||
UserKey = reader.GetString(2),
|
|
||||||
ConversationContent = reader.GetString(3),
|
|
||||||
SendMethod = reader.GetString(4),
|
|
||||||
UserLocation = reader.IsDBNull(5) ? "" : reader.GetString(5),
|
|
||||||
Latitude = reader.IsDBNull(6) ? "" : reader.GetString(6),
|
|
||||||
Longitude = reader.IsDBNull(7) ? "" : reader.GetString(7),
|
|
||||||
RecordTime = reader.GetDateTime(8),
|
|
||||||
RecordTimeUTCStamp = reader.GetInt64(9),
|
|
||||||
IsDeleted = reader.GetBoolean(10),
|
|
||||||
CreateTime = reader.GetDateTime(11),
|
|
||||||
MessageType = reader.GetInt32(12),
|
|
||||||
SpeakingTime = reader.IsDBNull(13) ? null : reader.GetInt32(13)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询总数,根据MessageType参数决定是否添加过滤条件
|
|
||||||
int totalCount = 0;
|
|
||||||
string countQuery = "SELECT COUNT(*) FROM xcx_conversation WHERE UserKey = @UserKey AND IsDeleted = 0";
|
|
||||||
if (request.MessageType == 1)
|
|
||||||
{
|
|
||||||
countQuery += " AND MessageType = @MessageType";
|
|
||||||
}
|
|
||||||
|
|
||||||
using (MySqlCommand countCmd = new MySqlCommand(countQuery, _connection))
|
|
||||||
{
|
|
||||||
countCmd.Parameters.AddWithValue("@UserKey", request.UserKey);
|
|
||||||
if (request.MessageType == 1)
|
|
||||||
{
|
|
||||||
countCmd.Parameters.AddWithValue("@MessageType", request.MessageType);
|
|
||||||
}
|
|
||||||
totalCount = Convert.ToInt32(await countCmd.ExecuteScalarAsync());
|
|
||||||
}
|
|
||||||
|
|
||||||
int totalPages = (int)Math.Ceiling((double)totalCount / request.PageSize);
|
|
||||||
|
|
||||||
return Ok(new {
|
|
||||||
success = true,
|
|
||||||
data = new {
|
|
||||||
conversations = conversations.OrderBy(z => z.RecordTimeUTCStamp),
|
|
||||||
totalCount = totalCount,
|
|
||||||
page = request.Page,
|
|
||||||
pageSize = request.PageSize,
|
|
||||||
totalPages = totalPages
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return StatusCode(500, new { success = false, message = "查询失败", error = ex.Message });
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (_connection.State == ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.CloseAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从Redis Stream读取消息
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<IActionResult> ReadMessageFromRedis([FromBody] RedisMessageRequest request)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// 确保Stream和Group存在
|
|
||||||
CSRedisCacheHelper.XGroupCreate("xcx_msg", "xcx_group", "0");
|
|
||||||
|
|
||||||
// 从Redis Stream读取消息
|
|
||||||
string groupName = request.GroupName ?? "xcx_group";
|
|
||||||
string consumerName = request.ConsumerName ?? "consumer_" + DateTime.Now.Ticks;
|
|
||||||
|
|
||||||
string messages = CSRedisCacheHelper.XReadGroup("xcx_msg", groupName, consumerName, request.Count ?? 1);
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(messages))
|
|
||||||
{
|
|
||||||
return Ok(new { success = true, message = "没有新消息", data = new List<string>() });
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解析消息
|
|
||||||
var messageList = new List<object>();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var messageEntries = System.Text.Json.JsonSerializer.Deserialize<List<Dictionary<string, object>>>(messages);
|
|
||||||
|
|
||||||
if (messageEntries != null)
|
|
||||||
{
|
|
||||||
foreach (var entry in messageEntries)
|
|
||||||
{
|
|
||||||
if (entry.TryGetValue("Id", out var id) &&
|
|
||||||
entry.TryGetValue("Values", out var values))
|
|
||||||
{
|
|
||||||
var messageData = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
// 如果Values是JsonElement,需要进一步解析
|
|
||||||
if (values is JsonElement valuesElement && valuesElement.ValueKind == JsonValueKind.Object)
|
|
||||||
{
|
|
||||||
foreach (var property in valuesElement.EnumerateObject())
|
|
||||||
{
|
|
||||||
messageData[property.Name] = property.Value.GetString() ?? "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (values is Dictionary<string, string> valuesDict)
|
|
||||||
{
|
|
||||||
messageData = valuesDict;
|
|
||||||
}
|
|
||||||
|
|
||||||
messageData["MessageId"] = id.ToString();
|
|
||||||
messageList.Add(messageData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception parseEx)
|
|
||||||
{
|
|
||||||
// 如果解析失败,尝试直接返回原始消息
|
|
||||||
System.Diagnostics.Debug.WriteLine($"解析消息失败: {parseEx.Message}");
|
|
||||||
messageList.Add(new { RawMessage = messages });
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(new { success = true, message = "成功读取消息", data = messageList });
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return StatusCode(500, new { success = false, message = "读取消息失败", error = ex.Message });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 请求和响应模型
|
|
||||||
public class ConversationRequest
|
|
||||||
{
|
|
||||||
public string UserKey { get; set; }
|
|
||||||
public string ConversationContent { get; set; }
|
|
||||||
public string SendMethod { get; set; }
|
|
||||||
public string UserLocation { get; set; }
|
|
||||||
public double Latitude { get; set; }
|
|
||||||
public double Longitude { get; set; }
|
|
||||||
public int MessageType { get; set; } = 1; // 1:公有,2:私有
|
|
||||||
public string? Guid { get; set; } // 会话唯一标识
|
|
||||||
public int? SpeakingTime { get; set; } // 对话时长
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UserKeyRequest
|
|
||||||
{
|
|
||||||
public string UserKey { get; set; }
|
|
||||||
public int MessageType { get; set; } = 0; // 0:不判断消息类型,1:公有,2:私有
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PaginationRequest
|
|
||||||
{
|
|
||||||
public string UserKey { get; set; }
|
|
||||||
public int Page { get; set; } = 1; // 默认第一页
|
|
||||||
public int PageSize { get; set; } = 10; // 默认每页10条
|
|
||||||
public int MessageType { get; set; } = 0; // 0:不判断消息类型,1:公有,2:私有
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UpdateConversationRequest
|
|
||||||
{
|
|
||||||
public long? Id { get; set; }
|
|
||||||
public string Guid { get; set; } // 会话唯一标识
|
|
||||||
public string UserKey { get; set; }
|
|
||||||
public string ConversationContent { get; set; }
|
|
||||||
public string SendMethod { get; set; }
|
|
||||||
public string UserLocation { get; set; }
|
|
||||||
public int MessageType { get; set; } = 0;
|
|
||||||
public int? SpeakingTime { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class DeleteConversationRequest
|
|
||||||
{
|
|
||||||
public long? Id { get; set; }
|
|
||||||
public string Guid { get; set; } // 会话唯一标识
|
|
||||||
public string UserKey { get; set; }
|
|
||||||
}
|
|
||||||
public class CheckAddressRequest
|
|
||||||
{
|
|
||||||
public long? Id { get; set; }
|
|
||||||
public string Guid { get; set; } // 会话唯一标识
|
|
||||||
}
|
|
||||||
public class GetConversationByGuidRequest
|
|
||||||
{
|
|
||||||
public long? Id { get; set; }
|
|
||||||
public string Guid { get; set; } // 会话唯一标识
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ConversationResponse
|
|
||||||
{
|
|
||||||
public long Id { get; set; }
|
|
||||||
public string Guid { get; set; } // 会话唯一标识
|
|
||||||
public string UserKey { get; set; }
|
|
||||||
public string ConversationContent { get; set; }
|
|
||||||
public string SendMethod { get; set; }
|
|
||||||
public string UserLocation { get; set; }
|
|
||||||
public string Latitude { get; set; }
|
|
||||||
public string Longitude { get; set; }
|
|
||||||
public DateTime RecordTime { get; set; }
|
|
||||||
public long RecordTimeUTCStamp { get; set; }
|
|
||||||
public bool IsDeleted { get; set; }
|
|
||||||
public DateTime CreateTime { get; set; }
|
|
||||||
public int MessageType { get; set; } // 1:公有消息,2:私有消息
|
|
||||||
public int? SpeakingTime { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RedisMessageRequest
|
|
||||||
{
|
|
||||||
public string GroupName { get; set; } = "xcx_group";
|
|
||||||
public string ConsumerName { get; set; }
|
|
||||||
public int? Count { get; set; } = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,324 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.IdentityModel.Tokens;
|
|
||||||
using MySql.Data.MySqlClient;
|
|
||||||
using System;
|
|
||||||
using System.Data;
|
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
|
||||||
using System.Security.Claims;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
namespace WxCheckMvc.Controllers
|
|
||||||
{
|
|
||||||
[Route("api/[controller]/[action]")]
|
|
||||||
[ApiController]
|
|
||||||
public class LoginController : ControllerBase
|
|
||||||
{
|
|
||||||
private readonly MySqlConnection _connection;
|
|
||||||
private readonly IHttpClientFactory _httpClientFactory;
|
|
||||||
public IConfiguration? configuration { get; set; }
|
|
||||||
|
|
||||||
public LoginController(MySqlConnection connection, IHttpClientFactory httpClientFactory, IConfiguration? configuration)
|
|
||||||
{
|
|
||||||
_connection = connection;
|
|
||||||
_httpClientFactory = httpClientFactory;
|
|
||||||
this.configuration = configuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取微信小程序OpenID
|
|
||||||
private async Task<string> GetWxOpenIdAsync(string code)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var appId = configuration["WeChat:AppId"];
|
|
||||||
var appSecret = configuration["WeChat:AppSecret"];
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(appId) || string.IsNullOrEmpty(appSecret))
|
|
||||||
{
|
|
||||||
throw new Exception("微信小程序配置缺失");
|
|
||||||
}
|
|
||||||
|
|
||||||
var httpClient = _httpClientFactory.CreateClient();
|
|
||||||
var url = $"https://api.weixin.qq.com/sns/jscode2session?appid={appId}&secret={appSecret}&js_code={code}&grant_type=authorization_code";
|
|
||||||
|
|
||||||
var response = await httpClient.GetAsync(url);
|
|
||||||
response.EnsureSuccessStatusCode();
|
|
||||||
|
|
||||||
var responseContent = await response.Content.ReadAsStringAsync();
|
|
||||||
var jsonDocument = JsonDocument.Parse(responseContent);
|
|
||||||
|
|
||||||
if (jsonDocument.RootElement.TryGetProperty("openid", out var openidElement))
|
|
||||||
{
|
|
||||||
return openidElement.GetString();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 如果有错误信息,抛出异常
|
|
||||||
if (jsonDocument.RootElement.TryGetProperty("errcode", out var errcodeElement) &&
|
|
||||||
jsonDocument.RootElement.TryGetProperty("errmsg", out var errmsgElement))
|
|
||||||
{
|
|
||||||
throw new Exception($"获取OpenID失败: {errcodeElement.GetInt32()} - {errmsgElement.GetString()}");
|
|
||||||
}
|
|
||||||
throw new Exception("获取OpenID失败: 响应中未包含openid");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new Exception($"获取微信OpenID时发生错误: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private string GetToken(string entity)
|
|
||||||
{
|
|
||||||
string TokenString;
|
|
||||||
var claims = new Claim[]
|
|
||||||
{
|
|
||||||
new Claim(ClaimTypes.NameIdentifier, Guid.NewGuid().ToString()),
|
|
||||||
new Claim(ClaimTypes.Name, entity)
|
|
||||||
};
|
|
||||||
|
|
||||||
var secretByte = Encoding.UTF8.GetBytes(configuration["JwT:SecretKey"]);
|
|
||||||
var signingKey = new SymmetricSecurityKey(secretByte);
|
|
||||||
var a = SecurityAlgorithms.HmacSha256;
|
|
||||||
|
|
||||||
var signingCredentials = new SigningCredentials(signingKey, a);
|
|
||||||
|
|
||||||
var token = new JwtSecurityToken(
|
|
||||||
issuer: configuration["JwT:Issuer"],
|
|
||||||
audience: configuration["JwT:Audience"],//接收
|
|
||||||
claims: claims,//存放的用户信息
|
|
||||||
notBefore: DateTime.UtcNow,//发布时间
|
|
||||||
expires: DateTime.UtcNow.AddMonths(12),
|
|
||||||
signingCredentials: signingCredentials
|
|
||||||
//有效期设置为1天signingCredentials //数字名
|
|
||||||
);
|
|
||||||
TokenString = new JwtSecurityTokenHandler().WriteToken(token);
|
|
||||||
return TokenString;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户注册接口
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<IActionResult> Register([FromBody] RegisterRequest request)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_connection.State != ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.OpenAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查用户是否存在
|
|
||||||
UserResponse user = null;
|
|
||||||
using (MySqlCommand checkCmd = new MySqlCommand("SELECT Id, UserName, UserKey, WeChatName, PhoneNumber, AvatarUrl, FirstLoginTime, IsDisabled, CreateTime, UpdateTime FROM xcx_users WHERE UserKey = @UserKey", _connection))
|
|
||||||
{
|
|
||||||
checkCmd.Parameters.AddWithValue("@UserKey", request.UserKey);
|
|
||||||
using (var reader = await checkCmd.ExecuteReaderAsync())
|
|
||||||
{
|
|
||||||
if (await reader.ReadAsync())
|
|
||||||
{
|
|
||||||
user = new UserResponse
|
|
||||||
{
|
|
||||||
Id = reader.GetInt64(0),
|
|
||||||
UserName = reader.IsDBNull(1) ? "" : reader.GetString(1),
|
|
||||||
UserKey = reader.GetString(2),
|
|
||||||
WeChatName = reader.IsDBNull(3) ? "" : reader.GetString(3),
|
|
||||||
PhoneNumber = reader.IsDBNull(4) ? "" : reader.GetString(4),
|
|
||||||
AvatarUrl = reader.IsDBNull(5) ? "" : reader.GetString(5),
|
|
||||||
FirstLoginTime = reader.GetDateTime(6),
|
|
||||||
IsDisabled = reader.GetBoolean(7),
|
|
||||||
CreateTime = reader.GetDateTime(8),
|
|
||||||
UpdateTime = reader.GetDateTime(9)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound(new { success = false, message = "用户不存在" });
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新用户信息
|
|
||||||
using (MySqlCommand cmd = new MySqlCommand("UPDATE xcx_users SET UserName = @UserName, WeChatName = @WeChatName, PhoneNumber = @PhoneNumber, AvatarUrl = @AvatarUrl, UpdateTime = NOW() WHERE UserKey = @UserKey", _connection))
|
|
||||||
{
|
|
||||||
cmd.Parameters.AddWithValue("@UserName", request.UserName ?? (object)DBNull.Value);
|
|
||||||
cmd.Parameters.AddWithValue("@WeChatName", request.WeChatName ?? "");
|
|
||||||
cmd.Parameters.AddWithValue("@PhoneNumber", request.PhoneNumber ?? "");
|
|
||||||
cmd.Parameters.AddWithValue("@AvatarUrl", request.AvatarUrl ?? (object)DBNull.Value);
|
|
||||||
cmd.Parameters.AddWithValue("@UserKey", request.UserKey);
|
|
||||||
|
|
||||||
await cmd.ExecuteNonQueryAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取更新后的用户信息
|
|
||||||
UserResponse updatedUser = null;
|
|
||||||
using (MySqlCommand cmd = new MySqlCommand("SELECT Id, UserName, UserKey, WeChatName, PhoneNumber, AvatarUrl, FirstLoginTime, IsDisabled, CreateTime, UpdateTime FROM xcx_users WHERE UserKey = @UserKey", _connection))
|
|
||||||
{
|
|
||||||
cmd.Parameters.AddWithValue("@UserKey", request.UserKey);
|
|
||||||
using (var reader = await cmd.ExecuteReaderAsync())
|
|
||||||
{
|
|
||||||
if (await reader.ReadAsync())
|
|
||||||
{
|
|
||||||
updatedUser = new UserResponse
|
|
||||||
{
|
|
||||||
Id = reader.GetInt64(0),
|
|
||||||
UserName = reader.IsDBNull(1) ? "" : reader.GetString(1),
|
|
||||||
UserKey = reader.GetString(2),
|
|
||||||
WeChatName = reader.IsDBNull(3) ? "" : reader.GetString(3),
|
|
||||||
PhoneNumber = reader.IsDBNull(4) ? "" : reader.GetString(4),
|
|
||||||
AvatarUrl = reader.IsDBNull(5) ? "" : reader.GetString(5),
|
|
||||||
FirstLoginTime = reader.GetDateTime(6),
|
|
||||||
IsDisabled = reader.GetBoolean(7),
|
|
||||||
CreateTime = reader.GetDateTime(8),
|
|
||||||
UpdateTime = reader.GetDateTime(9),
|
|
||||||
Token = GetToken(request.UserKey)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(new { success = true, data = updatedUser });
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return StatusCode(500, new { success = false, message = "更新用户信息失败", error = ex.Message });
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (_connection.State == ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.CloseAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 用户登录接口
|
|
||||||
[HttpPost]
|
|
||||||
public async Task<IActionResult> Login([FromBody] LoginRequest request)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string openId;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
openId = await GetWxOpenIdAsync(request.Code);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return BadRequest(new { success = false, message = "获取微信OpenID失败", error = ex.Message });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_connection.State != ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.OpenAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
UserResponse user = null;
|
|
||||||
|
|
||||||
// 检查用户是否存在
|
|
||||||
using (MySqlCommand checkCmd = new MySqlCommand("SELECT COUNT(1) FROM xcx_users WHERE UserKey = @UserKey", _connection))
|
|
||||||
{
|
|
||||||
checkCmd.Parameters.AddWithValue("@UserKey", openId);
|
|
||||||
int count = Convert.ToInt32(await checkCmd.ExecuteScalarAsync());
|
|
||||||
|
|
||||||
// 如果用户不存在,则注册新用户
|
|
||||||
if (count == 0)
|
|
||||||
{
|
|
||||||
using (MySqlCommand insertCmd = new MySqlCommand("INSERT INTO xcx_users (UserKey, FirstLoginTime, IsDisabled, CreateTime, UpdateTime) VALUES (@UserKey, @FirstLoginTime, @IsDisabled, NOW(), NOW())", _connection))
|
|
||||||
{
|
|
||||||
insertCmd.Parameters.AddWithValue("@UserKey", openId);
|
|
||||||
insertCmd.Parameters.AddWithValue("@FirstLoginTime", DateTime.Now);
|
|
||||||
insertCmd.Parameters.AddWithValue("@IsDisabled", 0); // 默认启用
|
|
||||||
|
|
||||||
await insertCmd.ExecuteNonQueryAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取用户信息
|
|
||||||
using (MySqlCommand cmd = new MySqlCommand("SELECT Id, UserName, UserKey, WeChatName, PhoneNumber, AvatarUrl, FirstLoginTime, IsDisabled, CreateTime, UpdateTime FROM xcx_users WHERE UserKey = @UserKey", _connection))
|
|
||||||
{
|
|
||||||
cmd.Parameters.AddWithValue("@UserKey", openId);
|
|
||||||
|
|
||||||
using (var reader = await cmd.ExecuteReaderAsync())
|
|
||||||
{
|
|
||||||
if (await reader.ReadAsync())
|
|
||||||
{
|
|
||||||
user = new UserResponse
|
|
||||||
{
|
|
||||||
Id = reader.GetInt64(0),
|
|
||||||
UserName = reader.IsDBNull(1) ? "" : reader.GetString(1),
|
|
||||||
UserKey = reader.GetString(2),
|
|
||||||
WeChatName = reader.IsDBNull(3) ? "" : reader.GetString(3),
|
|
||||||
PhoneNumber = reader.IsDBNull(4) ? "" : reader.GetString(4),
|
|
||||||
AvatarUrl = reader.IsDBNull(5) ? "" : reader.GetString(5),
|
|
||||||
FirstLoginTime = reader.GetDateTime(6),
|
|
||||||
IsDisabled = reader.GetBoolean(7),
|
|
||||||
CreateTime = reader.GetDateTime(8),
|
|
||||||
UpdateTime = reader.GetDateTime(9),
|
|
||||||
Token = GetToken(openId)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return NotFound(new { success = false, message = "用户不存在" });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user.IsDisabled)
|
|
||||||
{
|
|
||||||
return Ok(new { success = false, message = "用户已被禁用" });
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(new { success = true, data = user });
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return StatusCode(500, new { success = false, message = "登录失败", error = ex.Message });
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (_connection.State == ConnectionState.Open)
|
|
||||||
{
|
|
||||||
await _connection.CloseAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 请求和响应模型
|
|
||||||
public class RegisterRequest
|
|
||||||
{
|
|
||||||
public string UserName { get; set; }
|
|
||||||
public string UserKey { get; set; } // 改为直接传入UserKey
|
|
||||||
public string WeChatName { get; set; }
|
|
||||||
public string PhoneNumber { get; set; }
|
|
||||||
public string AvatarUrl { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LoginRequest
|
|
||||||
{
|
|
||||||
public string Code { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class UserResponse
|
|
||||||
{
|
|
||||||
public long Id { get; set; }
|
|
||||||
public string UserName { get; set; }
|
|
||||||
public string UserKey { get; set; }
|
|
||||||
public string WeChatName { get; set; }
|
|
||||||
public string PhoneNumber { get; set; }
|
|
||||||
public string AvatarUrl { get; set; }
|
|
||||||
public DateTime FirstLoginTime { get; set; }
|
|
||||||
public bool IsDisabled { get; set; }
|
|
||||||
public DateTime CreateTime { get; set; }
|
|
||||||
public DateTime UpdateTime { get; set; }
|
|
||||||
public string Token { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace WxCheckApi.Controllers
|
|
||||||
{
|
|
||||||
[ApiController]
|
|
||||||
[Route("[controller]")]
|
|
||||||
public class WeatherForecastController : ControllerBase
|
|
||||||
{
|
|
||||||
private static readonly string[] Summaries = new[]
|
|
||||||
{
|
|
||||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
|
||||||
};
|
|
||||||
|
|
||||||
private readonly ILogger<WeatherForecastController> _logger;
|
|
||||||
|
|
||||||
public WeatherForecastController(ILogger<WeatherForecastController> logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet]
|
|
||||||
public IEnumerable<WeatherForecast> Get()
|
|
||||||
{
|
|
||||||
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
|
||||||
{
|
|
||||||
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
|
||||||
TemperatureC = Random.Shared.Next(-20, 55),
|
|
||||||
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
|
|
||||||
})
|
|
||||||
.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|
||||||
using Microsoft.IdentityModel.Tokens;
|
|
||||||
using MySql.Data.MySqlClient;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
|
||||||
|
|
||||||
// Add services to the container.
|
|
||||||
builder.Services.AddControllers();
|
|
||||||
|
|
||||||
// 添加HttpClientFactory
|
|
||||||
builder.Services.AddHttpClient();
|
|
||||||
|
|
||||||
// 添加数据库连接
|
|
||||||
builder.Services.AddScoped<MySqlConnection>(sp => {
|
|
||||||
var connectionString = builder.Configuration.GetConnectionString("MySQLConnection");
|
|
||||||
return new MySqlConnection(connectionString);
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.Services.AddAuthorization();
|
|
||||||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
|
||||||
.AddJwtBearer(option =>
|
|
||||||
{
|
|
||||||
string DefaultKey = "B,EZipeApY3cNj3~4RP0UMR=H>9x8.1!E85wmZ]]py2d$Y?5";
|
|
||||||
var sec = Encoding.UTF8.GetBytes(builder.Configuration["JWT:SecretKey"] ?? DefaultKey);
|
|
||||||
|
|
||||||
option.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
|
|
||||||
{
|
|
||||||
ValidateIssuer = true,
|
|
||||||
ValidateAudience = true,
|
|
||||||
ValidateLifetime = true,
|
|
||||||
|
|
||||||
ValidateIssuerSigningKey = true,
|
|
||||||
ValidIssuer = builder.Configuration["JwT:Issuer"],
|
|
||||||
ValidAudience = builder.Configuration["JwT:Audience"],
|
|
||||||
IssuerSigningKey = new SymmetricSecurityKey(sec)
|
|
||||||
};
|
|
||||||
|
|
||||||
option.Events = new JwtBearerEvents
|
|
||||||
{
|
|
||||||
OnMessageReceived = context =>
|
|
||||||
{
|
|
||||||
var token = context.Request.Headers["token"].FirstOrDefault();
|
|
||||||
if (string.IsNullOrEmpty(token))
|
|
||||||
{
|
|
||||||
// 如果没有找到 token 头部,则继续检查 Authorization 头部
|
|
||||||
token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
|
|
||||||
}
|
|
||||||
// 如果找到了 token,则将其设置到 HttpContext 中
|
|
||||||
if (!string.IsNullOrEmpty(token))
|
|
||||||
{
|
|
||||||
context.Token = token;
|
|
||||||
}
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
var app = builder.Build();
|
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
|
||||||
app.UseAuthentication(); // 添加认证中间件
|
|
||||||
app.UseAuthorization(); // 使用授权中间件
|
|
||||||
|
|
||||||
app.UseAuthorization();
|
|
||||||
|
|
||||||
app.MapControllers();
|
|
||||||
|
|
||||||
app.Run();
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
|
|
||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<DeleteExistingFiles>true</DeleteExistingFiles>
|
|
||||||
<ExcludeApp_Data>false</ExcludeApp_Data>
|
|
||||||
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
|
|
||||||
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
|
|
||||||
<LastUsedPlatform>Any CPU</LastUsedPlatform>
|
|
||||||
<PublishProvider>FileSystem</PublishProvider>
|
|
||||||
<PublishUrl>bin\Release\net8.0\publish\</PublishUrl>
|
|
||||||
<WebPublishMethod>FileSystem</WebPublishMethod>
|
|
||||||
<_TargetId>Folder</_TargetId>
|
|
||||||
<SiteUrlToLaunchAfterPublish />
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
|
||||||
<ProjectGuid>e545c738-a21b-71f3-9fb9-a68d8018822d</ProjectGuid>
|
|
||||||
<SelfContained>false</SelfContained>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
|
|
||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<_PublishTargetUrl>E:\Project\WxCheck\WxCheckApi\bin\Release\net8.0\publish\</_PublishTargetUrl>
|
|
||||||
<History>True|2025-11-08T01:48:12.8385703Z||;True|2025-11-07T15:09:26.3902793+08:00||;True|2025-11-07T11:51:31.5643958+08:00||;True|2025-11-07T11:50:44.2146653+08:00||;True|2025-11-04T14:29:55.7628000+08:00||;False|2025-11-04T14:29:50.0660192+08:00||;True|2025-11-04T14:20:52.6380538+08:00||;True|2025-11-04T10:14:31.0406197+08:00||;True|2025-11-04T10:01:51.9971474+08:00||;True|2025-11-04T09:53:16.2195499+08:00||;True|2025-11-04T09:45:30.2430508+08:00||;True|2025-11-04T08:52:40.6424728+08:00||;True|2025-11-03T21:04:36.1464303+08:00||;True|2025-11-03T20:46:33.3635634+08:00||;True|2025-11-03T20:45:29.5368625+08:00||;True|2025-11-03T20:42:14.5975957+08:00||;True|2025-11-03T20:40:43.0062117+08:00||;True|2025-11-03T20:16:38.4711929+08:00||;True|2025-11-03T20:14:42.8936169+08:00||;True|2025-11-03T19:35:15.7051947+08:00||;True|2025-11-03T19:01:58.6546141+08:00||;True|2025-11-03T17:59:30.0861681+08:00||;True|2025-11-03T16:15:01.5245126+08:00||;True|2025-11-03T16:06:34.1178642+08:00||;True|2025-10-31T17:30:06.3039818+08:00||;True|2025-10-31T16:20:12.7490590+08:00||;True|2025-10-31T15:10:14.4751645+08:00||;</History>
|
|
||||||
<LastFailureDetails />
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
|
|
||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<DeleteExistingFiles>true</DeleteExistingFiles>
|
|
||||||
<ExcludeApp_Data>false</ExcludeApp_Data>
|
|
||||||
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
|
|
||||||
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
|
|
||||||
<LastUsedPlatform>Any CPU</LastUsedPlatform>
|
|
||||||
<PublishProvider>FileSystem</PublishProvider>
|
|
||||||
<PublishUrl>bin\Release\net8.0\publish\</PublishUrl>
|
|
||||||
<WebPublishMethod>FileSystem</WebPublishMethod>
|
|
||||||
<_TargetId>Folder</_TargetId>
|
|
||||||
<SiteUrlToLaunchAfterPublish />
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
|
||||||
<ProjectGuid>e545c738-a21b-71f3-9fb9-a68d8018822d</ProjectGuid>
|
|
||||||
<SelfContained>false</SelfContained>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
|
|
||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<_PublishTargetUrl>E:\Project_Class\WX_XCX\WxCheck_Wx_Prod\WxCheckApi\bin\Release\net8.0\publish\</_PublishTargetUrl>
|
|
||||||
<History>True|2025-12-05T03:46:42.6952752Z||;True|2025-12-03T17:28:08.6000818+08:00||;True|2025-12-03T15:36:17.3153352+08:00||;True|2025-12-03T15:34:35.0408800+08:00||;True|2025-12-03T15:32:13.7754473+08:00||;True|2025-12-03T15:23:43.3405041+08:00||;True|2025-12-03T11:08:15.0823391+08:00||;True|2025-12-03T11:04:29.8829020+08:00||;True|2025-12-03T11:00:07.4056298+08:00||;True|2025-12-03T10:56:38.5220608+08:00||;True|2025-12-03T10:51:59.6142114+08:00||;</History>
|
|
||||||
<LastFailureDetails />
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
|
||||||
"iisSettings": {
|
|
||||||
"windowsAuthentication": false,
|
|
||||||
"anonymousAuthentication": true,
|
|
||||||
"iisExpress": {
|
|
||||||
"applicationUrl": "http://localhost:6041",
|
|
||||||
"sslPort": 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"profiles": {
|
|
||||||
"http": {
|
|
||||||
"commandName": "Project",
|
|
||||||
"dotnetRunMessages": true,
|
|
||||||
"launchBrowser": true,
|
|
||||||
"launchUrl": "weatherforecast",
|
|
||||||
"applicationUrl": "http://localhost:5065",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"IIS Express": {
|
|
||||||
"commandName": "IISExpress",
|
|
||||||
"launchBrowser": true,
|
|
||||||
"launchUrl": "weatherforecast",
|
|
||||||
"environmentVariables": {
|
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
namespace WxCheckApi
|
|
||||||
{
|
|
||||||
public class WeatherForecast
|
|
||||||
{
|
|
||||||
public DateOnly Date { get; set; }
|
|
||||||
|
|
||||||
public int TemperatureC { get; set; }
|
|
||||||
|
|
||||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
|
||||||
|
|
||||||
public string? Summary { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="CSRedisCore" Version="3.8.806" />
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.21" />
|
|
||||||
<PackageReference Include="MySql.Data" Version="8.4.0" />
|
|
||||||
<PackageReference Include="System.Text.Json" Version="8.0.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
@WxCheckApi_HostAddress = http://localhost:5065
|
|
||||||
|
|
||||||
GET {{WxCheckApi_HostAddress}}/weatherforecast/
|
|
||||||
Accept: application/json
|
|
||||||
|
|
||||||
###
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<Solution>
|
|
||||||
<Project Path="../WxCheckMvc/WxCheckMvc.csproj" Id="5f5aee53-ea7f-4a13-a039-d664f136a7f8" />
|
|
||||||
<Project Path="WxCheckApi.csproj" />
|
|
||||||
</Solution>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft.AspNetCore": "Warning"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"JwT": {
|
|
||||||
"SecretKey": "1%猜U36eraIYI?3s9dI}46an不Nn>P]3)$9:dCnS5=ajAu%8B5]15hF到20T20QBD]Mt9}2z76jO#Glg&0yDy7k-2zVdt&Z5ur>=l)QF2^1&Dq04m76U2P9wvlWf",
|
|
||||||
"Issuer": "微信小程序token",
|
|
||||||
"Audience": "W*u93xxp*08DnW@%6}5Tjh6bE?;hW"
|
|
||||||
},
|
|
||||||
"WeChat": {
|
|
||||||
"AppId": "wx42e9add0f91af98b",
|
|
||||||
"AppSecret": "5620f00b40297efaf3d197d61ae184d6"
|
|
||||||
},
|
|
||||||
"Logging": {
|
|
||||||
"LogLevel": {
|
|
||||||
"Default": "Information",
|
|
||||||
"Microsoft.AspNetCore": "Warning"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"AllowedHosts": "*",
|
|
||||||
"ConnectionStrings": {
|
|
||||||
"MySQLConnection": "Server=47.119.147.104;Database=wx_xcx_check;user id=root;password=hbfjW6A_eob;port=3307;"
|
|
||||||
},
|
|
||||||
"AmapApi": {
|
|
||||||
"ApiKey": "4d5cb7818664ada68ae5f68783b8bd4c"
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
Navicat Premium Dump SQL
|
|
||||||
|
|
||||||
Source Server : 47.119.147.104
|
|
||||||
Source Server Type : MariaDB
|
|
||||||
Source Server Version : 120002 (12.0.2-MariaDB)
|
|
||||||
Source Host : 47.119.147.104:3307
|
|
||||||
Source Schema : wx_xcx_check
|
|
||||||
|
|
||||||
Target Server Type : MariaDB
|
|
||||||
Target Server Version : 120002 (12.0.2-MariaDB)
|
|
||||||
File Encoding : 65001
|
|
||||||
|
|
||||||
Date: 05/12/2025 11:40:09
|
|
||||||
*/
|
|
||||||
|
|
||||||
SET NAMES utf8mb4;
|
|
||||||
SET FOREIGN_KEY_CHECKS = 0;
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- Table structure for xcx_conversation
|
|
||||||
-- ----------------------------
|
|
||||||
DROP TABLE IF EXISTS `xcx_conversation`;
|
|
||||||
CREATE TABLE `xcx_conversation` (
|
|
||||||
`Id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
|
||||||
`UserKey` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户唯一标识键',
|
|
||||||
`ConversationContent` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '会话内容',
|
|
||||||
`MessageType` int(11) NOT NULL DEFAULT 1 COMMENT '信息类型:1-公有,2-私有',
|
|
||||||
`SendMethod` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '发送方式',
|
|
||||||
`UserLocation` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '用户定位信息',
|
|
||||||
`RecordTime` datetime NOT NULL COMMENT '记录时间',
|
|
||||||
`RecordTimeUTCStamp` bigint(20) NOT NULL COMMENT '记录时间的UTC时间戳',
|
|
||||||
`IsDeleted` tinyint(4) NULL DEFAULT 0 COMMENT '是否删除:0-正常,1-删除',
|
|
||||||
`CreateTime` datetime NULL DEFAULT current_timestamp() COMMENT '创建时间',
|
|
||||||
`Latitude` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '纬度',
|
|
||||||
`Longitude` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '经度',
|
|
||||||
`Guid` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT 'GUID',
|
|
||||||
`SpeakingTime` int(11) NULL DEFAULT NULL COMMENT '对话时长',
|
|
||||||
PRIMARY KEY (`Id`) USING BTREE,
|
|
||||||
INDEX `idx_userkey`(`UserKey` ASC) USING BTREE,
|
|
||||||
INDEX `idx_utcstamp`(`RecordTimeUTCStamp` ASC) USING BTREE,
|
|
||||||
INDEX `idx_deleted`(`IsDeleted` ASC) USING BTREE,
|
|
||||||
INDEX `idx_recordtime`(`RecordTime` ASC) USING BTREE,
|
|
||||||
INDEX `idx_messagetype`(`MessageType` ASC) USING BTREE,
|
|
||||||
INDEX `idx_guid`(`Guid` ASC) USING BTREE
|
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 418 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '会话记录表' ROW_FORMAT = Dynamic;
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- Table structure for xcx_log
|
|
||||||
-- ----------------------------
|
|
||||||
DROP TABLE IF EXISTS `xcx_log`;
|
|
||||||
CREATE TABLE `xcx_log` (
|
|
||||||
`Id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
|
||||||
`RecordTime` datetime NOT NULL COMMENT '记录时间',
|
|
||||||
`UserKey` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户唯一标识键',
|
|
||||||
`OperationContent` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '操作内容',
|
|
||||||
`UserLocation` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT '用户定位信息',
|
|
||||||
`Impact` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '产生的影响',
|
|
||||||
`CreateTime` datetime NULL DEFAULT current_timestamp() COMMENT '创建时间',
|
|
||||||
PRIMARY KEY (`Id`) USING BTREE,
|
|
||||||
INDEX `idx_userkey`(`UserKey` ASC) USING BTREE,
|
|
||||||
INDEX `idx_recordtime`(`RecordTime` ASC) USING BTREE
|
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志表' ROW_FORMAT = Dynamic;
|
|
||||||
|
|
||||||
-- ----------------------------
|
|
||||||
-- Table structure for xcx_users
|
|
||||||
-- ----------------------------
|
|
||||||
DROP TABLE IF EXISTS `xcx_users`;
|
|
||||||
CREATE TABLE `xcx_users` (
|
|
||||||
`Id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
|
||||||
`UserName` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '用户名',
|
|
||||||
`UserKey` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户唯一标识键',
|
|
||||||
`WeChatName` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '微信名称',
|
|
||||||
`PhoneNumber` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '电话号码',
|
|
||||||
`FirstLoginTime` datetime NOT NULL COMMENT '首次登录时间',
|
|
||||||
`IsDisabled` tinyint(4) NULL DEFAULT 0 COMMENT '是否禁用:0-启用,1-禁用',
|
|
||||||
`CreateTime` datetime NULL DEFAULT current_timestamp() COMMENT '创建时间',
|
|
||||||
`UpdateTime` datetime NULL DEFAULT current_timestamp() ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
|
||||||
`AvatarUrl` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '头像地址',
|
|
||||||
PRIMARY KEY (`Id`) USING BTREE,
|
|
||||||
UNIQUE INDEX `idx_userkey`(`UserKey` ASC) USING BTREE,
|
|
||||||
INDEX `idx_disabled`(`IsDisabled` ASC) USING BTREE,
|
|
||||||
INDEX `idx_logintime`(`FirstLoginTime` ASC) USING BTREE
|
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 22 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '小程序用户表' ROW_FORMAT = Dynamic;
|
|
||||||
|
|
||||||
SET FOREIGN_KEY_CHECKS = 1;
|
|
||||||
Reference in New Issue
Block a user