Jelajahi Sumber

1、初始话新版saas

yys 3 minggu lalu
induk
melakukan
f1869716b0
100 mengubah file dengan 2179 tambahan dan 11316 penghapusan
  1. 3 0
      deploy/chroma/.env
  2. 32 0
      deploy/chroma/backup.sh
  3. 85 0
      deploy/chroma/deploy.sh
  4. 32 0
      deploy/chroma/docker-compose.yml
  5. 61 0
      deploy/chroma/test.sh
  6. TEMPAT SAMPAH
      doc.jpg
  7. 0 879
      docs/Qdrant API 文档.md
  8. 0 314
      docs/SaaS改造方案.md
  9. 0 151
      docs/SaaS计费模块产品文档-业务简版.md
  10. 0 488
      docs/SaaS计费模块产品文档.md
  11. 0 152
      docs/user-app更改.md
  12. 0 83
      docs/方案.md
  13. 0 271
      docs/租户库升级方案.md
  14. 0 119
      docs/租户费用模块.postman_collection.json
  15. 0 200
      docs/租户费用模块SQL-master.sql
  16. 0 12
      docs/租户费用模块SQL-tenant.sql
  17. 0 203
      docs/租户费用模块SQL.sql
  18. 0 78
      docs/计费模块菜单SQL-总账号-计费配置入口.sql
  19. 0 66
      docs/计费模块菜单SQL-总账号.sql
  20. 0 70
      docs/计费模块菜单SQL-租户账号.sql
  21. 0 215
      fs-ad-api/src/main/java/com/fs/app/controller/MockAppController.java
  22. 0 46
      fs-ad-new-api/src/main/java/com/fs/app/controller/TestController.java
  23. 34 1
      fs-admin/pom.xml
  24. 0 78
      fs-admin/src/main/java/com/fs/ad/controller/AdCallbackController.java
  25. 3 2
      fs-admin/src/main/java/com/fs/ad/controller/MockAppController.java
  26. 3 2
      fs-admin/src/main/java/com/fs/ad/controller/task/BaiduTask.java
  27. 71 0
      fs-admin/src/main/java/com/fs/admin/controller/AdminAdController.java
  28. 75 0
      fs-admin/src/main/java/com/fs/admin/controller/AdminCrmController.java
  29. 84 0
      fs-admin/src/main/java/com/fs/admin/controller/AdminModuleUsageController.java
  30. 103 0
      fs-admin/src/main/java/com/fs/admin/controller/AdminProxyController.java
  31. 113 0
      fs-admin/src/main/java/com/fs/admin/controller/AdminSopController.java
  32. 262 0
      fs-admin/src/main/java/com/fs/admin/controller/AdminStatisticsController.java
  33. 71 0
      fs-admin/src/main/java/com/fs/admin/controller/AdminStoreOrderController.java
  34. 95 0
      fs-admin/src/main/java/com/fs/admin/controller/AiChatQualityController.java
  35. 102 0
      fs-admin/src/main/java/com/fs/admin/controller/AiProviderAdminController.java
  36. 103 0
      fs-admin/src/main/java/com/fs/admin/controller/ArticleAdminController.java
  37. 140 0
      fs-admin/src/main/java/com/fs/admin/controller/CallRecordAdminController.java
  38. 118 0
      fs-admin/src/main/java/com/fs/admin/controller/CompanyAdminController.java
  39. 124 0
      fs-admin/src/main/java/com/fs/admin/controller/CompanyUserAdminController.java
  40. 90 0
      fs-admin/src/main/java/com/fs/admin/controller/CourseAdminController.java
  41. 90 0
      fs-admin/src/main/java/com/fs/admin/controller/LiveAdminController.java
  42. 90 0
      fs-admin/src/main/java/com/fs/admin/controller/LobsterAdminController.java
  43. 102 0
      fs-admin/src/main/java/com/fs/admin/controller/ProductAdminController.java
  44. 87 0
      fs-admin/src/main/java/com/fs/admin/controller/QwExternalContactAdminController.java
  45. 3 2
      fs-admin/src/main/java/com/fs/api/controller/IndexStatisticsController.java
  46. 3 2
      fs-admin/src/main/java/com/fs/api/controller/StatisticManageController.java
  47. 0 48
      fs-admin/src/main/java/com/fs/company/controller/CompanyConfigController.java
  48. 0 308
      fs-admin/src/main/java/com/fs/company/controller/CompanyController.java
  49. 0 153
      fs-admin/src/main/java/com/fs/company/controller/CompanyDeductController.java
  50. 0 116
      fs-admin/src/main/java/com/fs/company/controller/CompanyDeptController.java
  51. 0 130
      fs-admin/src/main/java/com/fs/company/controller/CompanyDomainBindController.java
  52. 0 99
      fs-admin/src/main/java/com/fs/company/controller/CompanyDomainBindUserController.java
  53. 0 189
      fs-admin/src/main/java/com/fs/company/controller/CompanyDomainController.java
  54. 0 97
      fs-admin/src/main/java/com/fs/company/controller/CompanyLogininforController.java
  55. 0 121
      fs-admin/src/main/java/com/fs/company/controller/CompanyMenuController.java
  56. 0 188
      fs-admin/src/main/java/com/fs/company/controller/CompanyMoneyLogsController.java
  57. 0 97
      fs-admin/src/main/java/com/fs/company/controller/CompanyOperLogController.java
  58. 0 97
      fs-admin/src/main/java/com/fs/company/controller/CompanyPostController.java
  59. 0 276
      fs-admin/src/main/java/com/fs/company/controller/CompanyProfitController.java
  60. 0 144
      fs-admin/src/main/java/com/fs/company/controller/CompanyRechargeController.java
  61. 0 63
      fs-admin/src/main/java/com/fs/company/controller/CompanyRedPackageController.java
  62. 0 103
      fs-admin/src/main/java/com/fs/company/controller/CompanyRedPacketBalanceLogsController.java
  63. 0 97
      fs-admin/src/main/java/com/fs/company/controller/CompanyRoleController.java
  64. 0 97
      fs-admin/src/main/java/com/fs/company/controller/CompanyRoleDeptController.java
  65. 0 97
      fs-admin/src/main/java/com/fs/company/controller/CompanyRoleMenuController.java
  66. 0 98
      fs-admin/src/main/java/com/fs/company/controller/CompanySmsController.java
  67. 0 122
      fs-admin/src/main/java/com/fs/company/controller/CompanySmsLogsController.java
  68. 0 99
      fs-admin/src/main/java/com/fs/company/controller/CompanySmsOrderController.java
  69. 0 97
      fs-admin/src/main/java/com/fs/company/controller/CompanySmsPackageController.java
  70. 0 115
      fs-admin/src/main/java/com/fs/company/controller/CompanySmsTempController.java
  71. 0 793
      fs-admin/src/main/java/com/fs/company/controller/CompanyStatisticsController.java
  72. 0 261
      fs-admin/src/main/java/com/fs/company/controller/CompanyTcmReportController.java
  73. 0 120
      fs-admin/src/main/java/com/fs/company/controller/CompanyTcmScheduleController.java
  74. 0 118
      fs-admin/src/main/java/com/fs/company/controller/CompanyTrafficController.java
  75. 0 49
      fs-admin/src/main/java/com/fs/company/controller/CompanyTrafficLogController.java
  76. 0 586
      fs-admin/src/main/java/com/fs/company/controller/CompanyUserAllController.java
  77. 0 201
      fs-admin/src/main/java/com/fs/company/controller/CompanyUserController.java
  78. 0 97
      fs-admin/src/main/java/com/fs/company/controller/CompanyUserPostController.java
  79. 0 97
      fs-admin/src/main/java/com/fs/company/controller/CompanyUserRoleController.java
  80. 0 104
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceApiController.java
  81. 0 97
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceBlacklistController.java
  82. 0 137
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceCallerController.java
  83. 0 169
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceConfigController.java
  84. 0 102
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceController.java
  85. 0 106
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceDialogController.java
  86. 0 133
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceLogsController.java
  87. 0 124
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceMobileController.java
  88. 0 97
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoicePackageController.java
  89. 0 99
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoicePackageOrderController.java
  90. 0 97
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceRoboticCalleesController.java
  91. 0 200
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceRoboticController.java
  92. 0 97
      fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceRoboticWxController.java
  93. 0 115
      fs-admin/src/main/java/com/fs/company/controller/CompanyWxAccountController.java
  94. 0 125
      fs-admin/src/main/java/com/fs/company/controller/CompanyWxClientController.java
  95. 0 104
      fs-admin/src/main/java/com/fs/company/controller/CompanyWxDialogController.java
  96. 0 146
      fs-admin/src/main/java/com/fs/company/controller/CompanyWxUserController.java
  97. 0 107
      fs-admin/src/main/java/com/fs/company/controller/CompanyWxUserGroupController.java
  98. 0 145
      fs-admin/src/main/java/com/fs/company/controller/ExternalApiConfigController.java
  99. 0 57
      fs-admin/src/main/java/com/fs/company/controller/IndexController.java
  100. 0 148
      fs-admin/src/main/java/com/fs/course/controller/FsCourseWatchCommentController.java

+ 3 - 0
deploy/chroma/.env

@@ -0,0 +1,3 @@
+CHROMA_AUTH_TOKEN=your_secure_token_here_change_me
+EMBEDDING_API_KEY=your_embedding_api_key_here
+OPENAI_API_KEY=your_openai_api_key_here

+ 32 - 0
deploy/chroma/backup.sh

@@ -0,0 +1,32 @@
+#!/bin/bash
+
+BACKUP_DIR="/data/chroma/backups"
+DATE=$(date +%Y%m%d_%H%M%S)
+BACKUP_FILE="chroma_backup_$DATE.tar.gz"
+
+echo "======================================"
+echo "  Chroma 数据备份脚本"
+echo "======================================"
+echo ""
+
+mkdir -p $BACKUP_DIR
+
+echo "[1/3] 创建备份..."
+docker exec chroma_server tar -czf /tmp/$BACKUP_FILE -C /chroma chroma_data
+
+echo "[2/3] 复制备份文件..."
+docker cp chroma_server:/tmp/$BACKUP_FILE $BACKUP_DIR/
+
+echo "[3/3] 清理旧备份..."
+find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete
+
+BACKUP_SIZE=$(du -h $BACKUP_DIR/$BACKUP_FILE | cut -f1)
+
+echo ""
+echo "======================================"
+echo "  备份完成!"
+echo "======================================"
+echo ""
+echo "备份文件: $BACKUP_DIR/$BACKUP_FILE"
+echo "文件大小: $BACKUP_SIZE"
+echo ""

+ 85 - 0
deploy/chroma/deploy.sh

@@ -0,0 +1,85 @@
+#!/bin/bash
+
+echo "======================================"
+echo "  Chroma 向量数据库部署脚本"
+echo "======================================"
+echo ""
+
+DEPLOY_DIR="/opt/chroma"
+DATA_DIR="/data/chroma"
+
+echo "[1/5] 检查环境..."
+if ! command -v docker &> /dev/null; then
+    echo "错误: Docker 未安装,请先安装 Docker"
+    exit 1
+fi
+
+if ! command -v docker-compose &> /dev/null; then
+    echo "错误: Docker Compose 未安装,请先安装 Docker Compose"
+    exit 1
+fi
+
+echo "[2/5] 创建目录..."
+mkdir -p $DEPLOY_DIR
+mkdir -p $DATA_DIR/chroma_data
+
+echo "[3/5] 生成配置文件..."
+
+cat > $DEPLOY_DIR/docker-compose.yml << 'EOF'
+version: '3.8'
+
+services:
+  chroma:
+    image: chromadb/chroma:latest
+    container_name: chroma_server
+    ports:
+      - "8000:8000"
+    volumes:
+      - /data/chroma/chroma_data:/chroma/chroma_data
+    environment:
+      - CHROMA_SERVER_HOST=0.0.0.0
+      - CHROMA_SERVER_HTTP_PORT=8000
+      - CHROMA_SERVER_AUTH_CREDENTIALS=${CHROMA_AUTH_TOKEN}
+      - CHROMA_SERVER_AUTH_PROVIDER=chromadb.auth.token.TokenAuthProvider
+      - ANONYMIZED_TELEMETRY=False
+    restart: unless-stopped
+    healthcheck:
+      test: ["CMD", "curl", "-f", "http://localhost:8000/api/v1/heartbeat"]
+      interval: 30s
+      timeout: 10s
+      retries: 3
+    networks:
+      - chroma_network
+
+networks:
+  chroma_network:
+    driver: bridge
+EOF
+
+AUTH_TOKEN=$(openssl rand -hex 32)
+
+cat > $DEPLOY_DIR/.env << EOF
+CHROMA_AUTH_TOKEN=$AUTH_TOKEN
+EMBEDDING_API_KEY=your_embedding_api_key_here
+OPENAI_API_KEY=your_openai_api_key_here
+EOF
+
+echo "[4/5] 启动服务..."
+cd $DEPLOY_DIR
+docker-compose up -d
+
+echo "[5/5] 等待服务启动..."
+sleep 10
+
+echo ""
+echo "======================================"
+echo "  部署完成!"
+echo "======================================"
+echo ""
+echo "服务地址: http://localhost:8000"
+echo "认证Token: $AUTH_TOKEN"
+echo ""
+echo "验证命令: curl http://localhost:8000/api/v1/heartbeat"
+echo ""
+echo "配置文件位置: $DEPLOY_DIR/.env"
+echo ""

+ 32 - 0
deploy/chroma/docker-compose.yml

@@ -0,0 +1,32 @@
+version: '3.8'
+
+services:
+  chroma:
+    image: chromadb/chroma:latest
+    container_name: chroma_server
+    ports:
+      - "8000:8000"
+    volumes:
+      - ./chroma_data:/chroma/chroma_data
+    environment:
+      - CHROMA_SERVER_HOST=0.0.0.0
+      - CHROMA_SERVER_HTTP_PORT=8000
+      - CHROMA_SERVER_AUTH_CREDENTIALS=${CHROMA_AUTH_TOKEN}
+      - CHROMA_SERVER_AUTH_PROVIDER=chromadb.auth.token.TokenAuthProvider
+      - ANONYMIZED_TELEMETRY=False
+    restart: unless-stopped
+    healthcheck:
+      test: ["CMD", "curl", "-f", "http://localhost:8000/api/v1/heartbeat"]
+      interval: 30s
+      timeout: 10s
+      retries: 3
+    networks:
+      - chroma_network
+
+networks:
+  chroma_network:
+    driver: bridge
+
+volumes:
+  chroma_data:
+    driver: local

+ 61 - 0
deploy/chroma/test.sh

@@ -0,0 +1,61 @@
+#!/bin/bash
+
+echo "======================================"
+echo "  Chroma 服务测试脚本"
+echo "======================================"
+echo ""
+
+CHROMA_URL="http://localhost:8000"
+API_BASE="http://localhost:8080"
+
+echo "[1/4] 测试 Chroma 健康状态..."
+HEALTH=$(curl -s -o /dev/null -w "%{http_code}" $CHROMA_URL/api/v1/heartbeat)
+if [ "$HEALTH" -eq 200 ]; then
+    echo "✓ Chroma 服务正常"
+else
+    echo "✗ Chroma 服务异常 (HTTP $HEALTH)"
+    exit 1
+fi
+
+echo ""
+echo "[2/4] 测试知识库检索..."
+SEARCH_RESULT=$(curl -s -X POST $API_BASE/api/knowledge/search \
+  -H "Content-Type: application/json" \
+  -d '{
+    "tenantId": "1",
+    "collectionName": "workflow_knowledge_base",
+    "question": "产品功能",
+    "topK": 5
+  }')
+
+if [ -n "$SEARCH_RESULT" ]; then
+    echo "✓ 知识库检索成功"
+    echo "结果: $SEARCH_RESULT"
+else
+    echo "✗ 知识库检索失败"
+fi
+
+echo ""
+echo "[3/4] 测试对话接口..."
+CHAT_RESULT=$(curl -s -X POST $API_BASE/api/chat \
+  -H "Content-Type: application/json" \
+  -d '{
+    "question": "你们的产品有什么功能?",
+    "companyId": 1
+  }')
+
+if [ -n "$CHAT_RESULT" ]; then
+    echo "✓ 对话接口正常"
+    echo "响应: $CHAT_RESULT"
+else
+    echo "✗ 对话接口异常"
+fi
+
+echo ""
+echo "[4/4] 测试数据迁移..."
+echo "请手动执行迁移测试: mvn test -Dtest=ChromaMigrationTest"
+
+echo ""
+echo "======================================"
+echo "  测试完成!"
+echo "======================================"

TEMPAT SAMPAH
doc.jpg


+ 0 - 879
docs/Qdrant API 文档.md

@@ -1,879 +0,0 @@
-# Qdrant REST API 文档
-
-> **基础地址**: `https://saaschroma.ylrzcloud.com`
-> **Qdrant 版本**: 1.17.1
-> **向量维度**: 1024
-> **距离算法**: Cosine
-> **已有 Collection**: `saasai_3`
-
-> 所有请求 **Content-Type**: `application/json`
-
----
-
-## 目录
-
-1. [基础信息](#1-基础信息)
-2. [Collection 管理](#2-collection-管理)
-3. [Point 管理](#3-point-管理)
-4. [向量搜索](#4-向量搜索)
-5. [Cluster 管理](#5-cluster-管理)
-
----
-
-## 1. 基础信息
-
-### 1.1 获取服务状态
-
-```
-GET https://saaschroma.ylrzcloud.com/
-```
-
-**响应示例**:
-
-```json
-{
-  "title": "qdrant - vector search engine",
-  "version": "1.17.1",
-  "commit": "eabee371fda447974a94d29fbaa675a6a596cc7b"
-}
-```
-
----
-
-## 2. Collection 管理
-
-### 2.1 获取所有 Collection 列表
-
-```
-GET https://saaschroma.ylrzcloud.com/collections
-```
-
-**响应示例**:
-
-```json
-{
-  "result": {
-    "collections": [
-      {
-        "name": "saasai_3"
-      }
-    ]
-  },
-  "status": "ok",
-  "time": 5.9e-6
-}
-```
-
----
-
-### 2.2 获取 Collection 详情
-
-```
-GET https://saaschroma.ylrzcloud.com/collections/saasai_3
-```
-
-**响应示例**:
-
-```json
-{
-  "result": {
-    "status": "green",
-    "optimizer_status": "ok",
-    "indexed_vectors_count": 0,
-    "points_count": 1,
-    "segments_count": 4,
-    "config": {
-      "params": {
-        "vectors": {
-          "size": 1024,
-          "distance": "Cosine"
-        },
-        "shard_number": 1,
-        "replication_factor": 1,
-        "write_consistency_factor": 1,
-        "on_disk_payload": true
-      },
-      "hnsw_config": {
-        "m": 16,
-        "ef_construct": 100,
-        "full_scan_threshold": 10000,
-        "max_indexing_threads": 0,
-        "on_disk": false
-      },
-      "optimizer_config": {
-        "deleted_threshold": 0.2,
-        "vacuum_min_vector_number": 1000,
-        "default_segment_number": 0,
-        "max_segment_size": null,
-        "indexing_threshold": 10000,
-        "flush_interval_sec": 5
-      },
-      "wal_config": {
-        "wal_capacity_mb": 32,
-        "wal_segments_ahead": 0
-      },
-      "quantization_config": null
-    },
-    "payload_schema": {},
-    "update_queue": {
-      "length": 0
-    }
-  },
-  "status": "ok",
-  "time": 0.0002909
-}
-```
-
----
-
-### 2.3 创建 Collection
-
-```
-PUT https://saaschroma.ylrzcloud.com/collections/{collectionName}
-```
-
-**请求参数**(Path 参数):
-
-| 参数 | 类型 | 说明 |
-|------|------|------|
-| collectionName | String | 集合名称,例如 `my_knowledge_base` |
-
-**请求体**:
-
-```json
-{
-  "vectors": {
-    "size": 1024,
-    "distance": "Cosine"
-  }
-}
-```
-
-**参数说明**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| vectors.size | int | 是 | 向量维度(当前固定 1024) |
-| vectors.distance | String | 是 | 距离算法:`Cosine` / `Euclid` / `Dot` |
-
-**响应示例**:
-
-```json
-{
-  "result": true,
-  "status": "ok",
-  "time": 0.058248
-}
-```
-
----
-
-### 2.4 删除 Collection
-
-```
-DELETE https://saaschroma.ylrzcloud.com/collections/{collectionName}
-```
-
-**请求参数**(Path 参数):
-
-| 参数 | 类型 | 说明 |
-|------|------|------|
-| collectionName | String | 要删除的集合名称 |
-
-**响应示例**:
-
-```json
-{
-  "result": true,
-  "status": "ok",
-  "time": 0.016075
-}
-```
-
----
-
-### 2.5 更新 Collection 配置
-
-```
-PATCH https://saaschroma.ylrzcloud.com/collections/{collectionName}
-```
-
-**请求体**:
-
-```json
-{
-  "optimizers_config": {
-    "indexing_threshold": 10000
-  },
-  "params": {
-    "replication_factor": 2,
-    "write_consistency_factor": 1
-  }
-}
-```
-
-**参数说明**:
-
-| 参数 | 类型 | 说明 |
-|------|------|------|
-| optimizers_config.indexing_threshold | int | 索引阈值,超过此数量自动建索引 |
-| params.replication_factor | int | 副本因子 |
-| params.write_consistency_factor | int | 写入一致性因子 |
-
-**响应示例**:
-
-```json
-{
-  "result": true,
-  "status": "ok",
-  "time": 0.053372
-}
-```
-
----
-
-## 3. Point 管理
-
-### 3.1 批量写入(Upsert)Points
-
-```
-PUT https://saaschroma.ylrzcloud.com/collections/{collectionName}/points
-```
-
-**请求参数**(Path 参数):
-
-| 参数 | 类型 | 说明 |
-|------|------|------|
-| collectionName | String | 集合名称 |
-
-**请求体**:
-
-```json
-{
-  "points": [
-    {
-      "id": 1,
-      "vector": [0.01, 0.02, 0.03, ...],  ← 1024 个 float
-      "payload": {
-        "document": "这份文件的主要内容是关于XX疾病的基本知识。",
-        "chunk_index": 0,
-        "doc_id": 1001,
-        "dataset_id": 1,
-        "file_name": "XX疾病知识手册.pdf"
-      }
-    },
-    {
-      "id": 2,
-      "vector": [0.04, 0.05, 0.06, ...],  ← 1024 个 float
-      "payload": {
-        "document": "疾病的病因包括遗传因素和环境因素两个方面。",
-        "chunk_index": 1,
-        "doc_id": 1001,
-        "dataset_id": 1,
-        "file_name": "XX疾病知识手册.pdf"
-      }
-    }
-  ],
-  "wait": true
-}
-```
-
-**参数说明**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| points[].id | int/long | 是 | Point 唯一 ID |
-| points[].vector | float[] | 是 | 向量数据,长度 1024 |
-| points[].payload | object | 否 | 附加元数据 |
-| wait | boolean | 否 | true=等待写入完成再返回;false=异步返回 |
-
-**响应示例**:
-
-```json
-{
-  "result": {
-    "operation_id": 123,
-    "status": "completed"
-  },
-  "status": "ok",
-  "time": 0.015
-}
-```
-
----
-
-### 3.2 查询单个 Point
-
-```
-GET https://saaschroma.ylrzcloud.com/collections/{collectionName}/points/{id}?with_payload=true&with_vector=true
-```
-
-**请求参数**:
-
-| 参数 | 位置 | 类型 | 必填 | 说明 |
-|------|------|------|------|------|
-| collectionName | Path | String | 是 | 集合名称 |
-| id | Path | long | 是 | Point ID |
-| with_payload | Query | boolean | 否 | 是否返回 payload,默认 false |
-| with_vector | Query | boolean | 否 | 是否返回 vector,默认 false |
-
-**响应示例**:
-
-```json
-{
-  "result": {
-    "id": 1,
-    "version": 2,
-    "payload": {
-      "document": "这份文件的主要内容是关于XX疾病的基本知识。",
-      "chunk_index": 0,
-      "doc_id": 1001,
-      "file_name": "XX疾病知识手册.pdf"
-    },
-    "vector": [0.01, 0.02, 0.03, ...]
-  },
-  "status": "ok",
-  "time": 0.000227
-}
-```
-
----
-
-### 3.3 滚动查询 Points(分页)
-
-```
-POST https://saaschroma.ylrzcloud.com/collections/{collectionName}/points/scroll
-```
-
-**请求体**:
-
-```json
-{
-  "limit": 10,
-  "offset": 0,
-  "with_payload": true,
-  "with_vector": false,
-  "filter": {
-    "must": [
-      {
-        "key": "doc_id",
-        "match": {
-          "value": 1001
-        }
-      }
-    ]
-  }
-}
-```
-
-**参数说明**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| limit | int | 否 | 返回数量,默认 10 |
-| offset | long/int | 否 | 偏移量(从 0 开始) |
-| with_payload | boolean | 否 | 是否返回 payload |
-| with_vector | boolean | 否 | 是否返回 vector |
-| filter | object | 否 | 筛选条件 |
-
-**响应示例**:
-
-```json
-{
-  "result": {
-    "points": [
-      {
-        "id": 1,
-        "payload": {
-          "document": "这份文件的主要内容是关于XX疾病的基本知识。",
-          "chunk_index": 0,
-          "doc_id": 1001
-        },
-        "vector": null
-      },
-      {
-        "id": 2,
-        "payload": {
-          "document": "疾病的病因包括遗传因素和环境因素两个方面。",
-          "chunk_index": 1,
-          "doc_id": 1001
-        },
-        "vector": null
-      }
-    ],
-    "next_page_offset": 2
-  },
-  "status": "ok",
-  "time": 0.0001
-}
-```
-
-> 注:`next_page_offset` 为 null 时表示无更多数据。将 `next_page_offset` 作为下一次请求的 `offset` 参数即可翻页。
-
----
-
-### 3.4 删除 Points
-
-```
-POST https://saaschroma.ylrzcloud.com/collections/{collectionName}/points/delete
-```
-
-**请求体(按 ID 删除)**:
-
-```json
-{
-  "points": [1, 2, 3],
-  "wait": true
-}
-```
-
-**请求体(按 Filter 删除)**:
-
-```json
-{
-  "filter": {
-    "must": [
-      {
-        "key": "doc_id",
-        "match": {
-          "value": 1001
-        }
-      }
-    ]
-  },
-  "wait": true
-}
-```
-
-**参数说明**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| points | long[] | 二选一 | 按 ID 列表删除 |
-| filter | object | 二选一 | 按筛选条件删除 |
-| wait | boolean | 否 | 是否等待完成 |
-
-**响应示例**:
-
-```json
-{
-  "result": {
-    "operation_id": 456,
-    "status": "completed"
-  },
-  "status": "ok",
-  "time": 0.005
-}
-```
-
----
-
-### 3.5 计数 Points
-
-```
-POST https://saaschroma.ylrzcloud.com/collections/{collectionName}/points/count
-```
-
-> 注意:不是 GET,是 POST
-
-**请求体**:
-
-```json
-{
-  "filter": {
-    "must": [
-      {
-        "key": "doc_id",
-        "match": {
-          "value": 1001
-        }
-      }
-    ]
-  }
-}
-```
-
-**参数说明**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| filter | object | 否 | 筛选条件;不传则统计整个 Collection 总数 |
-
-**响应示例**:
-
-```json
-{
-  "result": {
-    "count": 5
-  },
-  "status": "ok",
-  "time": 0.00005
-}
-```
-
----
-
-### 3.6 更新向量(不修改 Payload)
-
-```
-PUT https://saaschroma.ylrzcloud.com/collections/{collectionName}/points/vectors
-```
-
-**请求体**:
-
-```json
-{
-  "points": [
-    {
-      "id": 1,
-      "vector": [0.05, 0.06, 0.07, ...]
-    },
-    {
-      "id": 2,
-      "vector": [0.08, 0.09, 0.10, ...]
-    }
-  ],
-  "wait": true
-}
-```
-
-**响应示例**:
-
-```json
-{
-  "result": {
-    "operation_id": 789,
-    "status": "completed"
-  },
-  "status": "ok",
-  "time": 0.012
-}
-```
-
----
-
-### 3.7 设置 Payload
-
-```
-POST https://saaschroma.ylrzcloud.com/collections/{collectionName}/points/payload
-```
-
-**请求体**:
-
-```json
-{
-  "payload": {
-    "category": "内科",
-    "tags": ["高血压", "糖尿病"],
-    "importance": 5
-  },
-  "points": [1, 2, 3],
-  "wait": true
-}
-```
-
-> 可选使用 `filter` 替代 `points` 按筛选条件设置
-
-**响应示例**:
-
-```json
-{
-  "result": {
-    "operation_id": 101,
-    "status": "completed"
-  },
-  "status": "ok",
-  "time": 0.008
-}
-```
-
----
-
-### 3.8 按 Key 删除 Payload
-
-```
-POST https://saaschroma.ylrzcloud.com/collections/{collectionName}/points/payload/delete
-```
-
-**请求体**:
-
-```json
-{
-  "keys": ["category", "tags"],
-  "points": [1, 2],
-  "wait": true
-}
-```
-
-> 可选使用 `filter` 替代 `points` 按筛选条件删除
-
-**响应示例**:
-
-```json
-{
-  "result": {
-    "operation_id": 102,
-    "status": "completed"
-  },
-  "status": "ok",
-  "time": 0.006
-}
-```
-
----
-
-### 3.9 清空所有 Payload
-
-```
-PUT https://saaschroma.ylrzcloud.com/collections/{collectionName}/points/payload/clear
-```
-
-**请求体**:
-
-```json
-{
-  "points": [1, 2, 3],
-  "wait": true
-}
-```
-
-> 可选使用 `filter` 替代 `points` 按筛选条件清空
-
-**响应示例**:
-
-```json
-{
-  "result": {
-    "operation_id": 103,
-    "status": "completed"
-  },
-  "status": "ok",
-  "time": 0.007
-}
-```
-
----
-
-## 4. 向量搜索
-
-### 4.1 向量相似度搜索
-
-```
-POST https://saaschroma.ylrzcloud.com/collections/{collectionName}/points/search
-```
-
-**请求体**:
-
-```json
-{
-  "vector": [0.01, 0.02, 0.03, ...],
-  "limit": 5,
-  "with_payload": true,
-  "with_vector": false,
-  "filter": {
-    "must": [
-      {
-        "key": "dataset_id",
-        "match": {
-          "value": 1
-        }
-      },
-      {
-        "key": "doc_id",
-        "match": {
-          "value": 1001
-        }
-      }
-    ]
-  },
-  "params": {
-    "hnsw_ef": 128,
-    "exact": false
-  }
-}
-```
-
-**参数说明**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| vector | float[] | 是 | 查询向量,长度 1024 |
-| limit | int | 否 | 返回 TopK 数量,默认 10 |
-| with_payload | boolean | 否 | 是否返回 payload |
-| with_vector | boolean | 否 | 是否返回 vector |
-| filter.must[] | object[] | 否 | 筛选条件(AND 关系) |
-| filter.should[] | object[] | 否 | 筛选条件(OR 关系) |
-| params.hnsw_ef | int | 否 | 搜索精度(越大越精确越慢),默认 128 |
-| params.exact | boolean | 否 | true=精确搜索,false=近似搜索 |
-
-**Filter 条件详细说明**:
-
-```json
-{
-  "must": [
-    { "key": "string_field",   "match":         { "value": "xxx" } },     // 精确匹配
-    { "key": "keyword_field",  "match":         { "keyword": "xxx" } },   // 关键词匹配
-    { "key": "text_field",     "match":         { "text": "xxx" } },      // 全文匹配(需配置全文索引)
-    { "key": "int_field",      "range":         { "gte": 1, "lte": 100 } },  // 范围匹配
-    { "key": "id_field",       "has_id":        [1, 2, 3] },              // ID 匹配
-    { "key": "ids_field",      "values_count":  { "gte": 2 } }            // 数组数量匹配
-  ],
-  "should": [ /* 同 must 结构,OR 逻辑 */ ],
-  "must_not": [ /* 同 must 结构,排除匹配 */ ]
-}
-```
-
-**响应示例**:
-
-```json
-{
-  "result": [
-    {
-      "id": 2,
-      "version": 2,
-      "score": 0.923456,
-      "payload": {
-        "document": "疾病的病因包括遗传因素和环境因素两个方面。",
-        "chunk_index": 1,
-        "doc_id": 1001,
-        "dataset_id": 1,
-        "file_name": "XX疾病知识手册.pdf"
-      },
-      "vector": null
-    },
-    {
-      "id": 1,
-      "version": 2,
-      "score": 0.891234,
-      "payload": {
-        "document": "这份文件的主要内容是关于XX疾病的基本知识。",
-        "chunk_index": 0,
-        "doc_id": 1001,
-        "dataset_id": 1,
-        "file_name": "XX疾病知识手册.pdf"
-      },
-      "vector": null
-    }
-  ],
-  "status": "ok",
-  "time": 0.002
-}
-```
-
-> **注意**:`score` 值范围 0~1(Cosine 距离),值越大表示越相似。
-
----
-
-### 4.2 分组搜索
-
-```
-POST https://saaschroma.ylrzcloud.com/collections/{collectionName}/points/search/groups
-```
-
-**请求体**:
-
-```json
-{
-  "vector": [0.01, 0.02, 0.03, ...],
-  "limit": 5,
-  "group_by": "doc_id",
-  "group_size": 3,
-  "with_payload": true,
-  "with_vector": false
-}
-```
-
-**参数说明**:
-
-| 参数 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| group_by | String | 是 | 按哪个 payload key 分组 |
-| group_size | int | 是 | 每组返回多少个结果 |
-| limit | int | 是 | 返回多少组 |
-
-**响应示例**:
-
-```json
-{
-  "result": {
-    "groups": [
-      {
-        "id": "1001",
-        "hits": [
-          { "id": 2, "score": 0.923, "payload": { "doc_id": 1001, ... } },
-          { "id": 1, "score": 0.891, "payload": { "doc_id": 1001, ... } }
-        ]
-      },
-      {
-        "id": "1002",
-        "hits": [
-          { "id": 5, "score": 0.815, "payload": { "doc_id": 1002, ... } }
-        ]
-      }
-    ]
-  },
-  "status": "ok",
-  "time": 0.003
-}
-```
-
----
-
-## 5. Cluster 管理
-
-### 5.1 获取 Collection 集群信息
-
-```
-GET https://saaschroma.ylrzcloud.com/collections/{collectionName}/cluster
-```
-
-**响应示例**:
-
-```json
-{
-  "result": {
-    "peer_id": 1752358415013712,
-    "shard_count": 1,
-    "local_shards": [
-      {
-        "shard_id": 0,
-        "points_count": 1,
-        "state": "Active"
-      }
-    ],
-    "remote_shards": [],
-    "shard_transfers": []
-  },
-  "status": "ok",
-  "time": 0.0002224
-}
-```
-
----
-
-## 附:APIPost 导入说明
-
-### 快速使用步骤
-
-1. 打开 APIPost
-2. 创建项目或文件夹(如 "Qdrant")
-3. 按上面的格式逐个添加请求:
-   - 方法:根据接口选择 GET/POST/PUT/DELETE/PATCH
-   - URL:`https://saaschroma.ylrzcloud.com/xxx`
-   - Headers:`Content-Type: application/json`
-   - Body:选择 JSON 格式并粘贴对应请求体
-4. 点击发送
-
-### 常见问题
-
-| 问题 | 原因 | 解决 |
-|------|------|------|
-| 返回 404 | Collection 不存在 | 先创建 Collection 或检查名称拼写 |
-| 返回 400 | 请求参数格式错误 | 检查 JSON 格式和必填字段 |
-| 搜索返回 score = 0 | 向量维度不匹配 | 确认 vector 长度 = 1024 |
-| 响应慢 | 数据量太大或未建索引 | 设置 `params.exact: false` 使用近似搜索 |
-
----
-
-> 本文档对应 Qdrant v1.17.1 REST API,完整官方文档请参考:
-> https://api.qdrant.tech/api-reference

+ 0 - 314
docs/SaaS改造方案.md

@@ -1,314 +0,0 @@
-# 互联网医院平台 SaaS 化改造方案
-
-## 一、现状总结
-
-### 1.1 已有能力(可直接复用)
-
-| 能力 | 位置 | 说明 |
-|------|------|------|
-| 租户表与 CRUD | `fs-service` / `tenant_info` | `TenantInfo` 含 dbUrl/dbAccount/dbPwd,支持按库隔离 |
-| 动态租户数据源 | `fs-framework` / `TenantDataSourceManager` | 按 tenantId 动态创建并缓存 Druid 数据源,注入 `DynamicDataSource` |
-| 管理端多租户登录 | `fs-admin` / `SysLoginController` + `SysLoginService` | 登录支持 `LoginBody.tenantCode`,校验后切租户库并设置 `LoginUser.tenantId` |
-| 请求级切库 + 租户配置 | `fs-framework` / `JwtAuthenticationTokenFilter` | 从 Token 取 `tenantId` → 设置数据源 + 从当前库查 `projectConfig` 写入 `TenantConfigContext` |
-| 租户配置存储 | 各租户库 `sys_config`(config_key=projectConfig) | 微信、支付、云存储等按租户隔离 |
-| Redis 租户前缀 | `fs-common` / `TenantKeyRedisSerializer` | Key 前缀 `tenantid:{tenantId}`,需确保取 tenantId 的上下文一致 |
-
-### 1.2 当前缺口(需改造)
-
-- **仅管理端走完整租户链路**:`fs-admin`、部分 `fs-company` 使用 framework 的 `JwtAuthenticationTokenFilter` + `DynamicDataSource`;**fs-user-app、fs-doctor-app、fs-store 等 C 端/应用端未接入**。
-- **C 端认证独立**:user-app 使用自有 `JwtUtils` + 请求头 `APPToken`,不经过 framework,**无 tenantId、无切库、无 TenantConfigContext**。
-- **租户识别方式未统一**:C 端用户如何归属到某租户(域名、请求头、登录时选租户等)未在代码中体现。
-- **数据隔离方式**:当前为「每租户独立库」,业务表无 `tenant_id` 字段;若未来要支持「共享库 + tenant_id」,需单独规划。
-
----
-
-## 二、改造目标
-
-1. **全模块 SaaS 化**:所有对外入口(admin、user-app、doctor-app、company-app、store、各 API 等)请求链路均带租户身份,按租户切库或使用租户配置。
-2. **租户识别统一**:管理端继续用「登录时 tenantCode」;C 端明确一种或多种方式(如请求头 `X-Tenant-Code`、二级域名、或登录接口选租户)。
-3. **Token 与上下文统一**:凡需多租户的应用,Token 或请求上下文中携带 `tenantId`,并统一用 framework 的过滤器做切库与 `TenantConfigContext` 注入。
-4. **配置与 Redis**:租户级配置继续用 `sys_config` + `TenantConfigContext`;Redis 使用处统一带租户前缀(`TenantKeyRedisSerializer` 依赖的 tenantId 需在请求链中可用)。
-
----
-
-## 三、整体架构(改造后)
-
-```
-                    ┌─────────────────────────────────────────────────────────┐
-                    │                    统一租户识别入口                        │
-                    │  (域名 / X-Tenant-Code / 登录参数 → tenantId)             │
-                    └─────────────────────────────────────────────────────────┘
-                                              │
-         ┌────────────────────────────────────┼────────────────────────────────────┐
-         ▼                                    ▼                                    ▼
-   fs-admin (已有)                    fs-user-app (需改)                    fs-doctor-app 等
-   - 登录带 tenantCode                - 接入 framework 过滤器               - 同 user-app
-   - JWT 含 tenantId                  - Token 含 tenantId                    - Token 含 tenantId
-   - 请求切库 + TenantConfigContext   - 请求切库 + TenantConfigContext       - 请求切库 + TenantConfigContext
-         │                                    │                                    │
-         └────────────────────────────────────┼────────────────────────────────────┘
-                                              ▼
-                    ┌─────────────────────────────────────────────────────────┐
-                    │  fs-framework:JwtAuthenticationTokenFilter             │
-                    │  - 解析 Token → LoginUser(tenantId)                      │
-                    │  - DynamicDataSourceContextHolder.set("tenant:"+tenantId)  │
-                    │  - TenantConfigContext.set(projectConfig)                │
-                    │  - ProjectConfig.loadTenantConfigsFromContext()          │
-                    └─────────────────────────────────────────────────────────┘
-                                              │
-                    ┌─────────────────────────┼─────────────────────────┐
-                    ▼                         ▼                         ▼
-              主库 (tenant_info 等)    租户库 A (业务数据)        租户库 B (业务数据)
-```
-
----
-
-## 四、主要改动点及改法
-
-### 4.1 租户识别策略(先定方案再落地)
-
-| 入口 | 推荐方式 | 说明 |
-|------|----------|------|
-| 管理端 fs-admin | 登录参数 `tenantCode`(已有) | 保持不变 |
-| C 端 fs-user-app / H5/小程序 | **方案 A**:登录接口增加 `tenantCode`,与账号一起校验后写进 Token;**方案 B**:请求头 `X-Tenant-Code`,网关/过滤器先解析再查主库得到 tenantId | 二选一或组合(如 B 做兜底) |
-| 企业端 fs-company-app | 同 C 端或与管理端一致 | 视是否同套登录 |
-| 各 API(fs-wx-api、fs-store 等) | 请求头或 Token 中的 tenantId/tenantCode | 与网关/过滤器约定 |
-
-**落地要点**:
-
-- 在 **fs-common** 或 **fs-framework** 中新增「租户解析」工具:根据请求头 `X-Tenant-Code` 或参数从主库查 `tenant_info` 得到 `tenantId`,并放入 ThreadLocal 或请求属性,供过滤器和业务使用。
-- 若 C 端登录选租户:在 **fs-user-app** 的登录接口增加 `tenantCode`,校验通过后调用与 admin 类似的「查租户 → switchTenant → 生成 Token 并设置 LoginUser.tenantId」逻辑(可抽到 framework 的 `SysLoginService` 或新服务中复用)。
-
----
-
-### 4.2 fs-user-app(C 端)接入多租户
-
-**目标**:C 端请求也按租户切库并使用 `TenantConfigContext`,与 admin 行为一致。
-
-#### 4.2.1 依赖与数据源
-
-- **pom.xml**:增加对 **fs-framework** 的依赖(若尚未引入),以便使用 `JwtAuthenticationTokenFilter`、`DynamicDataSource`、`TenantDataSourceManager`、`TenantConfigContext`。
-- **数据源**:改为使用 **fs-framework** 的 `DataSourceConfig`(即主库 + 可选 SOP/从库 + 租户动态数据源),或在本模块复制一份并保证 `DynamicDataSource` 注入 `TenantDataSourceManager` 使用的同一实例,这样 `TenantDataSourceManager` 动态加入的租户库才会生效。
-
-#### 4.2.2 认证与 Token 统一
-
-- **Token 生成**:C 端登录(微信/手机号/账号密码等)时,若需多租户,则:
-  - 入参增加 `tenantCode`(或从请求头 `X-Tenant-Code` 取);
-  - 查主库 `tenant_info` 校验租户状态;
-  - 调用 `TenantDataSourceManager.switchTenant(tenantInfo)` 切换到该租户库(便于本次登录逻辑里查该租户下的用户等);
-  - 构建 `LoginUser` 并 **setTenantId(tenantInfo.getId())**;
-  - 使用 **fs-framework** 的 `TokenService.createToken(loginUser)` 生成 JWT,这样 JWT 中会带 tenantId。
-- **请求头**:为与现有前端兼容,可保留 `APPToken` 作为 Token 传递方式;在 **fs-framework** 的 `TokenService.getLoginUser(request)` 中支持从 `APPToken` 解析(或 user-app 单独一个 Filter 先取 APPToken 再塞到 `Authorization`),保证后续 Filter 拿到的 `LoginUser` 含 tenantId。
-
-#### 4.2.3 启用 framework 的 JWT + 租户过滤器
-
-- **SecurityConfig**:在 **fs-user-app** 的 `SecurityConfig` 中,加入与 fs-admin 相同的 **JwtAuthenticationTokenFilter**(并注入 `TokenService`、`DynamicDataSource`、`SysConfigMapper`),保证每个请求:
-  - 解析 Token 得到 `LoginUser`(含 tenantId);
-  - 按 tenantId 设置 `DynamicDataSourceContextHolder` 和 `TenantConfigContext`;
-  - 在 finally 中清理上下文。
-- 若 user-app 当前用的是 **Interceptor**(如 `AuthorizationInterceptor`)+ 自有 `JwtUtils`,可逐步替换:先让 Filter 只做「解析 Token → 设置租户上下文」,业务仍用现有 getUserId();再逐步把 getUserId/getTenantId 统一为从 `SecurityUtils.getLoginUser()` 取。
-
-#### 4.2.4 基类与业务使用租户上下文
-
-- **AppBaseController**:增加 `getTenantId()`,从 `SecurityUtils.getLoginUser().getTenantId()` 或从当前请求的租户 ThreadLocal 取;现有 `getUserId()` 可改为优先从 `LoginUser` 取,便于与 framework 统一。
-- 所有需要「当前租户」的 Service/Mapper,在请求链中不再传 tenantId 参数,而是统一从 **TenantConfigContext** 或 **DynamicDataSourceContextHolder** 间接使用(当前库即租户库);若业务要写 Redis,确保使用的 RedisTemplate 已配置 **TenantKeyRedisSerializer**,且请求链中 tenantId 已设置。
-
-#### 4.2.5 小结:fs-user-app 改动清单
-
-| 序号 | 改动项 | 说明 |
-|------|--------|------|
-| 1 | 引入 fs-framework 依赖 | 使用其 DataSourceConfig、JwtAuthenticationTokenFilter、TokenService、TenantDataSourceManager |
-| 2 | 数据源改为 DynamicDataSource + 租户 | 与 framework 一致,保证租户库被动态注入 |
-| 3 | C 端登录入参/请求头带 tenantCode | 登录时解析租户并 setTenantId,Token 用 TokenService 生成 |
-| 4 | Security 中注册 JwtAuthenticationTokenFilter | 顺序在认证之前,确保每次请求设好数据源与 TenantConfigContext |
-| 5 | TokenService 支持从 APPToken 取 Token | 或 Filter 内兼容 APPToken 请求头 |
-| 6 | AppBaseController 提供 getTenantId() | 业务按需使用 |
-| 7 | Redis 使用 TenantKeyRedisSerializer | 若 user-app 有独立 RedisConfig,需与 common 一致,并保证 tenantId 在上下文可用 |
-
----
-
-### 4.3 fs-doctor-app / fs-company-app / fs-store 等
-
-- 思路与 **fs-user-app** 相同:**依赖 framework → 数据源统一为 DynamicDataSource + 租户 → 登录/请求带 tenantCode 或 tenantId → 使用 JwtAuthenticationTokenFilter → 业务从 SecurityUtils/TenantConfigContext 取租户**。
-- 若某模块目前连「用户登录」都没有(纯 API Key 或内部调用),则只需在网关或入口 Filter 中根据 **请求头 X-Tenant-Code**(或类似)解析出 tenantId,设置到 **DynamicDataSourceContextHolder** 和 **TenantConfigContext**,不涉及 JWT 用户身份。
-
----
-
-### 4.4 fs-framework 可做的增强(可选)
-
-| 增强项 | 说明 |
-|--------|------|
-| 租户解析器 | 提供 `TenantResolver` 接口:从 `HttpServletRequest`(域名/请求头/参数)解析出 `tenantCode` 或 `tenantId`,查主库得到 `TenantInfo`,供各模块 Filter 调用 |
-| TokenService 扩展 | `getLoginUser(request)` 支持从 `APPToken` 等请求头取 Token,避免各端重复写 |
-| 租户数据源生命周期 | 对 `TENANT_DS_CACHE` 做容量与过期策略,或增加「租户禁用时移除数据源」的联动 |
-| 健康检查 | 定时检测各租户数据源可用性,不可用时从缓存移除或告警 |
-
----
-
-### 4.5 配置与 Redis
-
-- **租户配置**:继续使用各租户库的 `sys_config.projectConfig` + `TenantConfigContext`,无需改表结构;若新增配置项,在 projectConfig 的 JSON 中扩展即可。
-- **Redis**:  
-  - 所有写 Redis 的地方使用已配置 **TenantKeyRedisSerializer** 的 RedisTemplate。  
-  - 确保在 Filter 链中,在调用 `TokenService.getLoginUser()` 并设置好 `LoginUser.tenantId` 之后,再执行业务逻辑(这样 TenantKeyRedisSerializer 从 ThreadLocal 或 SecurityContext 取到的 tenantId 才正确)。  
-  - 若某模块在 Filter 之前就访问 Redis,需避免用带租户前缀的 Key,或改为在 Filter 内先设好 tenantId 再放行。
-
----
-
-### 4.6 数据库与表结构(当前保持「按库隔离」)
-
-- 当前 **每租户独立库** 已满足多租户隔离,无需给业务表加 `tenant_id`。
-- 若未来要支持「共享库 + tenant_id」:
-  - 需在部分业务表增加 `tenant_id` 字段;
-  - 数据访问层统一加 tenant_id 条件(如 MyBatis 拦截器或 Mapper 中从 TenantConfigContext 取 tenantId 拼接);
-  - 与「按库隔离」二选一或分阶段迁移,此处不展开。
-
----
-
-## 五、实施步骤建议
-
-1. **确定租户识别策略**  
-   - 管理端:保持 tenantCode 登录。  
-   - C 端:确定「登录参数 tenantCode」和/或「请求头 X-Tenant-Code」的优先级与使用场景。
-
-2. **fs-framework 小增强**  
-   - 增加租户解析(如 TenantResolver),TokenService 支持 APPToken(若需要)。  
-   - 可选:租户数据源缓存策略与清理逻辑。
-
-3. **先改 fs-user-app**  
-   - 加 framework 依赖,切数据源与 Filter,登录写 tenantId 到 Token,Controller/Service 用 getTenantId() 与 TenantConfigContext。  
-   - 联调:同一套代码,用不同 tenantCode 登录或带不同 X-Tenant-Code,验证数据与配置按租户隔离。
-
-4. **再改 fs-doctor-app、fs-company-app、fs-store 等**  
-   - 按同一模式接入 framework 的租户链路。
-
-5. **各 API 模块(fs-wx-api、fs-ad-api 等)**  
-   - 若对外需区分租户,在入口 Filter 或网关中解析 tenantId 并设置数据源与 TenantConfigContext;内部调用若已带 Token,则与现有 Filter 一致。
-
-6. **回归与监控**  
-   - 全链路回归:管理端、C 端、各 API 在不同租户下数据与配置隔离正确。  
-   - 监控:租户数据源数量、连接池、Redis 键前缀与过期。
-
----
-
-## 六、涉及的主要文件/目录(参考)
-
-| 模块 | 主要改动文件/目录 |
-|------|-------------------|
-| fs-common | `LoginUser`/`LoginBody` 已有 tenantId/tenantCode;RedisConfig 确保 TenantKeyRedisSerializer 生效 |
-| fs-framework | `JwtAuthenticationTokenFilter`、`TenantDataSourceManager`、`DataSourceConfig`、`TokenService`;新增 TenantResolver(可选) |
-| fs-admin | 已支持多租户,仅需保证登录/Token 与文档一致,无需大改 |
-| fs-user-app | `pom.xml`、`DataSourceConfig`/数据源、`SecurityConfig`、登录 Controller/Service、`AppBaseController`、各业务 Controller 若需 tenantId 则用 getTenantId() |
-| fs-service | 租户与系统配置相关已存在;若 C 端登录要查主库 tenant_info,可复用 `TenantInfoService` |
-
----
-
-按上述方案实施后,全代码模块可统一为「SaaS 版」:各入口带租户身份,按租户切库与使用租户配置,为后续计费、限流、租户级功能开关等打好基础。
-
----
-
-## 七、定时任务模块 SaaS 化(fs-quartz 与 fs-qw-task)
-
-私有化部署时:每个客户独立库、独立服务器,定时任务跑在该客户自己的进程里,天然只操作本库。SaaS 化后:**一套进程、多租户多库**,定时任务需要「按租户执行」,即每个任务逻辑要对每个启用租户各执行一遍,且执行时数据源和租户配置为该租户的库与配置。
-
----
-
-### 7.1 fs-quartz(管理端可配置的定时任务)
-
-**现状**:
-
-- 由 **fs-admin** 引入,Quartz 使用一个 DataSource(私有化时即该客户唯一库)。
-- 任务配置表 **sys_job**、日志表 **sys_job_log** 在该库;启动时 `SysJobServiceImpl.init()` 从该库 `selectJobAll()` 加载任务并注册到 Quartz。
-- 触发时无 HTTP 请求,无 `LoginUser`,无租户上下文;`JobInvokeUtil.invokeMethod(sysJob)` 调用的 Bean 方法访问的也是「当前默认数据源」。
-
-**SaaS 下的矛盾**:  
-若仍用「一个 DataSource」且用主库,则读不到各租户的 sys_job;若用某一租户库,则只能跑该租户任务。因此需要**显式按租户调度 + 按租户执行**。
-
-#### 方案 A:租户任务分发器(推荐,表结构不变)
-
-- **思路**:Quartz 只保留**一个**定时任务(例如每分钟执行一次),该任务不直接执行业务,而是做「租户分发」:
-  1. 从**主库**查所有启用且未过期的租户列表(`tenant_info`)。
-  2. 对每个租户:  
-     - 使用 `TenantDataSourceManager.switchTenant(tenantInfo)` 切到该租户库;  
-     - 从**当前数据源**(该租户库)查 `sys_job` 中状态为「正常」且**本分钟应触发**的任务(或查全部,在内存里用 Cron 判断是否到点);  
-     - 对每个到点任务执行 `JobInvokeUtil.invokeMethod(sysJob)`(此时线程上下文已是该租户库);  
-     - 写 `sys_job_log` 时仍在当前租户库,无需改表。
-  3. 执行完毕后清理 `DynamicDataSourceContextHolder`、`TenantConfigContext`。
-- **优点**:各租户的 sys_job / sys_job_log 仍保留在各自库,表结构、管理端「定时任务」功能无需大改;只需新增一个「分发器」Job 和对应的 cron(如 `0 * * * * ?` 每分钟)。
-- **需要改的点**:
-  - **fs-admin**(或 fs-framework)中:  
-    - 增加一个 Bean,例如 `TenantJobDispatcherJob`,实现 Quartz Job,内部逻辑为上述 1~3。  
-    - 该 Job 需要在**启动时**就注册到 Scheduler(可写死在代码里,或从主库一张「系统级任务表」里读唯一一条「分发器」配置)。  
-    - 分发器从主库查租户列表需用主库数据源(查 tenant_info 时先切到 MASTER,再循环里再切到各租户)。  
-  - **fs-quartz**:  
-    - 若希望「任务配置仍在各租户库」,则 **SysJobServiceImpl.init()** 不再从当前库 selectJobAll 注册所有任务,改为只注册「租户分发器」这一条;  
-    - 或者保留 init() 但仅当检测到是「主库」时只注册分发器,具体可根据你们是否把 sys_job 放在主库一条而定。  
-  - **数据源**:fs-admin 的 Quartz 使用的 DataSource 需为 **DynamicDataSource**(主库 + 各租户动态库),且调度线程执行分发器前要能访问主库与 TenantDataSourceManager。
-
-#### 方案 B:sys_job 上迁主库并带 tenant_id
-
-- **思路**:把 sys_job(和可选 sys_job_log)迁到**主库**,表增加 **tenant_id** 字段;Quartz 从主库加载**全部**任务,JobKey 用 `tenantId + jobId` 保证唯一;执行时从 JobDataMap 取出 tenantId,先 `switchTenant` + 设置 TenantConfigContext,再执行 invokeMethod。
-- **优点**:一个 Quartz 调度器、一套触发逻辑,与现有 Quartz 模型一致。  
-- **缺点**:要迁移表结构、数据;管理端「定时任务」界面需改为按租户过滤(且操作的是主库表);若希望「租户只能看自己的任务」需在权限上控制。
-
-**建议**:优先采用 **方案 A**,对现有私有化表结构零侵入,仅增加一个分发器 Job 和按租户循环执行的逻辑。
-
----
-
-### 7.2 fs-qw-task(企微等固定节奏的定时任务)
-
-**现状**:
-
-- **独立 Spring Boot 应用**,依赖 fs-service,使用 **@Scheduled** 写死 cron(如每小时、每天凌晨等)。
-- 数据源为单 master + SOP,**无租户概念**;任务直接调 Mapper/Service,操作的是「当前连接的那一个库」。
-
-**SaaS 下目标**:  
-同一套代码、同一进程,但每个定时任务要对**每个启用租户**各执行一遍,且执行时该租户的库、企微配置等来自该租户的 `sys_config`(TenantConfigContext)。
-
-#### 改法:按租户遍历执行 + 租户上下文
-
-1. **引入多租户能力**  
-   - 依赖 **fs-framework**(或至少引入 **TenantDataSourceManager**、主库数据源、能查 `tenant_info` 的 Mapper)。  
-   - 数据源改为 **DynamicDataSource**(主库 + 租户动态库),与 fs-admin 一致;应用启动时只配主库,租户库由 TenantDataSourceManager 在运行时按需加入。
-
-2. **封装「按租户执行」工具**  
-   - 在 fs-framework 或 fs-qw-task 内提供工具类/Bean,例如:  
-     `TenantTaskRunner.runForEachTenant(Consumer<TenantInfo> action)`  
-   - 逻辑:从主库查所有 status=启用、未过期的租户列表 → for 每个租户:  
-     - `TenantDataSourceManager.switchTenant(tenantInfo)`;  
-     - 从该租户库查 `sys_config.projectConfig` 写入 `TenantConfigContext`(可复用现有 ProjectConfig.loadTenantConfigsFromContext 逻辑);  
-     - 执行 `action.accept(tenantInfo)`;  
-     - finally 中清理 `DynamicDataSourceContextHolder`、`TenantConfigContext`。  
-   - 若某租户执行抛错,可记录日志并继续下一个租户,避免一个租户异常导致其余不执行。
-
-3. **改造每个 @Scheduled 方法**  
-   - 将原有「无租户」的一坨逻辑封装成一个方法或 Lambda。  
-   - 在 @Scheduled 方法里只写一行:  
-     `tenantTaskRunner.runForEachTenant(tenantInfo -> { 原有逻辑 });`  
-   - 例如:  
-     - `qwCheckSopRuleTime()` → `tenantTaskRunner.runForEachTenant(t -> qwSopService.checkSopRuleTime());`  
-     - `addTag()` → `tenantTaskRunner.runForEachTenant(t -> qwSopTagService.addTag());`  
-   - 这样原有业务代码(Mapper、Service)无需改,只要在「有租户上下文」的线程里执行即可。
-
-4. **Redis**  
-   - 若任务里有用到 Redis,需保证 RedisTemplate 使用 **TenantKeyRedisSerializer**,且执行时 ThreadLocal 或上下文里能拿到当前 tenantId(在 runForEachTenant 内 set 一次即可)。
-
-**小结**:fs-qw-task 不改任务业务逻辑,只加一层「按租户执行」的壳;数据源与租户配置与 fs-admin 对齐即可。
-
----
-
-### 7.3 实施顺序建议
-
-1. **先做 fs-qw-task**:依赖 framework、切 DynamicDataSource、实现 TenantTaskRunner、逐个 @Scheduled 包一层 runForEachTenant,联调多租户数据与配置隔离。  
-2. **再做 fs-quartz**:在 fs-admin 中实现「租户任务分发器」Job,Quartz 只调度该 Job;分发器内按租户切库并执行各租户 sys_job 中到点任务;视需要调整 init() 与任务管理界面(若仍用各租户库 sys_job,界面按当前登录租户查即可)。
-
----
-
-### 7.4 涉及的主要文件/目录(定时任务)
-
-| 模块 | 改动要点 |
-|------|----------|
-| **fs-framework** | 可选:提供 `TenantTaskRunner`(或放在 fs-qw-task 内),依赖 TenantDataSourceManager、TenantInfoService/Mapper、TenantConfigContext。 |
-| **fs-admin** | Quartz 使用 DynamicDataSource;新增 `TenantJobDispatcherJob`;init() 只注册分发器或按策略注册。 |
-| **fs-quartz** | 若采用方案 A,可不改表与 Mapper,仅被分发器通过 JobInvokeUtil 调用;若采用方案 B,需 sys_job 增加 tenant_id 及迁移脚本。 |
-| **fs-qw-task** | 依赖 fs-framework;DataSource 改为 DynamicDataSource + 租户;新增 TenantTaskRunner;各 @Scheduled 改为 runForEachTenant(原有逻辑)。 |

+ 0 - 151
docs/SaaS计费模块产品文档-业务简版.md

@@ -1,151 +0,0 @@
-# SaaS计费模块产品文档(业务简版)
-
-## 1. 这套模块解决什么问题
-
-一句话:  
-平台可以统一配置收费规则,系统按租户实际使用自动计费,租户可随时查看自己的费用明细。
-
----
-
-## 2. 角色分工
-
-## 2.1 平台总账号
-
-可以做:
-
-1. 配置计费方案(单价、阶梯、收费项);
-2. 绑定租户使用哪个方案;
-3. 查看所有租户费用明细;
-4. 生成账单。
-
-## 2.2 租户账号
-
-可以做:
-
-1. 查看自己的费用明细;
-2. 查看钱包余额;
-3. 发起充值(按授权开放)。
-
----
-
-## 3. 计费项说明(业务口径)
-
-当前支持:
-
-1. 流量计费(FLOW)
-2. 通话计费(CALL_OUT / CALL_IN)
-3. AI 外呼附加计费(AI_CALL)
-4. SOP Token 计费(TOKEN_SOP)
-5. AI 回复 Token 计费(TOKEN_AI_REPLY)
-6. 加微计费(ADD_WECHAT)
-7. 开户费(OPEN_ACCOUNT_AI / OPEN_ACCOUNT_NON_AI)
-
----
-
-## 4. 核心计费规则
-
-## 4.1 预付费 vs 后付费
-
-- 预付费:计费后立即从钱包扣款;
-- 后付费:先记费用,后续按账单结算。
-
-## 4.2 流量阶梯
-
-- 预付费租户按累计预存金额匹配阶梯单价;
-- 后付费租户按后付费单价计费。
-
-## 4.3 通话规则
-
-- 外呼/呼入按分钟计费;
-- 不足 1 分钟按 1 分钟计算;
-- 若为 AI 外呼,则在通话费基础上增加 AI 附加费用。
-
-## 4.4 Token 规则
-
-- 例如配置“10万 Token = 1元”;
-- 计费时按 token 用量折算金额。
-
-## 4.5 幂等规则
-
-- 同一个事件ID只计费一次;
-- 重复上报不会重复扣费。
-
----
-
-## 5. 业务流程(简版)
-
-## 5.1 平台配置流程
-
-1. 创建方案;
-2. 录入收费项;
-3. 录入流量阶梯;
-4. 发布方案;
-5. 绑定到租户。
-
-## 5.2 日常计费流程
-
-1. 业务系统上报“用量事件”;
-2. 系统按租户方案计算金额;
-3. 写入费用明细;
-4. 预付费则自动扣钱包。
-
-## 5.3 出账流程
-
-1. 按时间区间汇总未出账明细;
-2. 生成账单;
-3. 明细标记已入账。
-
----
-
-## 6. 页面说明
-
-## 6.1 总账号页面
-
-- 页面:费用明细(总账号)
-- 功能:查看全租户明细,可按租户筛选。
-
-## 6.2 租户页面
-
-- 页面:费用明细(我的)
-- 功能:仅查看本租户费用明细。
-
----
-
-## 7. 数据安全口径
-
-1. 租户页面不允许手工指定租户ID;
-2. 系统按登录身份自动识别所属租户;
-3. 总账号和租户账号权限分离,避免越权查看。
-
----
-
-## 8. 上线验收清单(业务侧)
-
-1. 平台可完成方案配置与发布;
-2. 租户绑定后可正常计费;
-3. 同一事件重复上报不重复计费;
-4. 预付费租户会正确扣减余额;
-5. 总账号可查看全部租户明细;
-6. 租户仅能查看自己明细;
-7. 账单可按区间正常生成。
-
----
-
-## 9. 常见问题(FAQ)
-
-## Q1:为什么租户看不到别的租户数据?
-
-因为系统按登录身份自动绑定租户,接口层不接受手工传入租户ID。
-
-## Q2:重复上报会重复扣费吗?
-
-不会。事件ID幂等,重复事件会被识别并忽略。
-
-## Q3:后付费租户会立即扣钱包吗?
-
-不会。后付费只记明细,后续通过账单结算。
-
-## Q4:价格调整会影响历史数据吗?
-
-不会。历史明细按发生时绑定的方案版本计算并固化。
-

+ 0 - 488
docs/SaaS计费模块产品文档.md

@@ -1,488 +0,0 @@
-# SaaS计费模块产品文档
-
-## 1. 文档信息
-
-- 模块名称:SaaS 多租户计费模块
-- 适用系统:`ylrz_saas_his_scrm`
-- 当前状态:已完成核心计费闭环改造(方案、绑定、钱包、事件计费、明细、账单)
-- 文档用途:产品、研发、测试、运营统一对齐
-
----
-
-## 2. 产品目标
-
-### 2.1 目标
-
-构建一套可在 SaaS 场景下稳定运行的统一计费能力,支持:
-
-1. 平台统一维护计费方案;
-2. 租户按绑定方案自动计费;
-3. 支持预付费/后付费;
-4. 全链路可追溯(事件 -> 明细 -> 钱包流水 -> 账单)。
-
-### 2.2 业务价值
-
-- 支撑商业化收费与多租户精细化运营;
-- 平台可审计全部租户费用情况;
-- 租户可自助查看自身费用明细,降低客服压力。
-
----
-
-## 3. 角色与权限模型
-
-### 3.1 平台总账号(Admin)
-
-- 配置并发布计费方案;
-- 绑定租户计费方案;
-- 查看全部租户明细(可按租户筛选);
-- 生成账单。
-
-权限点:
-
-- `fee:billing:admin:list`
-
-### 3.2 租户账号(Tenant)
-
-- 查看“我的费用明细”;
-- 查询钱包、发起充值(按产品授权控制)。
-
-权限点:
-
-- `fee:billing:tenant:list`
-
----
-
-## 4. 收费项设计
-
-当前实现的收费项如下:
-
-1. `FLOW`:流量计费  
-   - 预付费:按阶梯价格(基于累计预存金额);
-   - 后付费:按 `FLOW_POSTPAID` 单价。
-2. `CALL`:通话计费  
-   - 子类型:`CALL_OUT`、`CALL_IN`;
-   - 不满一分钟按一分钟;
-   - AI 外呼在通话费基础上叠加 `AI_CALL`。
-3. `TOKEN_SOP`:SOP Token 计费。
-4. `TOKEN_AI_REPLY`:AI 回复 Token 计费。
-5. `ADD_WECHAT`:按加微次数计费。
-6. `OPEN_ACCOUNT`:开户费  
-   - AI 租户:`OPEN_ACCOUNT_AI`;
-   - 非 AI 租户:`OPEN_ACCOUNT_NON_AI`。
-
----
-
-## 5. 核心业务规则
-
-## 5.1 方案规则
-
-1. 方案唯一键:`planCode + version`;
-2. 仅 `PUBLISHED` 状态方案可用于计费;
-3. 支持多版本并行,租户绑定到具体版本。
-
-## 5.2 租户绑定规则
-
-租户绑定项:
-
-- `tenantType`(AI / NON_AI)
-- `billingMode`(PREPAID / POSTPAID)
-- `planCode`
-- `planVersion`
-
-未绑定方案时禁止执行计费。
-
-## 5.3 幂等规则
-
-`usage_event.event_id` 作为幂等键:  
-重复事件上报不重复计费。
-
-## 5.4 钱包规则
-
-- 预付费:实时扣减余额并写流水;
-- 后付费:仅记录明细,后续账单结算。
-
-## 5.5 账单规则
-
-1. 仅聚合未入账明细(`statement_id is null`);
-2. 账单项按 `event_type` 聚合;
-3. 生成后回填明细 `statement_id`,避免重复出账。
-
----
-
-## 6. 端到端流程
-
-## 6.1 方案配置流程(平台)
-
-1. 创建方案草稿;
-2. 配置收费项;
-3. 配置流量阶梯;
-4. 发布方案;
-5. 绑定租户。
-
-## 6.2 事件计费流程(系统)
-
-1. 业务侧上报 `usage_event`;
-2. 幂等校验(`eventId`);
-3. 加载租户绑定与方案配置;
-4. 计算金额并写 `billing_detail`;
-5. 若预付费则扣钱包并写 `tenant_wallet_txn`;
-6. 返回计费结果。
-
-## 6.3 对账出账流程(平台)
-
-1. 查询明细;
-2. 指定时间区间生成账单;
-3. 账单聚合 + 明细挂账;
-4. 进入后续财务流程(支付/核销可扩展)。
-
----
-
-## 7. 页面设计(前端)
-
-已按“两页面模型”实现:
-
-1. 总账号页:`saas/billingAdmin/index`  
-   - 查看所有租户费用明细;
-   - 支持按租户筛选。
-2. 租户页:`saas/billingTenant/index`  
-   - 仅查看当前登录租户的费用明细;
-   - 不允许手工传 `tenantId`。
-
----
-
-## 8. 接口清单与示例
-
-以下示例统一返回结构基于项目常见 `R`:
-
-```json
-{
-  "code": 200,
-  "msg": "操作成功",
-  "data": {},
-  "rows": []
-}
-```
-
-## 8.1 方案管理
-
-### 8.1.1 创建方案
-
-- `POST /api/fee/plan/create`
-
-请求示例:
-
-```json
-{
-  "planCode": "STANDARD",
-  "planName": "标准方案",
-  "version": 1,
-  "remark": "默认标准方案"
-}
-```
-
-响应示例:
-
-```json
-{
-  "code": 200,
-  "msg": "创建成功"
-}
-```
-
-### 8.1.2 保存收费项
-
-- `POST /api/fee/plan/item/save`
-
-请求示例:
-
-```json
-{
-  "planCode": "STANDARD",
-  "version": 1,
-  "items": [
-    {
-      "itemCode": "FLOW_POSTPAID",
-      "unit": "KB",
-      "unitPrice": 0.2,
-      "tokenUnit": 100000,
-      "minChargeUnit": 1,
-      "enabled": 1
-    },
-    {
-      "itemCode": "CALL_OUT",
-      "unit": "MIN",
-      "unitPrice": 0.3,
-      "enabled": 1
-    }
-  ]
-}
-```
-
-### 8.1.3 保存流量阶梯
-
-- `POST /api/fee/plan/flow-tier/save`
-
-请求示例:
-
-```json
-{
-  "planCode": "STANDARD",
-  "version": 1,
-  "tiers": [
-    {
-      "minPrepayAmount": 0,
-      "maxPrepayAmount": 100000,
-      "unitPrice": 0.1,
-      "sortNo": 1
-    },
-    {
-      "minPrepayAmount": 100000,
-      "maxPrepayAmount": 200000,
-      "unitPrice": 0.08,
-      "sortNo": 2
-    }
-  ]
-}
-```
-
-### 8.1.4 发布方案
-
-- `POST /api/fee/plan/publish?planCode=STANDARD&version=1`
-
----
-
-## 8.2 租户绑定
-
-### 8.2.1 绑定方案
-
-- `POST /api/fee/tenant/bind-plan`
-
-请求示例:
-
-```json
-{
-  "tenantId": 1001,
-  "tenantType": "NON_AI",
-  "billingMode": "PREPAID",
-  "planCode": "STANDARD",
-  "planVersion": 1
-}
-```
-
-### 8.2.2 切换计费模式
-
-- `POST /api/fee/tenant/change-billing-mode`
-
-请求示例:
-
-```json
-{
-  "tenantId": 1001,
-  "billingMode": "POSTPAID"
-}
-```
-
-### 8.2.3 切换租户类型
-
-- `POST /api/fee/tenant/change-type`
-
-请求示例:
-
-```json
-{
-  "tenantId": 1001,
-  "tenantType": "AI"
-}
-```
-
----
-
-## 8.3 钱包
-
-### 8.3.1 查询钱包
-
-- `GET /api/fee/wallet/{tenantId}`
-
-响应示例:
-
-```json
-{
-  "code": 200,
-  "data": {
-    "tenantId": 1001,
-    "balanceAmount": 12345.67,
-    "totalRecharge": 50000,
-    "totalCost": 37654.33
-  }
-}
-```
-
-### 8.3.2 充值
-
-- `POST /api/fee/wallet/recharge`
-
-请求示例:
-
-```json
-{
-  "tenantId": 1001,
-  "amount": 10000,
-  "bizNo": "RC202604210001",
-  "remark": "线下转账充值"
-}
-```
-
----
-
-## 8.4 用量上报
-
-### 8.4.1 上报并计费
-
-- `POST /api/fee/usage/report`
-
-请求示例:
-
-```json
-{
-  "eventId": "EVT_20260421_0001",
-  "tenantId": 1001,
-  "eventType": "CALL",
-  "subType": "CALL_OUT",
-  "bizId": "ORDER_001",
-  "usageValue": 125,
-  "usageUnit": "SECOND",
-  "occurredAt": "2026-04-21 15:30:00",
-  "extJson": {
-    "isAiCall": true
-  }
-}
-```
-
-响应示例:
-
-```json
-{
-  "code": 200,
-  "data": {
-    "eventId": "EVT_20260421_0001",
-    "charged": true,
-    "amount": 2.4,
-    "message": "计费成功"
-  }
-}
-```
-
----
-
-## 8.5 明细与账单
-
-### 8.5.1 平台查询明细(可看全租户)
-
-- `GET /api/fee/billing/detail/list`
-- 参数:`tenantId`(可选)
-
-示例:
-
-- `GET /api/fee/billing/detail/list`(全部)
-- `GET /api/fee/billing/detail/list?tenantId=1001`(指定租户)
-
-### 8.5.2 租户查询我的明细
-
-- `GET /api/fee/billing/detail/my`
-- 不接收 tenantId,由后端从登录态获取
-
-### 8.5.3 生成账单
-
-- `POST /api/fee/statement/generate`
-- 参数:`tenantId`、`periodType`、`periodStart`、`periodEnd`
-
-示例:
-
-`POST /api/fee/statement/generate?tenantId=1001&periodType=MONTH&periodStart=2026-04-01%2000:00:00&periodEnd=2026-04-30%2023:59:59`
-
-响应示例:
-
-```json
-{
-  "code": 200,
-  "data": {
-    "statementId": 88,
-    "statementNo": "ST1713693258123",
-    "periodType": "MONTH",
-    "periodStart": "2026-04-01 00:00:00",
-    "periodEnd": "2026-04-30 23:59:59",
-    "totalAmount": 1299.35
-  }
-}
-```
-
----
-
-## 9. 数据模型
-
-## 9.1 方案
-
-- `fee_plan`
-- `fee_plan_item`
-- `fee_plan_flow_tier`
-
-## 9.2 租户绑定
-
-- `tenant_info`(新增计费相关字段)
-  - `tenant_type`
-  - `billing_mode`
-  - `fee_plan_code`
-  - `fee_plan_version`
-
-## 9.3 钱包
-
-- `tenant_wallet`
-- `tenant_wallet_txn`
-
-## 9.4 计费主链路
-
-- `usage_event`
-- `billing_detail`
-- `billing_statement`
-- `billing_statement_item`
-
----
-
-## 10. 安全与数据隔离
-
-1. 明细查询按权限点分流;
-2. 租户端明细接口不接受 `tenantId`;
-3. 统一通过登录态解析租户 ID;
-4. 防止前端参数篡改导致跨租户越权查询。
-
----
-
-## 11. 监控与审计建议
-
-1. 监控 `usage_event` 入库量与重复率;
-2. 监控钱包扣费失败告警;
-3. 监控账单生成耗时和失败率;
-4. 保留事件、明细、流水的关联查询能力,支持财务审计。
-
----
-
-## 12. 验收标准(UAT)
-
-1. 方案创建/配置/发布可用;
-2. 租户绑定后可正常计费;
-3. 重复事件不会重复扣费;
-4. 预付费会扣钱包并生成流水;
-5. 总账号可看全租户明细;
-6. 租户仅能看本人租户明细;
-7. 账单生成后明细正确挂账。
-
----
-
-## 13. 版本演进建议
-
-1. 增加账单支付、核销、坏账流程;
-2. 增加账单列表与账单详情 API;
-3. 增加按天/月统计报表与导出;
-4. 用量上报支持 MQ 异步削峰;
-5. 引入欠费阈值与停服策略。
-

+ 0 - 152
docs/user-app更改.md

@@ -1,152 +0,0 @@
-[17 tools called]
-
-先修改 user-app 的数据源 key,然后新增租户数据源管理类和租户切换过滤器,最后编译+写文档。
-
-[22 tools called]
-
-下面是这次对 C 端 `fs-user-app` 的 SaaS 改造情况、用法和说明。
-
----
-
-### 一、这次具体改了什么(代码层面)
-
-#### 1. 数据源 key 统一为字符串(MASTER/SLAVE)
-
-- **文件**:`com.fs.framework.config.DataSourceConfig`
-- **改动**:将原来用枚举作为 key 的写法统一为字符串 key:
-  ```java
-  targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
-  targetDataSources.put(DataSourceType.SLAVE.name(), slaveDataSource);
-  
-  ```
-- **原因**:`DynamicDataSourceContextHolder.setDataSourceType()` 传的是字符串(如 `"MASTER"`),以前 `targetDataSources` 用的是 `DataSourceType.MASTER`(枚举),两者不相等,后面做动态切库会出问题,所以先把 key 统一成字符串。
-
-#### 2. 新增租户数据源管理类 `TenantDataSourceManager`
-
-- **文件**:`com.fs.framework.datasource.TenantDataSourceManager`
-- **作用**:
-    - 根据主库里的 `TenantInfo`(`tenant_info` 表)动态创建租户库的数据源(`DruidDataSource`);
-    - 把新数据源挂到当前 `DynamicDataSource` 的 `resolvedDataSources` 上;
-    - 调用 `DynamicDataSourceContextHolder.setDataSourceType("tenant:{tenantId}")` 把当前线程切到对应租户库;
-    - 提供 `clear()` 方法在请求结束时清理 ThreadLocal,避免线程复用串库。
-- **实现要点**:
-    - 内部用 `TENANT_DS_CACHE` 缓存租户数据源,避免重复创建连接池;
-    - 用反射访问 `AbstractRoutingDataSource.resolvedDataSources`,运行时追加数据源;
-    - 租户 key 统一为 `tenant:{id}`,和 admin/company 一致;
-    - 注释里已经详细解释了用途和注意点。
-
-#### 3. 新增租户切换过滤器 `AppTenantSwitchFilter`
-
-- **文件**:`com.fs.framework.filter.AppTenantSwitchFilter`
-- **注解**:`@Component`、`@Order(5)`,继承 `OncePerRequestFilter`。
-- **入口约定**:
-    - 使用请求头 **`X-Tenant-Code`** 作为 C 端的租户标识(和 admin 的 `tenantCode` 含义一致)。
-    - 前端 app / H5 / 小程序只要在请求头上带上这个租户编码,本次改造就会按该租户切库并加载租户配置。
-- **过滤逻辑(按请求)**:
-
-    1. 从请求头读取 `X-Tenant-Code`:
-        - 为空:**直接放行**,不做任何租户切换,兼容老逻辑(单库)。
-    2. 切到主库 MASTER:
-        - `DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());`
-    3. 用 `TenantInfoService` 在主库根据 `tenantCode` 查 `tenant_info`:
-        - 找不到 / 状态不为启用 / 已过期:记录日志,**放行但不切库**(保持单库行为)。
-    4. 对有效租户调用 `tenantDataSourceManager.switchTenant(tenant)` 切到该租户库:
-        - 如无数据源则创建一个 `DruidDataSource` 并挂到 `DynamicDataSource`;
-        - 当前线程的数据源 key 变为 `tenant:{id}`。
-    5. 在租户库中查询租户级项目配置:
-        - `SysConfig cfg = sysConfigMapper.selectConfigByConfigKey("projectConfig");`
-        - 若有值:`TenantConfigContext.set(JSONObject.parseObject(cfg.getConfigValue()));`
-        - 然后调用 `ProjectConfig.loadTenantConfigsFromContext()`,让 Wx/支付等配置指向当前租户。
-    6. 调用 `filterChain.doFilter(request, response)`,后面的 Controller/Service/Mapper 就跑在该租户库上,并使用该租户的项目配置。
-    7. `finally` 中清理上下文:
-        - `ProjectConfig.clearTenantConfigs();`
-        - `TenantConfigContext.clear();`
-        - `tenantDataSourceManager.clear();`(内部清除数据源标记)。
-
-- **兼容性**:
-    - **不带 `X-Tenant-Code`**:一切照旧(单库)。
-    - **错误/禁用/过期租户**:仅打日志,不中断请求,退回单库行为(你可以后面再根据需要调整为直接返回错误)。
-
----
-
-### 二、C 端前端需要怎么配合(非常关键)
-
-1. **每个 C 端请求都带上 `X-Tenant-Code`**:
-    - header 名:`X-Tenant-Code`;
-    - 值:你的租户编码(主库 `tenant_info.tenant_code`)。
-2. 包括以下类型的请求:
-    - 登录接口(`/app/app/login`、`/store/app/app/login` 等);
-    - 用户信息、课程、订单、SOP 等所有业务接口;
-    - 登出(如有)等。
-3. 租户编码获取方式(你可以按业务决定):
-    - 用户进入 app 之前选择医院/企业;
-    - 二级域名解析(如 `tenantA.xxx.com` → `tenantCode=tenantA`),前端启动时就把这个值带在 header 里。
-
-**只要 header 带得上,多租户这层就自动生效。**
-
----
-
-### 三、现有登录 / Token / Redis 行为说明
-
-- user-app 目前的登录逻辑(`AppLoginController` / `AppLoginScrmController`)**没有改**:
-    - 还是用 `JwtUtils.generateToken(userId)` 生成 `APPToken`;
-    - 还是把 token 存到 Redis 的 `userToken:{userId}`;
-    - 鉴权还是用 header 里的 `APPToken` 解出 `userId`。
-- 这次的 SaaS 改造:
-    - **不改 token 结构**,不强行在 token 里塞 `tenantId`;
-    - **按请求头的 `X-Tenant-Code` 切库**,把“用户归属哪个租户”的责任交给前端来决定;
-    - Redis 这块暂时也不按租户做前缀,保证旧逻辑无感知(如果后面你要对 C 端 Redis 也做租户隔离,可以再单独一轮改造)。
-
----
-
-### 四、如何自测 user-app C 端的多租户
-
-你可以用 Postman 或直接在 app 上做几组简单验证:
-
-1. **多租户切库验证**
-    - 在主库的 `tenant_info` 中配置两个租户 A / B,对应不同业务库,两个库中插入不同的测试数据;
-    - 调用同一个 C 端接口(比如课程列表),分别带:
-        - `X-Tenant-Code: A`
-        - `X-Tenant-Code: B`
-    - 确认两个请求看到的是各自库中的数据(比如医院名/课程名不同)。
-
-2. **租户配置隔离验证**
-    - 在租户 A/B 的各自库的 `sys_config.projectConfig` 里,配置不同的微信 / 支付参数(可以改一个明显的字段);
-    - 调用依赖这些配置的接口(如微信登录、支付相关接口),看是否按不同租户配置生效。
-
-3. **兼容性验证**
-    - 不带 `X-Tenant-Code` 调接口,确保行为与改造前一致(不报错,不异常,仍然能正常访问)。
-
-4. **异常租户验证**
-    - 用一个不存在的 `X-Tenant-Code` 请求,观察日志里有告警(租户不存在 / 禁用 / 过期),同时请求不会抛异常,只是退回用主库。
-
----
-
-### 五、user-app 模块改造说明文档
-
-我已经帮你在项目里生成了一个专门的文档:
-
-- **路径**:`docs/user-app模块SaaS改造说明.md`
-
-里面详细写了:
-
-- 本次改造的目标、原则;
-- DataSourceConfig 的改动;
-- `TenantDataSourceManager` 和 `AppTenantSwitchFilter` 的设计与实现细节;
-- 前端如何带 `X-Tenant-Code`;
-- 推荐的自测场景。
-
-你可以直接把这个文档发给前端和其他后端同事,对接起来会更顺畅。
-
----
-
-### 六、总结(给你一个操作要点版)
-
-- **后端**:
-    - 已经支持通过 `X-Tenant-Code` 切换到对应租户库,并加载该租户的 `projectConfig`。
-    - 老逻辑兼容,不带头还是单库。
-- **前端需要做的一件事**:
-    - 所有 user-app 请求(含登录)统一加上请求头:
-        - `X-Tenant-Code: <对应的租户编码>`。
-
-如果你希望下一步把 C 端的 Token 和 Redis 也做成像 admin/company 那种“token 里带 tenantId、Redis key 按租户隔离”的模式,我也可以再帮你设计一套不影响现有用户的渐进改法。

+ 0 - 83
docs/方案.md

@@ -1,83 +0,0 @@
-## 现状结论
-
-- **管理端(fs-admin)** 已具备多租户:`tenant_info`、按库隔离、登录带 `tenantCode`、JWT 带 `tenantId`、请求里切库并注入 `TenantConfigContext`。
-- **C 端(fs-user-app 等)** 还未接多租户:用自有 `JwtUtils` + `APPToken`,没有 `tenantId`、不切库、也不用租户配置。
-
----
-
-## 改造目标(SaaS 版要达成什么)
-
-1. 所有入口(admin、user-app、doctor-app、company、store、各 API)请求都带**租户身份**,按租户切库或使用租户配置。
-2. 租户识别方式统一(管理端继续用登录 `tenantCode`,C 端用登录参数和/或请求头如 `X-Tenant-Code`)。
-3. Token/请求上下文中统一带 `tenantId`,用 framework 的过滤器做切库和 `TenantConfigContext` 注入。
-
----
-
-## 主要要改的地方与改法
-
-| 类别 | 改什么 | 怎么改 |
-|------|--------|--------|
-| **租户识别** | C 端如何知道是哪个租户 | 方案 A:登录接口增加 `tenantCode`,写入 Token;方案 B:请求头 `X-Tenant-Code`,在 Filter 里解析出 tenantId。可 A+B 组合。 |
-| **fs-user-app** | 接入多租户链路 | 1)依赖 fs-framework;2)数据源改为用 framework 的 DynamicDataSource(含租户库);3)登录时查主库 `tenant_info`、切租户、`LoginUser.setTenantId()`,用 `TokenService.createToken()` 生成 JWT;4)在 Security 里加入 `JwtAuthenticationTokenFilter`,保证每次请求按 tenantId 切库并设置 `TenantConfigContext`;5)`TokenService.getLoginUser()` 支持从 `APPToken` 取 Token;6)`AppBaseController` 增加 `getTenantId()`。 |
-| **fs-doctor-app / company / store 等** | 与 user-app 一致支持多租户 | 同样:依赖 framework、用 DynamicDataSource、登录/请求带 tenantCode 或 tenantId、使用 `JwtAuthenticationTokenFilter`、业务从 `SecurityUtils`/`TenantConfigContext` 取租户。 |
-| **fs-framework(可选增强)** | 租户解析与 Token 兼容 | 新增 `TenantResolver`(从请求头/域名解析 tenantCode→tenantId);`TokenService` 支持从 `APPToken` 取 Token。 |
-| **Redis** | 多租户下 Key 隔离 | 使用已配置 `TenantKeyRedisSerializer` 的 RedisTemplate,并保证在 Filter 里先设置好 `LoginUser.tenantId` 再执行业务。 |
-| **数据库** | 保持现有隔离方式 | 继续「每租户一库」,无需给业务表加 `tenant_id`;若以后要做共享库再单独规划。 |
-
----
-
-## 建议实施顺序
-
-1. 定好 C 端租户识别策略(登录参数 vs 请求头)。
-2. 在 fs-framework 做小增强:租户解析(可选)、Token 支持 APPToken。
-3. **先改 fs-user-app**:接 framework、改数据源、登录写 tenantId、加 Filter、基类加 getTenantId(),联调不同 tenantCode 验证隔离。
-4. 再按同一模式改 fs-doctor-app、fs-company-app、fs-store 等。
-5. 各 API 模块在入口 Filter 或网关上解析 tenantId 并设置数据源与 `TenantConfigContext`。
-
-完整步骤、架构图和涉及文件清单都在 **`docs/SaaS改造方案.md`** 里,可按该文档逐步落地。如果你希望从某一块先动手(例如先只改 user-app 或先做 TenantResolver),可以说一下,我可以按那一块给出更具体的改法或示例代码。
-
-
-查看 fs-quartz 和 fs-qw-task 的当前实现,以便给出 SaaS 下定时任务的处理方案。
-
-
-## 一、问题本质
-
-- **私有化**:每个客户独立库、独立服务器,定时任务只连本客户库,没有多租户问题。
-- **SaaS**:一套进程、多租户多库,定时任务必须「按租户执行」——同一任务逻辑要对**每个启用租户**各跑一遍,且每次跑的是该租户的库和配置。
-
----
-
-## 二、fs-quartz(管理端可配置的定时任务)
-
-- **现状**:任务配置在 `sys_job`(当前是单库),Quartz 用单一 DataSource 加载并触发,执行时没有租户上下文。
-- **推荐做法(方案 A:租户任务分发器)**  
-  - Quartz 只注册**一个**定时任务(例如每分钟一次),不直接执行业务,只做「按租户分发」:  
-    1. 从**主库**查所有启用租户;  
-    2. 对每个租户:`TenantDataSourceManager.switchTenant(tenantInfo)` 切到该租户库 → 从**该租户库**的 `sys_job` 里查出本分钟该触发的任务 → 对每个任务执行 `JobInvokeUtil.invokeMethod(sysJob)`;  
-    3. 执行完后清理数据源和租户上下文。  
-  - 这样 **sys_job / sys_job_log 仍保留在各租户库**,表结构不用改,只是多了一个「分发器」Job。  
-- **需要改的地方**:  
-  - fs-admin:Quartz 使用 **DynamicDataSource**(主库 + 租户动态库);新增一个 Bean(如 `TenantJobDispatcherJob`),实现上述 1~3,并在启动时只把该分发器注册到 Scheduler。  
-  - fs-quartz:`SysJobServiceImpl.init()` 改为只注册这一条「分发器」任务,不再从当前库 `selectJobAll` 注册所有任务(具体是否保留 init 可根据你是否把 sys_job 迁主库而定)。
-
----
-
-## 三、fs-qw-task(企微等 @Scheduled 定时任务)
-
-- **现状**:独立应用,用 **@Scheduled** 写死 cron,连的是单 master + SOP,没有租户。
-- **做法:按租户遍历 + 租户上下文**  
-  1. **接入多租户**:引入 fs-framework,数据源改为 **DynamicDataSource**(主库 + 租户动态库),与 fs-admin 一致。  
-  2. **封装执行器**:提供 `TenantTaskRunner.runForEachTenant(Consumer<TenantInfo> action)`:从主库查启用租户 → 对每个租户切库、设置 `TenantConfigContext` → 执行 `action` → 清理上下文。  
-  3. **改造每个 @Scheduled**:原来整段任务逻辑包一层,例如:  
-     - `tenantTaskRunner.runForEachTenant(t -> qwSopService.checkSopRuleTime());`  
-     - 其它如 `addTag()`、`wxSop()`、`sendQwGroupMsgTask()` 等同理,都包在 `runForEachTenant` 里。  
-  4. 业务 Mapper/Service 不用改,只要在「已切到该租户库 + 已设置租户配置」的线程里执行即可;若用 Redis,需保证带租户前缀(TenantKeyRedisSerializer)且上下文中有 tenantId。
-
----
-
-## 四、实施顺序建议
-
-1. **先做 fs-qw-task**:接 framework、DynamicDataSource、实现 `TenantTaskRunner`、逐个 @Scheduled 包一层 `runForEachTenant`,验证多租户数据与配置隔离。  
-2. **再做 fs-quartz**:在 fs-admin 里实现「租户任务分发器」Job,Quartz 只调度这一条;分发器内按租户切库并执行各租户库中到点的 sys_job。
-
-更细的步骤、方案 B(sys_job 上迁主库 + tenant_id)以及涉及的文件清单,都在 **`docs/SaaS改造方案.md`** 的 **第七章** 里,可直接按文档落地。

+ 0 - 271
docs/租户库升级方案.md

@@ -1,271 +0,0 @@
-# SaaS 租户库升级方案(字段/表结构变更同步)
-
-本文档用于解决 SaaS 模式下「代码发版后,数据库字段和表结构如何同步到各租户库」的问题。  
-当前项目采用「主库 `tenant_info` + 每租户独立库」模式,方案基于现有 `TenantDataSourceManager`、`TenantTaskRunner`、`TenantUtils` 能力落地。
-
----
-
-## 一、目标与范围
-
-### 1.1 目标
-
-- 每次发版涉及 DDL/DML 变更时,能够自动同步到所有目标租户库。
-- 支持灰度(部分租户)与全量(所有租户)两种执行模式。
-- 支持失败重试、断点续跑、任务审计与结果追踪。
-
-### 1.2 范围
-
-- **包含**:租户业务库的字段新增/修改、索引、初始化数据、数据回填。
-- **不包含**:跨库强事务回滚(多租户不适合做全局事务回滚)。
-
----
-
-## 二、总体设计
-
-采用「**版本化脚本 + 租户执行记录 + 主库任务编排**」模式:
-
-1. 脚本按版本管理(`VyyyyMMdd_nn__desc.sql`)。
-2. 每个租户库记录已执行版本(`tenant_db_migration`)。
-3. 主库记录升级任务与租户执行明细(`tenant_upgrade_task`、`tenant_upgrade_task_detail`)。
-4. 升级时主库查租户列表,按租户切库执行未执行脚本。
-5. 失败租户可单独重试,成功租户不重复执行。
-
----
-
-## 三、数据库表设计
-
-### 3.1 租户库:迁移记录表(必须)
-
-表名:`tenant_db_migration`
-
-```sql
-CREATE TABLE IF NOT EXISTS `tenant_db_migration` (
-  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
-  `version` VARCHAR(64) NOT NULL COMMENT '脚本版本,如 V20260416_01',
-  `script_name` VARCHAR(255) NOT NULL COMMENT '脚本文件名',
-  `checksum` VARCHAR(64) DEFAULT NULL COMMENT '脚本内容 SHA256',
-  `status` VARCHAR(16) NOT NULL COMMENT 'SUCCESS/FAILED',
-  `started_at` DATETIME NOT NULL COMMENT '开始时间',
-  `finished_at` DATETIME DEFAULT NULL COMMENT '结束时间',
-  `error_msg` TEXT DEFAULT NULL COMMENT '失败错误信息',
-  `executor` VARCHAR(64) DEFAULT NULL COMMENT '执行器标识',
-  `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
-  PRIMARY KEY (`id`),
-  UNIQUE KEY `uk_version` (`version`),
-  KEY `idx_status` (`status`),
-  KEY `idx_started_at` (`started_at`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户库迁移记录表';
-```
-
-### 3.2 主库:任务总表(建议)
-
-表名:`tenant_upgrade_task`
-
-```sql
-CREATE TABLE IF NOT EXISTS `tenant_upgrade_task` (
-  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
-  `task_no` VARCHAR(64) NOT NULL COMMENT '任务号',
-  `scope_type` VARCHAR(16) NOT NULL COMMENT 'ALL/INCLUDE/EXCLUDE',
-  `target_versions` VARCHAR(512) NOT NULL COMMENT '目标版本范围或列表',
-  `status` VARCHAR(16) NOT NULL COMMENT 'RUNNING/SUCCESS/PARTIAL/FAILED',
-  `total_tenants` INT NOT NULL DEFAULT 0 COMMENT '总租户数',
-  `success_tenants` INT NOT NULL DEFAULT 0 COMMENT '成功租户数',
-  `failed_tenants` INT NOT NULL DEFAULT 0 COMMENT '失败租户数',
-  `started_at` DATETIME NOT NULL COMMENT '开始时间',
-  `finished_at` DATETIME DEFAULT NULL COMMENT '结束时间',
-  `trigger_by` VARCHAR(64) DEFAULT NULL COMMENT '触发人',
-  `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注',
-  `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
-  PRIMARY KEY (`id`),
-  UNIQUE KEY `uk_task_no` (`task_no`),
-  KEY `idx_status` (`status`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户库升级任务主表';
-```
-
-### 3.3 主库:任务明细表(建议)
-
-表名:`tenant_upgrade_task_detail`
-
-```sql
-CREATE TABLE IF NOT EXISTS `tenant_upgrade_task_detail` (
-  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
-  `task_no` VARCHAR(64) NOT NULL COMMENT '任务号',
-  `tenant_id` BIGINT NOT NULL COMMENT '租户ID',
-  `tenant_code` VARCHAR(64) NOT NULL COMMENT '租户编码',
-  `current_version` VARCHAR(64) DEFAULT NULL COMMENT '升级前版本',
-  `target_version` VARCHAR(64) DEFAULT NULL COMMENT '目标版本',
-  `status` VARCHAR(16) NOT NULL COMMENT 'SUCCESS/FAILED/SKIPPED',
-  `error_msg` TEXT DEFAULT NULL COMMENT '失败原因',
-  `started_at` DATETIME NOT NULL COMMENT '开始时间',
-  `finished_at` DATETIME DEFAULT NULL COMMENT '结束时间',
-  `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
-  PRIMARY KEY (`id`),
-  UNIQUE KEY `uk_task_tenant` (`task_no`, `tenant_id`),
-  KEY `idx_task_no` (`task_no`),
-  KEY `idx_status` (`status`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户库升级任务明细';
-```
-
----
-
-## 四、脚本规范
-
-### 4.1 存放目录
-
-`fs-service/src/main/resources/db/migration/tenant/`
-
-### 4.2 命名规则
-
-- `V20260416_01__add_column_xxx.sql`
-- `V20260416_02__init_data_xxx.sql`
-
-### 4.3 编写要求
-
-- 只增量,不修改历史版本脚本。
-- 脚本必须幂等(`IF EXISTS`/`IF NOT EXISTS`、条件插入/更新)。
-- 大数据回填分批处理,避免长事务。
-- DDL 与 DML 拆分,便于排障与重试。
-
----
-
-## 五、应用架构与组件设计
-
-建议在 `fs-service` 增加以下组件:
-
-- `TenantMigrationScriptLoader`:扫描脚本、解析版本、排序、计算 checksum。
-- `TenantMigrationRepository`:在当前租户库读写 `tenant_db_migration`。
-- `TenantMigrationExecutor`:单租户执行器,串行执行该租户未执行脚本。
-- `TenantUpgradeOrchestrator`:主编排器,主库查租户并发起升级,汇总结果写主库任务表。
-
-可复用当前能力:
-
-- `tenant_info`:租户主数据来源。
-- `TenantDataSourceManager`:按租户切换数据源。
-- `TenantTaskRunner`:顺序/并行按租户执行框架。
-- `TenantUtils`:执行 SQL 脚本的工具能力(已改为 UTF-8 读取脚本)。
-
----
-
-## 六、升级流程
-
-### 6.1 发布前
-
-1. 研发提交本次版本 SQL 到脚本目录。
-2. 自测验证幂等(同脚本重复执行不报错)。
-3. 预发环境先全量演练。
-
-### 6.2 生产执行
-
-1. 先灰度(INCLUDE 指定租户)。
-2. 观察锁表、慢 SQL、失败率。
-3. 全量执行(ALL)。
-4. 对失败租户发起重试任务。
-
-### 6.3 发布后
-
-1. 导出任务结果(成功数/失败数/失败原因)。
-2. 与应用功能开关联动,确保目标版本达到后再开启新功能入口。
-
----
-
-## 七、接口设计(fs-admin)
-
-### 7.1 启动升级
-
-- `POST /tenant/upgrade/run`
-
-入参建议:
-
-- `scopeType`:`ALL` / `INCLUDE` / `EXCLUDE`
-- `tenantIds`:租户 ID 列表
-- `fromVersion`:起始版本(可空)
-- `toVersion`:目标版本(可空)
-- `parallel`:是否并行
-- `threads`:线程数
-- `remark`:备注
-
-### 7.2 查询任务
-
-- `GET /tenant/upgrade/task/{taskNo}`:任务总览
-- `GET /tenant/upgrade/task/{taskNo}/failures`:失败明细
-
-### 7.3 失败重试(可选)
-
-- `POST /tenant/upgrade/retry/{taskNo}`
-
----
-
-## 八、并发与稳定性策略
-
-- 默认顺序执行,稳定优先。
-- 租户多时开启并行(建议 4~8 线程起步)。
-- 原则:
-  - 租户之间可并行。
-  - 单租户内脚本严格串行。
-  - 单租户失败不中断全局任务。
-
-执行前检查建议:
-
-- 数据源连接池最大连接数 >= 并行线程数。
-- 避开业务高峰执行重 DDL。
-- 对高风险脚本先在小租户样本验证。
-
----
-
-## 九、失败处理与回滚策略
-
-### 9.1 处理原则
-
-- 不做跨租户全局回滚。
-- 失败租户记录错误并继续其余租户。
-- 修复后按失败清单重试。
-
-### 9.2 常见失败场景
-
-- 租户库结构已被手工改过(字段存在/类型不一致)。
-- 权限不足(DDL 权限缺失)。
-- 锁等待超时(与线上写入冲突)。
-
----
-
-## 十、实施步骤(建议分两期)
-
-### 第一期:可用版(1~2 周)
-
-1. 建立三张管理表(租户库一张,主库两张)。
-2. 落地脚本扫描与版本比较。
-3. 落地单租户执行器(含记录 SUCCESS/FAILED)。
-4. 落地主编排器(ALL/INCLUDE)。
-5. 提供 run/query 接口。
-
-### 第二期:增强版
-
-1. 并行执行与线程控制。
-2. 失败重试接口与告警通知。
-3. SQL 风险扫描(关键字与锁风险)。
-4. 与发布平台/流程联动自动触发。
-
----
-
-## 十一、与当前项目的关系说明
-
-- 本方案不改变现有「每租户独立库」隔离模型。
-- 不要求现有业务表新增 `tenant_id` 字段。
-- 方案可与当前 SaaS 登录、定时任务、动态切库实现并行推进。
-
----
-
-## 十二、实施清单(执行版)
-
-- [ ] 创建 `tenant_db_migration`(租户库)
-- [ ] 创建 `tenant_upgrade_task`(主库)
-- [ ] 创建 `tenant_upgrade_task_detail`(主库)
-- [ ] 新建脚本目录 `db/migration/tenant`
-- [ ] 规范脚本命名 `VyyyyMMdd_nn__desc.sql`
-- [ ] 实现脚本加载器与版本排序
-- [ ] 实现租户单库执行器
-- [ ] 实现主库任务编排器
-- [ ] 提供升级触发与查询接口
-- [ ] 预发全量演练
-- [ ] 生产灰度 + 全量 + 重试
-

+ 0 - 119
docs/租户费用模块.postman_collection.json

@@ -1,119 +0,0 @@
-{
-  "info": {
-    "_postman_id": "a0f8f4c6-3e22-4bd4-a3c8-billing-module",
-    "name": "租户费用模块联调集合",
-    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
-  },
-  "item": [
-    {
-      "name": "1. 创建方案",
-      "request": {
-        "method": "POST",
-        "header": [{ "key": "Content-Type", "value": "application/json" }],
-        "url": { "raw": "{{baseUrl}}/api/fee/plan/create", "host": ["{{baseUrl}}"], "path": ["api","fee","plan","create"] },
-        "body": {
-          "mode": "raw",
-          "raw": "{\n  \"planCode\": \"STANDARD\",\n  \"planName\": \"标准方案\",\n  \"version\": 1,\n  \"remark\": \"postman初始化\"\n}"
-        }
-      }
-    },
-    {
-      "name": "2. 保存计费项",
-      "request": {
-        "method": "POST",
-        "header": [{ "key": "Content-Type", "value": "application/json" }],
-        "url": { "raw": "{{baseUrl}}/api/fee/plan/item/save", "host": ["{{baseUrl}}"], "path": ["api","fee","plan","item","save"] },
-        "body": {
-          "mode": "raw",
-          "raw": "{\n  \"planCode\": \"STANDARD\",\n  \"version\": 1,\n  \"items\": [\n    {\"itemCode\":\"FLOW_POSTPAID\",\"unit\":\"GB\",\"unitPrice\":0.2,\"enabled\":1},\n    {\"itemCode\":\"CALL_OUT\",\"unit\":\"MIN\",\"unitPrice\":0.3,\"minChargeUnit\":1,\"enabled\":1},\n    {\"itemCode\":\"CALL_IN\",\"unit\":\"MIN\",\"unitPrice\":0.2,\"minChargeUnit\":1,\"enabled\":1},\n    {\"itemCode\":\"AI_CALL\",\"unit\":\"MIN\",\"unitPrice\":0.15,\"minChargeUnit\":1,\"enabled\":1},\n    {\"itemCode\":\"SOP_TOKEN\",\"unit\":\"TOKEN\",\"unitPrice\":1,\"tokenUnit\":100000,\"enabled\":1},\n    {\"itemCode\":\"AI_REPLY_TOKEN\",\"unit\":\"TOKEN\",\"unitPrice\":1,\"tokenUnit\":100000,\"enabled\":1},\n    {\"itemCode\":\"ADD_WECHAT\",\"unit\":\"COUNT\",\"unitPrice\":0.5,\"enabled\":1},\n    {\"itemCode\":\"OPEN_ACCOUNT_NON_AI\",\"unit\":\"TIME\",\"unitPrice\":1000,\"enabled\":1},\n    {\"itemCode\":\"OPEN_ACCOUNT_AI\",\"unit\":\"TIME\",\"unitPrice\":3000,\"enabled\":1}\n  ]\n}"
-        }
-      }
-    },
-    {
-      "name": "3. 保存流量阶梯",
-      "request": {
-        "method": "POST",
-        "header": [{ "key": "Content-Type", "value": "application/json" }],
-        "url": { "raw": "{{baseUrl}}/api/fee/plan/flow-tier/save", "host": ["{{baseUrl}}"], "path": ["api","fee","plan","flow-tier","save"] },
-        "body": {
-          "mode": "raw",
-          "raw": "{\n  \"planCode\":\"STANDARD\",\n  \"version\":1,\n  \"tiers\":[\n    {\"minPrepayAmount\":100000,\"maxPrepayAmount\":200000,\"unitPrice\":0.1,\"sortNo\":1},\n    {\"minPrepayAmount\":200000,\"maxPrepayAmount\":null,\"unitPrice\":0.08,\"sortNo\":2}\n  ]\n}"
-        }
-      }
-    },
-    {
-      "name": "4. 发布方案",
-      "request": {
-        "method": "POST",
-        "url": { "raw": "{{baseUrl}}/api/fee/plan/publish?planCode=STANDARD&version=1", "host": ["{{baseUrl}}"], "path": ["api","fee","plan","publish"], "query": [{"key":"planCode","value":"STANDARD"},{"key":"version","value":"1"}] }
-      }
-    },
-    {
-      "name": "5. 绑定租户方案",
-      "request": {
-        "method": "POST",
-        "header": [{ "key": "Content-Type", "value": "application/json" }],
-        "url": { "raw": "{{baseUrl}}/api/fee/tenant/bind-plan", "host": ["{{baseUrl}}"], "path": ["api","fee","tenant","bind-plan"] },
-        "body": {
-          "mode": "raw",
-          "raw": "{\n  \"tenantId\": 1,\n  \"tenantType\": \"AI\",\n  \"billingMode\": \"PREPAID\",\n  \"planCode\": \"STANDARD\",\n  \"planVersion\": 1\n}"
-        }
-      }
-    },
-    {
-      "name": "6. 钱包充值",
-      "request": {
-        "method": "POST",
-        "header": [{ "key": "Content-Type", "value": "application/json" }],
-        "url": { "raw": "{{baseUrl}}/api/fee/wallet/recharge", "host": ["{{baseUrl}}"], "path": ["api","fee","wallet","recharge"] },
-        "body": {
-          "mode": "raw",
-          "raw": "{\n  \"tenantId\": 1,\n  \"amount\": 100000,\n  \"bizNo\": \"RC001\",\n  \"remark\": \"预存充值\"\n}"
-        }
-      }
-    },
-    {
-      "name": "7. 上报CALL事件(AI外呼)",
-      "request": {
-        "method": "POST",
-        "header": [{ "key": "Content-Type", "value": "application/json" }],
-        "url": { "raw": "{{baseUrl}}/api/fee/usage/report", "host": ["{{baseUrl}}"], "path": ["api","fee","usage","report"] },
-        "body": {
-          "mode": "raw",
-          "raw": "{\n  \"eventId\": \"evt_call_001\",\n  \"tenantId\": 1,\n  \"eventType\": \"CALL\",\n  \"subType\": \"CALL_OUT\",\n  \"bizId\": \"callBiz001\",\n  \"usageValue\": 47,\n  \"usageUnit\": \"SECOND\",\n  \"extJson\": {\"isAiCall\": true}\n}"
-        }
-      }
-    },
-    {
-      "name": "8. 查询计费明细",
-      "request": {
-        "method": "GET",
-        "url": { "raw": "{{baseUrl}}/api/fee/billing/detail/list?tenantId=1", "host": ["{{baseUrl}}"], "path": ["api","fee","billing","detail","list"], "query": [{"key":"tenantId","value":"1"}] }
-      }
-    },
-    {
-      "name": "9. 生成账单",
-      "request": {
-        "method": "POST",
-        "url": {
-          "raw": "{{baseUrl}}/api/fee/statement/generate?tenantId=1&periodType=MONTHLY&periodStart=2026-04-01%2000:00:00&periodEnd=2026-04-30%2023:59:59",
-          "host": ["{{baseUrl}}"],
-          "path": ["api","fee","statement","generate"],
-          "query": [
-            {"key":"tenantId","value":"1"},
-            {"key":"periodType","value":"MONTHLY"},
-            {"key":"periodStart","value":"2026-04-01 00:00:00"},
-            {"key":"periodEnd","value":"2026-04-30 23:59:59"}
-          ]
-        }
-      }
-    }
-  ],
-  "variable": [
-    {
-      "key": "baseUrl",
-      "value": "http://127.0.0.1:8004"
-    }
-  ]
-}
-

+ 0 - 200
docs/租户费用模块SQL-master.sql

@@ -1,200 +0,0 @@
--- 租户费用模块 SQL(总库)
--- 适用数据库:MySQL 8.x
--- 说明:
--- 1) 当前计费模块采用“总库集中存储(按 tenant_id 隔离)”;
--- 2) 本文件应在总库执行;
--- 3) 所有金额统一使用 DECIMAL,避免浮点误差。
-
-/* =========================================================
-   0. 租户表扩展(tenant_info)
-   ========================================================= */
-ALTER TABLE tenant_info
-ADD COLUMN tenant_type VARCHAR(16) NOT NULL DEFAULT 'NON_AI' COMMENT '租户类型: NON_AI/AI',
-ADD COLUMN billing_mode VARCHAR(16) NOT NULL DEFAULT 'PREPAID' COMMENT '计费模式: PREPAID/POSTPAID',
-ADD COLUMN fee_plan_code VARCHAR(64) DEFAULT NULL COMMENT '绑定计费方案编码',
-ADD COLUMN fee_plan_version INT DEFAULT NULL COMMENT '绑定计费方案版本';
-
-/* =========================================================
-   1. 计费方案
-   ========================================================= */
-CREATE TABLE IF NOT EXISTS fee_plan (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  plan_code VARCHAR(64) NOT NULL COMMENT '方案编码',
-  plan_name VARCHAR(128) NOT NULL COMMENT '方案名称',
-  version INT NOT NULL COMMENT '版本号',
-  status VARCHAR(16) NOT NULL DEFAULT 'DRAFT' COMMENT 'DRAFT/PUBLISHED/ARCHIVED',
-  effective_time DATETIME DEFAULT NULL COMMENT '生效时间',
-  expire_time DATETIME DEFAULT NULL COMMENT '失效时间',
-  remark VARCHAR(500) DEFAULT NULL,
-  create_by VARCHAR(64) DEFAULT NULL,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  update_by VARCHAR(64) DEFAULT NULL,
-  update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_plan_ver (plan_code, version),
-  KEY idx_status (status)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='计费方案主表';
-
-CREATE TABLE IF NOT EXISTS fee_plan_item (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  plan_code VARCHAR(64) NOT NULL,
-  version INT NOT NULL,
-  item_code VARCHAR(64) NOT NULL COMMENT 'FLOW_POSTPAID/CALL_OUT/CALL_IN/AI_CALL/SOP_TOKEN/AI_REPLY_TOKEN/ADD_WECHAT/OPEN_ACCOUNT_NON_AI/OPEN_ACCOUNT_AI',
-  unit VARCHAR(32) NOT NULL COMMENT 'GB/MIN/TOKEN/COUNT/TIME',
-  unit_price DECIMAL(18,6) NOT NULL DEFAULT 0 COMMENT '单价',
-  token_unit BIGINT DEFAULT NULL COMMENT 'token计费单位(如100000)',
-  min_charge_unit INT DEFAULT NULL COMMENT '最小计费单位(如通话最小1分钟)',
-  enabled TINYINT NOT NULL DEFAULT 1,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_plan_item (plan_code, version, item_code)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='计费项配置';
-
-CREATE TABLE IF NOT EXISTS fee_plan_flow_tier (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  plan_code VARCHAR(64) NOT NULL,
-  version INT NOT NULL,
-  min_prepay_amount DECIMAL(18,2) NOT NULL COMMENT '最低预存金额(含)',
-  max_prepay_amount DECIMAL(18,2) DEFAULT NULL COMMENT '最高预存金额(不含,空为无上限)',
-  unit_price DECIMAL(18,6) NOT NULL COMMENT '流量单价(元/GB)',
-  sort_no INT NOT NULL DEFAULT 0,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_tier (plan_code, version, min_prepay_amount)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='流量阶梯配置';
-
-/* =========================================================
-   2. 钱包与流水
-   ========================================================= */
-CREATE TABLE IF NOT EXISTS tenant_wallet (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  tenant_id BIGINT NOT NULL,
-  balance_amount DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '可用余额',
-  frozen_amount DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '冻结金额',
-  credit_limit DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '授信额度(后付费可用)',
-  total_recharge DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '累计充值',
-  total_cost DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '累计消费',
-  update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_tenant_wallet (tenant_id)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户钱包';
-
-CREATE TABLE IF NOT EXISTS tenant_wallet_txn (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  tenant_id BIGINT NOT NULL,
-  txn_no VARCHAR(64) NOT NULL,
-  txn_type VARCHAR(32) NOT NULL COMMENT 'RECHARGE/CONSUME/ADJUST/REFUND',
-  amount DECIMAL(18,2) NOT NULL COMMENT '消费建议记录为负数',
-  balance_after DECIMAL(18,2) NOT NULL,
-  biz_type VARCHAR(64) DEFAULT NULL COMMENT 'FLOW/CALL/TOKEN/ADD_WECHAT/OPEN_ACCOUNT',
-  biz_id VARCHAR(64) DEFAULT NULL COMMENT '关联业务ID',
-  remark VARCHAR(500) DEFAULT NULL,
-  create_by VARCHAR(64) DEFAULT NULL,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_txn_no (txn_no),
-  KEY idx_tenant_time (tenant_id, create_time)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='钱包流水';
-
-/* =========================================================
-   3. 用量事件与计费明细
-   ========================================================= */
-CREATE TABLE IF NOT EXISTS usage_event (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  event_id VARCHAR(64) NOT NULL COMMENT '幂等ID',
-  tenant_id BIGINT NOT NULL,
-  event_type VARCHAR(32) NOT NULL COMMENT 'FLOW/CALL/TOKEN_SOP/TOKEN_AI_REPLY/ADD_WECHAT/OPEN_ACCOUNT',
-  sub_type VARCHAR(32) DEFAULT NULL COMMENT 'CALL_IN/CALL_OUT/AI_CALL 等',
-  biz_id VARCHAR(64) DEFAULT NULL,
-  usage_value DECIMAL(20,6) NOT NULL,
-  usage_unit VARCHAR(32) NOT NULL COMMENT 'GB/MB/SECOND/TOKEN/COUNT',
-  occurred_at DATETIME NOT NULL,
-  ext_json JSON DEFAULT NULL,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_event_id (event_id),
-  KEY idx_tenant_type_time (tenant_id, event_type, occurred_at)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用量事件';
-
-CREATE TABLE IF NOT EXISTS billing_detail (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  tenant_id BIGINT NOT NULL,
-  statement_id BIGINT DEFAULT NULL,
-  event_id VARCHAR(64) NOT NULL,
-  event_type VARCHAR(32) NOT NULL,
-  sub_type VARCHAR(32) DEFAULT NULL,
-  plan_code VARCHAR(64) NOT NULL,
-  plan_version INT NOT NULL,
-  unit_price DECIMAL(18,6) NOT NULL,
-  usage_value DECIMAL(20,6) NOT NULL,
-  charge_value DECIMAL(20,6) NOT NULL COMMENT '计费量,如向上取整后的分钟',
-  amount DECIMAL(18,2) NOT NULL,
-  billing_mode VARCHAR(16) NOT NULL COMMENT 'PREPAID/POSTPAID',
-  occurred_at DATETIME NOT NULL,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_event_type_sub (event_id, event_type, sub_type),
-  KEY idx_tenant_time (tenant_id, occurred_at),
-  KEY idx_statement (statement_id)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='计费明细';
-
-/* =========================================================
-   4. 账单
-   ========================================================= */
-CREATE TABLE IF NOT EXISTS billing_statement (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  statement_no VARCHAR(64) NOT NULL,
-  tenant_id BIGINT NOT NULL,
-  period_type VARCHAR(16) NOT NULL COMMENT 'DAILY/MONTHLY',
-  period_start DATETIME NOT NULL,
-  period_end DATETIME NOT NULL,
-  total_amount DECIMAL(18,2) NOT NULL DEFAULT 0,
-  paid_amount DECIMAL(18,2) NOT NULL DEFAULT 0,
-  unpaid_amount DECIMAL(18,2) NOT NULL DEFAULT 0,
-  status VARCHAR(16) NOT NULL DEFAULT 'INIT' COMMENT 'INIT/CONFIRMED/PAID/PARTIAL',
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_statement_no (statement_no),
-  KEY idx_tenant_period (tenant_id, period_start, period_end)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='账单主表';
-
-CREATE TABLE IF NOT EXISTS billing_statement_item (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  statement_id BIGINT NOT NULL,
-  item_code VARCHAR(64) NOT NULL,
-  amount DECIMAL(18,2) NOT NULL DEFAULT 0,
-  usage_value DECIMAL(20,6) NOT NULL DEFAULT 0,
-  unit VARCHAR(32) DEFAULT NULL,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_stmt_item (statement_id, item_code),
-  KEY idx_statement_id (statement_id)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='账单项汇总';
-
-/* =========================================================
-   5. 初始化示例数据(可选)
-   ========================================================= */
-INSERT INTO fee_plan(plan_code, plan_name, version, status, effective_time, remark)
-VALUES ('STANDARD', '标准计费方案', 1, 'PUBLISHED', NOW(), '默认方案')
-ON DUPLICATE KEY UPDATE plan_name=VALUES(plan_name), status=VALUES(status), effective_time=VALUES(effective_time), remark=VALUES(remark);
-
-INSERT INTO fee_plan_item(plan_code, version, item_code, unit, unit_price, min_charge_unit, token_unit, enabled) VALUES
-('STANDARD',1,'FLOW_POSTPAID','GB',0.20,NULL,NULL,1),
-('STANDARD',1,'CALL_OUT','MIN',0.30,1,NULL,1),
-('STANDARD',1,'CALL_IN','MIN',0.20,1,NULL,1),
-('STANDARD',1,'AI_CALL','MIN',0.15,1,NULL,1),
-('STANDARD',1,'SOP_TOKEN','TOKEN',1.00,NULL,100000,1),
-('STANDARD',1,'AI_REPLY_TOKEN','TOKEN',1.00,NULL,100000,1),
-('STANDARD',1,'ADD_WECHAT','COUNT',0.50,NULL,NULL,1),
-('STANDARD',1,'OPEN_ACCOUNT_NON_AI','TIME',1000.00,NULL,NULL,1),
-('STANDARD',1,'OPEN_ACCOUNT_AI','TIME',3000.00,NULL,NULL,1)
-ON DUPLICATE KEY UPDATE unit=VALUES(unit), unit_price=VALUES(unit_price), min_charge_unit=VALUES(min_charge_unit), token_unit=VALUES(token_unit), enabled=VALUES(enabled);
-
-INSERT INTO fee_plan_flow_tier(plan_code, version, min_prepay_amount, max_prepay_amount, unit_price, sort_no) VALUES
-('STANDARD',1,100000,200000,0.10,1),
-('STANDARD',1,200000,NULL,0.08,2)
-ON DUPLICATE KEY UPDATE max_prepay_amount=VALUES(max_prepay_amount), unit_price=VALUES(unit_price), sort_no=VALUES(sort_no);
-

+ 0 - 12
docs/租户费用模块SQL-tenant.sql

@@ -1,12 +0,0 @@
--- 租户费用模块 SQL(租户库)
--- 适用数据库:MySQL 8.x
--- 说明:
--- 1) 按当前版本实现,计费数据集中存储在总库,按 tenant_id 逻辑隔离;
--- 2) 因此本版本“租户库”无新增计费表结构;
--- 3) 保留此文件用于后续版本(若改为租户库分片计费可在此追加)。
-
-/* =========================================================
-   当前版本无租户库 DDL 变更
-   ========================================================= */
--- NO-OP
-

+ 0 - 203
docs/租户费用模块SQL.sql

@@ -1,203 +0,0 @@
--- 租户费用模块 SQL(MVP)
--- 适用数据库:MySQL 8.x
--- 说明:
--- 1) 先执行租户扩展字段,再执行计费基础表;
--- 2) 初始化示例数据可按需执行;
--- 3) 所有金额统一使用 DECIMAL,避免浮点误差。
--- 4) 已按库类型拆分为:
---    - docs/租户费用模块SQL-master.sql(总库执行)
---    - docs/租户费用模块SQL-tenant.sql(租户库执行)
-
-/* =========================================================
-   0. 租户表扩展(tenant_info)
-   ========================================================= */
-ALTER TABLE tenant_info
-ADD COLUMN tenant_type VARCHAR(16) NOT NULL DEFAULT 'NON_AI' COMMENT '租户类型: NON_AI/AI',
-ADD COLUMN billing_mode VARCHAR(16) NOT NULL DEFAULT 'PREPAID' COMMENT '计费模式: PREPAID/POSTPAID',
-ADD COLUMN fee_plan_code VARCHAR(64) DEFAULT NULL COMMENT '绑定计费方案编码',
-ADD COLUMN fee_plan_version INT DEFAULT NULL COMMENT '绑定计费方案版本';
-
-/* =========================================================
-   1. 计费方案
-   ========================================================= */
-CREATE TABLE IF NOT EXISTS fee_plan (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  plan_code VARCHAR(64) NOT NULL COMMENT '方案编码',
-  plan_name VARCHAR(128) NOT NULL COMMENT '方案名称',
-  version INT NOT NULL COMMENT '版本号',
-  status VARCHAR(16) NOT NULL DEFAULT 'DRAFT' COMMENT 'DRAFT/PUBLISHED/ARCHIVED',
-  effective_time DATETIME DEFAULT NULL COMMENT '生效时间',
-  expire_time DATETIME DEFAULT NULL COMMENT '失效时间',
-  remark VARCHAR(500) DEFAULT NULL,
-  create_by VARCHAR(64) DEFAULT NULL,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  update_by VARCHAR(64) DEFAULT NULL,
-  update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_plan_ver (plan_code, version),
-  KEY idx_status (status)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='计费方案主表';
-
-CREATE TABLE IF NOT EXISTS fee_plan_item (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  plan_code VARCHAR(64) NOT NULL,
-  version INT NOT NULL,
-  item_code VARCHAR(64) NOT NULL COMMENT 'FLOW_POSTPAID/CALL_OUT/CALL_IN/AI_CALL/SOP_TOKEN/AI_REPLY_TOKEN/ADD_WECHAT/OPEN_ACCOUNT_NON_AI/OPEN_ACCOUNT_AI',
-  unit VARCHAR(32) NOT NULL COMMENT 'GB/MIN/TOKEN/COUNT/TIME',
-  unit_price DECIMAL(18,6) NOT NULL DEFAULT 0 COMMENT '单价',
-  token_unit BIGINT DEFAULT NULL COMMENT 'token计费单位(如100000)',
-  min_charge_unit INT DEFAULT NULL COMMENT '最小计费单位(如通话最小1分钟)',
-  enabled TINYINT NOT NULL DEFAULT 1,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_plan_item (plan_code, version, item_code)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='计费项配置';
-
-CREATE TABLE IF NOT EXISTS fee_plan_flow_tier (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  plan_code VARCHAR(64) NOT NULL,
-  version INT NOT NULL,
-  min_prepay_amount DECIMAL(18,2) NOT NULL COMMENT '最低预存金额(含)',
-  max_prepay_amount DECIMAL(18,2) DEFAULT NULL COMMENT '最高预存金额(不含,空为无上限)',
-  unit_price DECIMAL(18,6) NOT NULL COMMENT '流量单价(元/GB)',
-  sort_no INT NOT NULL DEFAULT 0,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_tier (plan_code, version, min_prepay_amount)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='流量阶梯配置';
-
-/* =========================================================
-   2. 钱包与流水
-   ========================================================= */
-CREATE TABLE IF NOT EXISTS tenant_wallet (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  tenant_id BIGINT NOT NULL,
-  balance_amount DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '可用余额',
-  frozen_amount DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '冻结金额',
-  credit_limit DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '授信额度(后付费可用)',
-  total_recharge DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '累计充值',
-  total_cost DECIMAL(18,2) NOT NULL DEFAULT 0 COMMENT '累计消费',
-  update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_tenant_wallet (tenant_id)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户钱包';
-
-CREATE TABLE IF NOT EXISTS tenant_wallet_txn (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  tenant_id BIGINT NOT NULL,
-  txn_no VARCHAR(64) NOT NULL,
-  txn_type VARCHAR(32) NOT NULL COMMENT 'RECHARGE/CONSUME/ADJUST/REFUND',
-  amount DECIMAL(18,2) NOT NULL COMMENT '消费建议记录为负数',
-  balance_after DECIMAL(18,2) NOT NULL,
-  biz_type VARCHAR(64) DEFAULT NULL COMMENT 'FLOW/CALL/TOKEN/ADD_WECHAT/OPEN_ACCOUNT',
-  biz_id VARCHAR(64) DEFAULT NULL COMMENT '关联业务ID',
-  remark VARCHAR(500) DEFAULT NULL,
-  create_by VARCHAR(64) DEFAULT NULL,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_txn_no (txn_no),
-  KEY idx_tenant_time (tenant_id, create_time)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='钱包流水';
-
-/* =========================================================
-   3. 用量事件与计费明细
-   ========================================================= */
-CREATE TABLE IF NOT EXISTS usage_event (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  event_id VARCHAR(64) NOT NULL COMMENT '幂等ID',
-  tenant_id BIGINT NOT NULL,
-  event_type VARCHAR(32) NOT NULL COMMENT 'FLOW/CALL/TOKEN_SOP/TOKEN_AI_REPLY/ADD_WECHAT/OPEN_ACCOUNT',
-  sub_type VARCHAR(32) DEFAULT NULL COMMENT 'CALL_IN/CALL_OUT/AI_CALL 等',
-  biz_id VARCHAR(64) DEFAULT NULL,
-  usage_value DECIMAL(20,6) NOT NULL,
-  usage_unit VARCHAR(32) NOT NULL COMMENT 'GB/MB/SECOND/TOKEN/COUNT',
-  occurred_at DATETIME NOT NULL,
-  ext_json JSON DEFAULT NULL,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_event_id (event_id),
-  KEY idx_tenant_type_time (tenant_id, event_type, occurred_at)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用量事件';
-
-CREATE TABLE IF NOT EXISTS billing_detail (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  tenant_id BIGINT NOT NULL,
-  statement_id BIGINT DEFAULT NULL,
-  event_id VARCHAR(64) NOT NULL,
-  event_type VARCHAR(32) NOT NULL,
-  sub_type VARCHAR(32) DEFAULT NULL,
-  plan_code VARCHAR(64) NOT NULL,
-  plan_version INT NOT NULL,
-  unit_price DECIMAL(18,6) NOT NULL,
-  usage_value DECIMAL(20,6) NOT NULL,
-  charge_value DECIMAL(20,6) NOT NULL COMMENT '计费量,如向上取整后的分钟',
-  amount DECIMAL(18,2) NOT NULL,
-  billing_mode VARCHAR(16) NOT NULL COMMENT 'PREPAID/POSTPAID',
-  occurred_at DATETIME NOT NULL,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_event_type_sub (event_id, event_type, sub_type),
-  KEY idx_tenant_time (tenant_id, occurred_at),
-  KEY idx_statement (statement_id)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='计费明细';
-
-/* =========================================================
-   4. 账单
-   ========================================================= */
-CREATE TABLE IF NOT EXISTS billing_statement (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  statement_no VARCHAR(64) NOT NULL,
-  tenant_id BIGINT NOT NULL,
-  period_type VARCHAR(16) NOT NULL COMMENT 'DAILY/MONTHLY',
-  period_start DATETIME NOT NULL,
-  period_end DATETIME NOT NULL,
-  total_amount DECIMAL(18,2) NOT NULL DEFAULT 0,
-  paid_amount DECIMAL(18,2) NOT NULL DEFAULT 0,
-  unpaid_amount DECIMAL(18,2) NOT NULL DEFAULT 0,
-  status VARCHAR(16) NOT NULL DEFAULT 'INIT' COMMENT 'INIT/CONFIRMED/PAID/PARTIAL',
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_statement_no (statement_no),
-  KEY idx_tenant_period (tenant_id, period_start, period_end)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='账单主表';
-
-CREATE TABLE IF NOT EXISTS billing_statement_item (
-  id BIGINT NOT NULL AUTO_INCREMENT,
-  statement_id BIGINT NOT NULL,
-  item_code VARCHAR(64) NOT NULL,
-  amount DECIMAL(18,2) NOT NULL DEFAULT 0,
-  usage_value DECIMAL(20,6) NOT NULL DEFAULT 0,
-  unit VARCHAR(32) DEFAULT NULL,
-  create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  PRIMARY KEY (id),
-  UNIQUE KEY uk_stmt_item (statement_id, item_code),
-  KEY idx_statement_id (statement_id)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='账单项汇总';
-
-/* =========================================================
-   5. 初始化示例数据(可选)
-   ========================================================= */
-INSERT INTO fee_plan(plan_code, plan_name, version, status, effective_time, remark)
-VALUES ('STANDARD', '标准计费方案', 1, 'PUBLISHED', NOW(), '默认方案')
-ON DUPLICATE KEY UPDATE plan_name=VALUES(plan_name), status=VALUES(status), effective_time=VALUES(effective_time), remark=VALUES(remark);
-
-INSERT INTO fee_plan_item(plan_code, version, item_code, unit, unit_price, min_charge_unit, token_unit, enabled) VALUES
-('STANDARD',1,'FLOW_POSTPAID','GB',0.20,NULL,NULL,1),
-('STANDARD',1,'CALL_OUT','MIN',0.30,1,NULL,1),
-('STANDARD',1,'CALL_IN','MIN',0.20,1,NULL,1),
-('STANDARD',1,'AI_CALL','MIN',0.15,1,NULL,1),
-('STANDARD',1,'SOP_TOKEN','TOKEN',1.00,NULL,100000,1),
-('STANDARD',1,'AI_REPLY_TOKEN','TOKEN',1.00,NULL,100000,1),
-('STANDARD',1,'ADD_WECHAT','COUNT',0.50,NULL,NULL,1),
-('STANDARD',1,'OPEN_ACCOUNT_NON_AI','TIME',1000.00,NULL,NULL,1),
-('STANDARD',1,'OPEN_ACCOUNT_AI','TIME',3000.00,NULL,NULL,1)
-ON DUPLICATE KEY UPDATE unit=VALUES(unit), unit_price=VALUES(unit_price), min_charge_unit=VALUES(min_charge_unit), token_unit=VALUES(token_unit), enabled=VALUES(enabled);
-
-INSERT INTO fee_plan_flow_tier(plan_code, version, min_prepay_amount, max_prepay_amount, unit_price, sort_no) VALUES
-('STANDARD',1,100000,200000,0.10,1),
-('STANDARD',1,200000,NULL,0.08,2)
-ON DUPLICATE KEY UPDATE max_prepay_amount=VALUES(max_prepay_amount), unit_price=VALUES(unit_price), sort_no=VALUES(sort_no);
-

+ 0 - 78
docs/计费模块菜单SQL-总账号-计费配置入口.sql

@@ -1,78 +0,0 @@
--- 计费模块菜单 SQL(总账号 - 计费配置入口)
--- 说明:
--- 1) 为总账号新增“计费配置”页面菜单;
--- 2) 幂等执行,不重复插入;
--- 3) 默认挂在 path='tenant' 父菜单下,找不到则挂根节点(0)。
-
-SET @now = NOW();
-SET @createBy = 'admin';
-
--- 找父菜单:优先租户管理目录
-SELECT @parentId := menu_id
-FROM sys_menu
-WHERE path = 'tenant'
-ORDER BY menu_id DESC
-LIMIT 1;
-
-SET @parentId = IFNULL(@parentId, 0);
-
--- 1) 页面菜单(C)
-INSERT INTO sys_menu
-(menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
-SELECT
-  '计费配置', @parentId, 30, 'billingConfig', 'saas/billing/index', 1, 0, 'C', '0', '0', 'fee:billing:config', '#',
-  @createBy, @now, '', NULL, 'SaaS计费配置入口(方案、绑定、钱包、事件)'
-FROM dual
-WHERE NOT EXISTS (
-  SELECT 1 FROM sys_menu WHERE component = 'saas/billing/index'
-);
-
--- 菜单ID
-SELECT @configMenuId := menu_id
-FROM sys_menu
-WHERE component = 'saas/billing/index'
-LIMIT 1;
-
--- 2) 按钮权限(F):查询
-INSERT INTO sys_menu
-(menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
-SELECT
-  '计费配置查询', @configMenuId, 1, '#', '', 1, 0, 'F', '0', '0', 'fee:billing:config:query', '#',
-  @createBy, @now, '', NULL, '计费配置查询权限'
-FROM dual
-WHERE @configMenuId IS NOT NULL
-  AND NOT EXISTS (
-    SELECT 1 FROM sys_menu WHERE parent_id = @configMenuId AND perms = 'fee:billing:config:query' AND menu_type = 'F'
-  );
-
--- 3) 按钮权限(F):编辑
-INSERT INTO sys_menu
-(menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
-SELECT
-  '计费配置编辑', @configMenuId, 2, '#', '', 1, 0, 'F', '0', '0', 'fee:billing:config:edit', '#',
-  @createBy, @now, '', NULL, '计费配置编辑权限'
-FROM dual
-WHERE @configMenuId IS NOT NULL
-  AND NOT EXISTS (
-    SELECT 1 FROM sys_menu WHERE parent_id = @configMenuId AND perms = 'fee:billing:config:edit' AND menu_type = 'F'
-  );
-
--- 4) 授权给 admin 角色
-SELECT @adminRoleId := role_id
-FROM sys_role
-WHERE role_key = 'admin'
-LIMIT 1;
-
-INSERT INTO sys_role_menu (role_id, menu_id)
-SELECT @adminRoleId, m.menu_id
-FROM sys_menu m
-WHERE @adminRoleId IS NOT NULL
-  AND m.menu_id IN (
-    @configMenuId,
-    (SELECT menu_id FROM sys_menu WHERE parent_id = @configMenuId AND perms = 'fee:billing:config:query' AND menu_type = 'F' LIMIT 1),
-    (SELECT menu_id FROM sys_menu WHERE parent_id = @configMenuId AND perms = 'fee:billing:config:edit' AND menu_type = 'F' LIMIT 1)
-  )
-  AND NOT EXISTS (
-    SELECT 1 FROM sys_role_menu rm WHERE rm.role_id = @adminRoleId AND rm.menu_id = m.menu_id
-  );
-

+ 0 - 66
docs/计费模块菜单SQL-总账号.sql

@@ -1,66 +0,0 @@
--- 计费模块菜单 SQL(总账号)
--- 说明:
--- 1) 本脚本用于平台总账号菜单与权限初始化;
--- 2) 幂等执行,不会重复插入;
--- 3) 默认挂在 path='tenant' 的父菜单下,找不到则挂根节点(0)。
-
-SET @now = NOW();
-SET @createBy = 'admin';
-
--- 找父菜单:优先租户管理目录
-SELECT @parentId := menu_id
-FROM sys_menu
-WHERE path = 'tenant'
-ORDER BY menu_id DESC
-LIMIT 1;
-
-SET @parentId = IFNULL(@parentId, 0);
-
--- 1) 总账号页面菜单(C)
-INSERT INTO sys_menu
-(menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
-SELECT
-  '费用明细(总账号)', @parentId, 31, 'billingAdmin', 'saas/billingAdmin/index', 1, 0, 'C', '0', '0', 'fee:billing:admin:list', '#',
-  @createBy, @now, '', NULL, 'SaaS总账号查看全租户费用明细'
-FROM dual
-WHERE NOT EXISTS (
-  SELECT 1 FROM sys_menu WHERE component = 'saas/billingAdmin/index'
-);
-
--- 页面菜单ID
-SELECT @adminPageMenuId := menu_id
-FROM sys_menu
-WHERE component = 'saas/billingAdmin/index'
-LIMIT 1;
-
--- 2) 总账号查询按钮(F)
-INSERT INTO sys_menu
-(menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
-SELECT
-  '总账号费用明细查询', @adminPageMenuId, 1, '#', '', 1, 0, 'F', '0', '0', 'fee:billing:admin:list', '#',
-  @createBy, @now, '', NULL, '总账号费用明细查询权限'
-FROM dual
-WHERE @adminPageMenuId IS NOT NULL
-  AND NOT EXISTS (
-    SELECT 1
-    FROM sys_menu
-    WHERE parent_id = @adminPageMenuId
-      AND perms = 'fee:billing:admin:list'
-      AND menu_type = 'F'
-  );
-
--- 3) 绑定 admin 角色
-SELECT @adminRoleId := role_id
-FROM sys_role
-WHERE role_key = 'admin'
-LIMIT 1;
-
-INSERT INTO sys_role_menu (role_id, menu_id)
-SELECT @adminRoleId, m.menu_id
-FROM sys_menu m
-WHERE @adminRoleId IS NOT NULL
-  AND m.menu_id = @adminPageMenuId
-  AND NOT EXISTS (
-    SELECT 1 FROM sys_role_menu rm WHERE rm.role_id = @adminRoleId AND rm.menu_id = m.menu_id
-  );
-

+ 0 - 70
docs/计费模块菜单SQL-租户账号.sql

@@ -1,70 +0,0 @@
--- 计费模块菜单 SQL(租户账号)
--- 说明:
--- 1) 本脚本用于租户账号菜单与权限初始化;
--- 2) 幂等执行,不会重复插入;
--- 3) 默认挂在 path='tenant' 的父菜单下,找不到则挂根节点(0);
--- 4) 需将 @tenantRoleKey 修改为你系统真实租户角色 key。
-
-SET @now = NOW();
-SET @createBy = 'admin';
-
--- TODO: 改为你系统真实租户角色 key
-SET @tenantRoleKey = 'tenant_admin';
-
--- 找父菜单:优先租户管理目录
-SELECT @parentId := menu_id
-FROM sys_menu
-WHERE path = 'tenant'
-ORDER BY menu_id DESC
-LIMIT 1;
-
-SET @parentId = IFNULL(@parentId, 0);
-
--- 1) 租户账号页面菜单(C)
-INSERT INTO sys_menu
-(menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
-SELECT
-  '费用明细(我的)', @parentId, 32, 'billingTenant', 'saas/billingTenant/index', 1, 0, 'C', '0', '0', 'fee:billing:tenant:list', '#',
-  @createBy, @now, '', NULL, 'SaaS租户查看自己费用明细'
-FROM dual
-WHERE NOT EXISTS (
-  SELECT 1 FROM sys_menu WHERE component = 'saas/billingTenant/index'
-);
-
--- 页面菜单ID
-SELECT @tenantPageMenuId := menu_id
-FROM sys_menu
-WHERE component = 'saas/billingTenant/index'
-LIMIT 1;
-
--- 2) 租户账号查询按钮(F)
-INSERT INTO sys_menu
-(menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
-SELECT
-  '租户费用明细查询', @tenantPageMenuId, 1, '#', '', 1, 0, 'F', '0', '0', 'fee:billing:tenant:list', '#',
-  @createBy, @now, '', NULL, '租户费用明细查询权限'
-FROM dual
-WHERE @tenantPageMenuId IS NOT NULL
-  AND NOT EXISTS (
-    SELECT 1
-    FROM sys_menu
-    WHERE parent_id = @tenantPageMenuId
-      AND perms = 'fee:billing:tenant:list'
-      AND menu_type = 'F'
-  );
-
--- 3) 绑定租户角色
-SELECT @tenantRoleId := role_id
-FROM sys_role
-WHERE role_key = @tenantRoleKey
-LIMIT 1;
-
-INSERT INTO sys_role_menu (role_id, menu_id)
-SELECT @tenantRoleId, m.menu_id
-FROM sys_menu m
-WHERE @tenantRoleId IS NOT NULL
-  AND m.menu_id = @tenantPageMenuId
-  AND NOT EXISTS (
-    SELECT 1 FROM sys_role_menu rm WHERE rm.role_id = @tenantRoleId AND rm.menu_id = m.menu_id
-  );
-

+ 0 - 215
fs-ad-api/src/main/java/com/fs/app/controller/MockAppController.java

@@ -1,215 +0,0 @@
-package com.fs.app.controller;
-
-import com.fs.baidu.domain.BdApi;
-import com.fs.baidu.service.IBdApiService;
-import com.fs.baidu.utils.SignService;
-import com.fs.huifuPay.sdk.opps.core.exception.BasePayException;
-import com.fs.huifuPay.sdk.opps.core.utils.HttpClientUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.json.JSONObject;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.servlet.http.HttpServletRequest;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.TreeMap;
-
-@Slf4j
-@RestController
-@RequestMapping("/baiduBack")
-public class MockAppController {
-    private static final String APPID = "appId";
-    private static final String AUTH_CODE = "authCode";
-    private static final String USERID = "userId";
-    private static final String TIMESTAMP = "timestamp";
-    private static final String SIGNATURE = "signature";
-    private static final String STATE = "state";
-    private static final String ACCESSTOKEN_URL = "https://u.baidu.com/oauth/accessToken";
-
-    @Autowired
-    private IBdApiService bdApiService; // 开发者自定义
-    @Autowired
-    private SignService signService; // 开发者可自定义
-
-    @GetMapping("/callback")
-    public String mockApp(HttpServletRequest request) throws BasePayException {
-
-        // 获取请求参数
-        Map<String, String> params = new HashMap<>();
-        this.fillParams(params, request);
-        log.info("callback: params = {}", JSONObject.valueToString(params));
-        int userIdInt = 0;
-        try {
-            userIdInt = Integer.parseInt(params.get(USERID));
-        } catch (Exception e) {
-            return this.getResponseJson(600011, "参数错误", new Object());
-        }
-        // 对签名内容进行判空
-        if (StringUtils.isBlank(params.get(SIGNATURE))) {
-            return this.getResponseJson(600011, "参数错误", new Object());
-        }
-
-        // 获取应用对应的密钥
-        BdApi app = bdApiService.getAppByAppId(params.get(APPID));
-        String sk = app.getAppSecretKey();
-        // 开发者进行验签
-        // 检查状态码
-//        if (!this.checkState(params.get(APPID), app.getAppUserId(), params.get(STATE))) {
-//            log.info("callback: state check fail");
-//            return this.getResponseJson(600011, "状态码错误", new Object());
-//        }
-
-        // 签名验证
-        if (!this.checkSignature(params, sk)) {
-            log.info("callback: signature check fail");
-            return this.getResponseJson(600011, "签名错误", new Object());
-        }
-
-        // 调用接口换取授权令牌
-        String response = this.getAccessToken(params, sk, userIdInt);
-        log.info("callback:getAccesstoken, response={}", response);
-        String accessToken = null;
-        String refreshToken = null;
-        int uid;
-
-        if (response.length() > 0) {
-            JSONObject res = new JSONObject(response);
-            int code = (int) res.get("code");
-            if (code == 0) {
-                JSONObject data = res.getJSONObject("data");
-                accessToken = (String) data.get("accessToken");
-                // 注释部分为 accessToken 其他信息,各应用开发者酌情使用即可
-                 refreshToken = (String) data.get("refreshToken");
-                String openId = data.getString("openId");
-                int expiresIn = data.getInt("expiresIn");
-                int refreshExpiresIn = data.getInt("refreshExpiresIn");
-                app.setAccessToken(accessToken);
-                app.setRefreshToken(refreshToken);
-                app.setExpiresIn(expiresIn);
-                app.setOpenId(openId);
-                app.setRefreshExpiresIn(refreshExpiresIn);
-                app.setAuthCode(params.get(AUTH_CODE));
-                bdApiService.updateById(app);
-
-                // TODO 相关信息落库处理
-            } else {
-                return this.getResponseJson(600011, "未获取到 access_token", new Object());
-            }
-        }
-        Map<String, String> data = new HashMap<>();
-        data.put("accessToken", accessToken);
-        return this.getResponseJson(0, "success", data);
-    }
-
-    /**
-     * 填充请求参数,开发者可用实体代替map
-     *
-     * @param params
-     * @param request
-     */
-    private void fillParams(Map<String, String> params, HttpServletRequest request) {
-        params.put(APPID, request.getParameter(APPID));
-        params.put(AUTH_CODE, request.getParameter(AUTH_CODE));
-        params.put(USERID, request.getParameter(USERID));
-        params.put(TIMESTAMP, request.getParameter(TIMESTAMP));
-        params.put(SIGNATURE, request.getParameter(SIGNATURE));
-        params.put(STATE, request.getParameter(STATE));
-    }
-
-    /**
-     * 校验状态码是否符合预期
-     *
-     * @param appId  应用ID
-     * @param userId 创建应用的ID
-     * @param state  请求参数中的状态码
-     * @return
-     */
-    private boolean checkState(String appId, Long userId, String state) {
-        // md5util 开发者自行开发即可
-        String newState = md5(appId.concat("_").concat(String.valueOf(userId)));
-        return newState.equals(state);
-    }
-    public static String md5(String input) {
-        try {
-            MessageDigest md = MessageDigest.getInstance("MD5");
-            byte[] messageDigest = md.digest(input.getBytes());
-            StringBuilder hexString = new StringBuilder();
-            for (byte b : messageDigest) {
-                String hex = Integer.toHexString(0xff & b);
-                if (hex.length() == 1) {
-                    hexString.append('0');
-                }
-                hexString.append(hex);
-            }
-            return hexString.toString();
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException(e);
-        }
-    }
-    /**
-     * 签名验证方法
-     *
-     * @param params
-     * @param sk
-     * @return
-     */
-    private boolean checkSignature(Map<String, String> params, String sk) {
-        // 获取验签字符串:按key自然排序,拼接成 json 字符串,
-        // 示例:str1 = {"appId": xxxxx, "authCode": xxx, "state": xxx,"timestamp": xxx}
-        TreeMap<String, Object> map = new TreeMap<>();
-        map.put(APPID, params.get(APPID));
-        map.put(AUTH_CODE, params.get(AUTH_CODE));
-        map.put(USERID, params.get(USERID));
-        map.put(STATE, params.get(STATE));
-        map.put(TIMESTAMP, params.get(TIMESTAMP));
-        // 根据上述签名算法对接收到的参数签名
-        String sign = signService.paramsSign(sk, map);
-        log.info("callback: signature = {}", sign);
-        // 判断签名和URL传参签名是否一致
-        return params.get(SIGNATURE).equals(sign);
-    }
-
-    /**
-     * 换取授权令牌
-     *
-     * @param params
-     * @param sk
-     * @param userIdInt 授权账户ID
-     * @return
-     */
-    private String getAccessToken(Map<String, String> params, String sk, int userIdInt) throws BasePayException {
-        Map<String, Object> requestMap = new HashMap<>();
-        requestMap.put(APPID, params.get(APPID));
-        requestMap.put("secretKey", sk);
-        requestMap.put(AUTH_CODE, params.get(AUTH_CODE));
-        requestMap.put("grantType", "access_token");
-        requestMap.put("userId", userIdInt);
-
-        String paramsJson = JSONObject.valueToString(requestMap);
-        // 开发者自行增加异常判断
-        return HttpClientUtils.httpPostJson(ACCESSTOKEN_URL, new HashMap<>(), paramsJson);
-    }
-
-    /**
-     * 封装返回json串
-     *
-     * @param code
-     * @param message
-     * @param data
-     * @return
-     */
-    private String getResponseJson(int code, String message, Object data) {
-        // 封装返回字段的map
-        Map<String, Object> responseMap = new HashMap<>();
-        responseMap.put("code", code);
-        responseMap.put("message", message);
-        responseMap.put("data", data);
-        return JSONObject.valueToString(responseMap);
-    }
-}

+ 0 - 46
fs-ad-new-api/src/main/java/com/fs/app/controller/TestController.java

@@ -1,46 +0,0 @@
-package com.fs.app.controller;
-
-import com.fs.newAdv.dto.req.TraceIdDto;
-import com.fs.newAdv.integration.client.advertiser.BaiduApiClient;
-import com.fs.newAdv.enums.SystemEventTypeEnum;
-import com.fs.newAdv.event.ConversionEventPublisher;
-import com.fs.newAdv.service.IPromotionAccountService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-
-/**
- * 广告商监测链接
- *
- * @author zhangqin
- */
-@Slf4j
-@RestController
-@RequestMapping("/test")
-public class TestController {
-
-    @Autowired
-    private ConversionEventPublisher conversionEventPublisher;
-    @Autowired
-    private BaiduApiClient baiduApiClient;
-    @Autowired
-    private IPromotionAccountService promotionAccountService;
-
-    @PostMapping("/test1")
-    public void test1(@RequestBody TraceIdDto traceId) {
-        log.info("模拟 当日加群 事件完成");
-        conversionEventPublisher.publishConversionEvent(traceId.getTraceId(), SystemEventTypeEnum.GROUP_TODAY);
-    }
-
-    @PostMapping("/test2")
-    public void test2(@RequestBody TraceIdDto traceId) {
-        log.info("模拟 当日加微 事件完成");
-        conversionEventPublisher.publishConversionEvent(traceId.getTraceId(), SystemEventTypeEnum.WEI_CHAT_TODAY);
-    }
-
-    @PostMapping("/test3")
-    public void test3(@RequestBody TraceIdDto traceId) {
-        log.info("模拟 微信授权 事件完成");
-        conversionEventPublisher.publishConversionEvent(traceId.getTraceId(), SystemEventTypeEnum.AUTH_TODAY_CREATE);
-    }
-}

+ 34 - 1
fs-admin/pom.xml

@@ -42,6 +42,12 @@
         <dependency>
             <groupId>com.fs</groupId>
             <artifactId>fs-framework</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>javax.annotation</groupId>
+                    <artifactId>annotations-api</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
 
 
@@ -51,6 +57,12 @@
             <groupId>com.fs</groupId>
             <artifactId>fs-quartz</artifactId>
         </dependency>
+        <!-- lombok -->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>1.18.32</version>
+        </dependency>
 
         <!-- 代码生成-->
         <dependency>
@@ -82,6 +94,21 @@
             <artifactId>tencentcloud-sdk-java</artifactId>
             <version>3.1.322</version>
             <scope>compile</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.squareup.okio</groupId>
+                    <artifactId>okio</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.squareup.okhttp</groupId>
+                    <artifactId>okhttp</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.squareup.okio</groupId>
+            <artifactId>okio</artifactId>
+            <version>2.10.0</version>
         </dependency>
         <!-- https://mvnrepository.com/artifact/com.qcloud/qcloud-java-sdk -->
         <dependency>
@@ -106,9 +133,15 @@
             <plugin>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-maven-plugin</artifactId>
-                <version>2.1.1.RELEASE</version>
+                <version>2.7.18</version>
                 <configuration>
                     <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
+                    <excludes>
+                        <exclude>
+                            <groupId>org.apache.tomcat</groupId>
+                            <artifactId>annotations-api</artifactId>
+                        </exclude>
+                    </excludes>
                 </configuration>
                 <executions>
                     <execution>

+ 0 - 78
fs-admin/src/main/java/com/fs/ad/controller/AdCallbackController.java

@@ -1,78 +0,0 @@
-package com.fs.ad.controller;//package com.fs.ad.controller;
-//
-//import com.alibaba.fastjson.JSON;
-//import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-//import com.fs.ad.domain.AdHtmlUrl;
-//import com.fs.ad.mapper.AdHtmlUrlMapper;
-//import com.fs.ad.service.IAdHtmlClickLogService;
-//import com.fs.ad.yk.utils.ApiUtils;
-//import com.fs.ad.yk.vo.DataBackVo;
-//import com.fs.baidu.api.BaiduApis;
-//import com.fs.baidu.api.ConvertData;
-//import com.fs.baidu.vo.AdClickCallbackVo;
-//import com.fs.common.core.controller.BaseController;
-//import com.fs.common.core.domain.R;
-//import com.fs.common.utils.StringUtils;
-//import lombok.AllArgsConstructor;
-//import lombok.extern.slf4j.Slf4j;
-//import org.springframework.web.bind.annotation.*;
-//
-///**
-// * 知识库Controller
-// *
-// * @author fs
-// * @date 2024-04-21
-// */
-//@Slf4j
-//@AllArgsConstructor
-//@RestController
-//@RequestMapping("/baidu")
-//public class AdCallbackController extends BaseController {
-//
-//    private final AdHtmlUrlMapper adHtmlUrlMapper;
-//    private final IAdHtmlClickLogService adHtmlClickLogService;
-//    private final BaiduApis baiduApis;
-//
-//    //百度-页面点击接口
-//    @GetMapping("/callback")
-//    public R callback(String url, String no, String bdVid, String t) {
-//        if(StringUtils.isEmpty(no) || StringUtils.isEmpty(bdVid)) {
-//            return R.ok();
-//        }
-//        adHtmlClickLogService.addLog(url, no, bdVid, t, 0);
-//        Runnable runnable = () -> ConvertData.uploadConvertData(url, Integer.parseInt(t));
-//        runnable.run();
-//        return R.ok();
-//    }
-//    // 百度点击监听返回接口
-//    @GetMapping("/clickCallback")
-//    public R clickCallback(AdClickCallbackVo vo){
-//        log.info("百度监听地址返回数据:{}", JSON.toJSONString(vo));
-//        adHtmlClickLogService.setLog(vo, "67", 0);
-//        return R.ok();
-//    }
-//    @GetMapping("/getTemplate")
-//    public R getTemplate(String no){
-//        AdHtmlUrl htmlUrl = adHtmlUrlMapper.selectOne(new QueryWrapper<AdHtmlUrl>().eq("no", no));
-//        if(htmlUrl == null){
-//            return R.error("错误编号");
-//        }
-//        return R.ok().put("images", htmlUrl.getImages().split(",")).put("json", StringUtils.isNotEmpty(htmlUrl.getDataJson()) ? JSON.parseObject(htmlUrl.getDataJson()) : null);
-//    }
-//    @GetMapping("/syncPlan")
-//    public R syncPlan(){
-//        baiduApis.listAccount(1L);
-//        return R.ok();
-//    }
-//
-//
-//    @GetMapping("/youkuClickCallback")
-//    public R youkuClickCallback(AdClickCallbackVo vo){
-//        log.info("优酷监听地址返回数据:{}", JSON.toJSONString(vo));
-//        adHtmlClickLogService.setLog(vo, "wechat", 1);
-////        ApiUtils.dataBack(DataBackVo.builder().trackId(vo.getBd_vid()).creativeId(vo.getAid()).build());
-//        return R.ok();
-//    }
-//
-//
-//}

+ 3 - 2
fs-admin/src/main/java/com/fs/ad/controller/MockAppController.java

@@ -5,7 +5,8 @@ import com.fs.baidu.service.IBdApiService;
 import com.fs.baidu.utils.SignService;
 import com.fs.huifuPay.sdk.opps.core.exception.BasePayException;
 import com.fs.huifuPay.sdk.opps.core.utils.HttpClientUtils;
-import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.apache.commons.lang3.StringUtils;
 import org.json.JSONObject;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -20,10 +21,10 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.TreeMap;
 
-@Slf4j
 @RestController
 @RequestMapping("/baiduBack")
 public class MockAppController {
+    private static final Logger log = LoggerFactory.getLogger(MockAppController.class);
     private static final String APPID = "appId";
     private static final String AUTH_CODE = "authCode";
     private static final String USERID = "userId";

+ 3 - 2
fs-admin/src/main/java/com/fs/ad/controller/task/BaiduTask.java

@@ -1,14 +1,15 @@
 package com.fs.ad.controller.task;
 
 import com.fs.qw.service.IQwWorkUserService;
-import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
-@Slf4j
 @Component("baiduTask")
 public class BaiduTask {
+    private static final Logger log = LoggerFactory.getLogger(BaiduTask.class);
 
     @Autowired
     private IQwWorkUserService qwWorkUserService;

+ 71 - 0
fs-admin/src/main/java/com/fs/admin/controller/AdminAdController.java

@@ -0,0 +1,71 @@
+package com.fs.admin.controller;
+
+import java.util.*;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.DataSourceType;
+import com.fs.framework.datasource.DynamicDataSourceContextHolder;
+import com.fs.framework.datasource.TenantDataSourceManager;
+import com.fs.tenant.domain.TenantInfo;
+import com.fs.tenant.service.TenantInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/admin/ad")
+public class AdminAdController extends BaseController {
+
+    @Autowired
+    private TenantDataSourceManager tenantDataSourceManager;
+
+    @Autowired
+    private TenantInfoService tenantInfoService;
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @PreAuthorize("@ss.hasPermi('admin:ad:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(@RequestParam(required = false) String accountName,
+                              @RequestParam(required = false) String tenantCode) {
+        List<Map<String, Object>> allList = new ArrayList<>();
+
+        try {
+            DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
+            List<TenantInfo> tenants = tenantInfoService.selectTenantInfoList(new TenantInfo());
+            if (tenantCode != null && !tenantCode.isEmpty()) {
+                tenants.removeIf(t -> !t.getTenantCode().equals(tenantCode));
+            }
+
+            for (TenantInfo tenant : tenants) {
+                if (tenant.getStatus() == null || tenant.getStatus() != 1) continue;
+                try {
+                    tenantDataSourceManager.switchTenant(tenant);
+                    String tenantLabel = tenant.getTenantCode() + "|" + tenant.getTenantName();
+                    String sql = "SELECT *, ? AS tenant_label FROM ad_account WHERE 1=1";
+                    if (accountName != null && !accountName.isEmpty()) {
+                        sql += " AND account_name LIKE ?";
+                    }
+                    sql += " ORDER BY create_time DESC LIMIT 50";
+                    if (accountName != null && !accountName.isEmpty()) {
+                        allList.addAll(jdbcTemplate.queryForList(sql, tenantLabel, "%" + accountName + "%"));
+                    } else {
+                        allList.addAll(jdbcTemplate.queryForList(sql, tenantLabel));
+                    }
+                } catch (Exception e) {
+                    // skip tenant
+                } finally {
+                    tenantDataSourceManager.clear();
+                    DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
+                }
+            }
+        } catch (Exception e) {
+            // ignore
+        }
+
+        return getDataTable(allList);
+    }
+}

+ 75 - 0
fs-admin/src/main/java/com/fs/admin/controller/AdminCrmController.java

@@ -0,0 +1,75 @@
+package com.fs.admin.controller;
+
+import java.util.*;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.DataSourceType;
+import com.fs.framework.datasource.DynamicDataSourceContextHolder;
+import com.fs.framework.datasource.TenantDataSourceManager;
+import com.fs.tenant.domain.TenantInfo;
+import com.fs.tenant.service.TenantInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/admin/crm")
+public class AdminCrmController extends BaseController {
+
+    @Autowired
+    private TenantDataSourceManager tenantDataSourceManager;
+
+    @Autowired
+    private TenantInfoService tenantInfoService;
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @PreAuthorize("@ss.hasPermi('admin:crm:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(@RequestParam(required = false) String customerName,
+                              @RequestParam(required = false) String tenantCode) {
+        List<Map<String, Object>> allList = new ArrayList<>();
+
+        try {
+            DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
+            List<TenantInfo> tenants = tenantInfoService.selectTenantInfoList(new TenantInfo());
+            if (tenantCode != null && !tenantCode.isEmpty()) {
+                tenants.removeIf(t -> !t.getTenantCode().equals(tenantCode));
+            }
+
+            for (TenantInfo tenant : tenants) {
+                if (tenant.getStatus() == null || tenant.getStatus() != 1) continue;
+                try {
+                    tenantDataSourceManager.switchTenant(tenant);
+                    StringBuilder sql = new StringBuilder(
+                        "SELECT c.*, t.tenant_code, t.tenant_name FROM crm_customer c " +
+                        "CROSS JOIN (SELECT ? AS tenant_code, ? AS tenant_name) t WHERE 1=1");
+                    if (customerName != null && !customerName.isEmpty()) {
+                        sql.append(" AND c.customer_name LIKE ?");
+                    }
+                    sql.append(" LIMIT 100");
+                    if (customerName != null && !customerName.isEmpty()) {
+                        allList.addAll(jdbcTemplate.queryForList(sql.toString(),
+                            tenant.getTenantCode(), tenant.getTenantName(), "%" + customerName + "%"));
+                    } else {
+                        allList.addAll(jdbcTemplate.queryForList(sql.toString(),
+                            tenant.getTenantCode(), tenant.getTenantName()));
+                    }
+                } catch (Exception e) {
+                    // skip tenant
+                } finally {
+                    tenantDataSourceManager.clear();
+                    DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
+                }
+            }
+        } catch (Exception e) {
+            // ignore
+        }
+
+        return getDataTable(allList);
+    }
+}

+ 84 - 0
fs-admin/src/main/java/com/fs/admin/controller/AdminModuleUsageController.java

@@ -0,0 +1,84 @@
+package com.fs.admin.controller;
+
+import java.util.List;
+import java.util.Map;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.proxy.domain.TenantModuleUsage;
+import com.fs.proxy.service.TenantModuleUsageService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * Admin总后台-租户模块使用统计控制器
+ * 总后台可查看所有代理下所有租户的模块使用详情
+ * 支持按代理维度、租户维度筛选
+ */
+@RestController
+@RequestMapping("/admin/module-usage")
+public class AdminModuleUsageController extends BaseController {
+
+    @Autowired
+    private TenantModuleUsageService tenantModuleUsageService;
+
+    /**
+     * 查询所有租户模块使用统计列表
+     * 支持按代理ID、租户名称、日期范围筛选
+     */
+    @PreAuthorize("@ss.hasPermi('admin:moduleUsage:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(TenantModuleUsage query) {
+        startPage();
+        List<TenantModuleUsage> list = tenantModuleUsageService.selectTenantModuleUsageList(query);
+        return getDataTable(list);
+    }
+
+    /**
+     * 按代理维度查看模块使用详情
+     * 返回:指定代理下所有租户的模块使用情况
+     */
+    @PreAuthorize("@ss.hasPermi('admin:moduleUsage:list')")
+    @GetMapping("/proxy/{proxyId}")
+    public AjaxResult proxyDetail(@PathVariable Long proxyId,
+                                  @RequestParam(required = false) String statDate) {
+        Map<String, Object> data = tenantModuleUsageService.getModuleUsageDetail(proxyId, statDate);
+        return AjaxResult.success(data);
+    }
+
+    /**
+     * 查询指定租户的最新统计详情
+     */
+    @PreAuthorize("@ss.hasPermi('admin:moduleUsage:list')")
+    @GetMapping("/tenant/{tenantId}")
+    public AjaxResult tenantDetail(@PathVariable Long tenantId) {
+        TenantModuleUsage usage = tenantModuleUsageService.selectLatestByTenantId(tenantId);
+        return AjaxResult.success(usage);
+    }
+
+    /**
+     * 手动触发全量统计汇总
+     */
+    @PreAuthorize("@ss.hasPermi('admin:moduleUsage:refresh')")
+    @Log(title = "租户模块使用统计", businessType = BusinessType.INSERT)
+    @PostMapping("/refresh")
+    public AjaxResult refreshStatistics() {
+        tenantModuleUsageService.executeDailyStatistics();
+        return AjaxResult.success("全量统计任务已触发");
+    }
+
+    /**
+     * 手动触发指定租户的统计汇总
+     */
+    @PreAuthorize("@ss.hasPermi('admin:moduleUsage:refresh')")
+    @Log(title = "租户模块使用统计", businessType = BusinessType.INSERT)
+    @PostMapping("/refresh/{tenantId}")
+    public AjaxResult refreshTenantStatistics(@PathVariable Long tenantId) {
+        tenantModuleUsageService.statisticsForTenant(tenantId);
+        return AjaxResult.success("租户" + tenantId + "统计已刷新");
+    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/admin/controller/AdminProxyController.java

@@ -0,0 +1,103 @@
+package com.fs.admin.controller;
+
+import java.util.List;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.proxy.domain.Proxy;
+import com.fs.proxy.service.ProxyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 总后台-代理管理控制器
+ * 
+ * @author fs
+ * @date 2024-01-01
+ */
+@RestController
+@RequestMapping("/admin/proxy")
+public class AdminProxyController extends BaseController
+{
+    @Autowired
+    private ProxyService proxyService;
+
+    /**
+     * 查询代理列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:proxy:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(Proxy proxy) {
+        startPage();
+        List<Proxy> list = proxyService.selectProxyList(proxy);
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取代理详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('admin:proxy:query')")
+    @GetMapping(value = "/{proxyId}")
+    public AjaxResult getInfo(@PathVariable("proxyId") Long proxyId) {
+        return AjaxResult.success(proxyService.selectProxyById(proxyId));
+    }
+
+    /**
+     * 新增代理
+     */
+    @PreAuthorize("@ss.hasPermi('admin:proxy:add')")
+    @Log(title = "代理管理", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody Proxy proxy) {
+        return toAjax(proxyService.insertProxy(proxy));
+    }
+
+    /**
+     * 修改代理
+     */
+    @PreAuthorize("@ss.hasPermi('admin:proxy:edit')")
+    @Log(title = "代理管理", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody Proxy proxy) {
+        return toAjax(proxyService.updateProxy(proxy));
+    }
+
+    /**
+     * 删除代理
+     */
+    @PreAuthorize("@ss.hasPermi('admin:proxy:remove')")
+    @Log(title = "代理管理", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{proxyIds}")
+    public AjaxResult remove(@PathVariable Long[] proxyIds) {
+        return toAjax(proxyService.deleteProxyByIds(proxyIds));
+    }
+
+    /**
+     * 启用/禁用代理
+     */
+    @PreAuthorize("@ss.hasPermi('admin:proxy:edit')")
+    @Log(title = "代理管理", businessType = BusinessType.UPDATE)
+    @PutMapping("/changeStatus/{proxyId}")
+    public AjaxResult changeStatus(@PathVariable Long proxyId, @RequestParam Integer status) {
+        Proxy proxy = new Proxy();
+        proxy.setProxyId(proxyId);
+        proxy.setStatus(status);
+        return toAjax(proxyService.updateProxy(proxy));
+    }
+
+    /**
+     * 获取所有启用的代理(下拉列表用)
+     */
+    @PreAuthorize("@ss.hasPermi('admin:proxy:query')")
+    @GetMapping("/allEnabled")
+    public AjaxResult allEnabled() {
+        Proxy query = new Proxy();
+        query.setStatus(1);
+        List<Proxy> list = proxyService.selectProxyList(query);
+        return AjaxResult.success(list);
+    }
+}

+ 113 - 0
fs-admin/src/main/java/com/fs/admin/controller/AdminSopController.java

@@ -0,0 +1,113 @@
+package com.fs.admin.controller;
+
+import java.util.*;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.DataSourceType;
+import com.fs.framework.datasource.DynamicDataSourceContextHolder;
+import com.fs.framework.datasource.TenantDataSourceManager;
+import com.fs.tenant.domain.TenantInfo;
+import com.fs.tenant.service.TenantInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/admin/sop")
+public class AdminSopController extends BaseController {
+
+    @Autowired
+    private TenantDataSourceManager tenantDataSourceManager;
+
+    @Autowired
+    private TenantInfoService tenantInfoService;
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @PreAuthorize("@ss.hasPermi('admin:sop:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(@RequestParam(required = false) String sopName,
+                              @RequestParam(required = false) String tenantCode) {
+        List<Map<String, Object>> allList = new ArrayList<>();
+
+        try {
+            DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
+            List<TenantInfo> tenants = tenantInfoService.selectTenantInfoList(new TenantInfo());
+            if (tenantCode != null && !tenantCode.isEmpty()) {
+                tenants.removeIf(t -> !t.getTenantCode().equals(tenantCode));
+            }
+
+            for (TenantInfo tenant : tenants) {
+                if (tenant.getStatus() == null || tenant.getStatus() != 1) continue;
+                try {
+                    tenantDataSourceManager.switchTenant(tenant);
+                    String tenantLabel = tenant.getTenantCode() + "|" + tenant.getTenantName();
+                    String sql = "SELECT qs.*, ? AS tenant_label FROM qw_sop qs WHERE 1=1";
+                    if (sopName != null && !sopName.isEmpty()) {
+                        sql += " AND qs.name LIKE ?";
+                    }
+                    sql += " ORDER BY qs.create_time DESC LIMIT 50";
+                    if (sopName != null && !sopName.isEmpty()) {
+                        allList.addAll(jdbcTemplate.queryForList(sql, tenantLabel, "%" + sopName + "%"));
+                    } else {
+                        allList.addAll(jdbcTemplate.queryForList(sql, tenantLabel));
+                    }
+                } catch (Exception e) {
+                    // skip tenant
+                } finally {
+                    tenantDataSourceManager.clear();
+                    DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
+                }
+            }
+        } catch (Exception e) {
+            // ignore
+        }
+
+        return getDataTable(allList);
+    }
+
+    @PreAuthorize("@ss.hasPermi('admin:sop:list')")
+    @GetMapping("/temp/list")
+    public TableDataInfo tempList(@RequestParam(required = false) String tempName,
+                                   @RequestParam(required = false) String tenantCode) {
+        List<Map<String, Object>> allList = new ArrayList<>();
+
+        try {
+            DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
+            List<TenantInfo> tenants = tenantInfoService.selectTenantInfoList(new TenantInfo());
+            if (tenantCode != null && !tenantCode.isEmpty()) {
+                tenants.removeIf(t -> !t.getTenantCode().equals(tenantCode));
+            }
+
+            for (TenantInfo tenant : tenants) {
+                if (tenant.getStatus() == null || tenant.getStatus() != 1) continue;
+                try {
+                    tenantDataSourceManager.switchTenant(tenant);
+                    String tenantLabel = tenant.getTenantCode() + "|" + tenant.getTenantName();
+                    String sql = "SELECT *, ? AS tenant_label FROM qw_sop_temp WHERE 1=1";
+                    if (tempName != null && !tempName.isEmpty()) {
+                        sql += " AND name LIKE ?";
+                    }
+                    sql += " ORDER BY create_time DESC LIMIT 50";
+                    if (tempName != null && !tempName.isEmpty()) {
+                        allList.addAll(jdbcTemplate.queryForList(sql, tenantLabel, "%" + tempName + "%"));
+                    } else {
+                        allList.addAll(jdbcTemplate.queryForList(sql, tenantLabel));
+                    }
+                } catch (Exception e) {
+                    // skip tenant
+                } finally {
+                    tenantDataSourceManager.clear();
+                    DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
+                }
+            }
+        } catch (Exception e) {
+            // ignore
+        }
+
+        return getDataTable(allList);
+    }
+}

+ 262 - 0
fs-admin/src/main/java/com/fs/admin/controller/AdminStatisticsController.java

@@ -0,0 +1,262 @@
+package com.fs.admin.controller;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.proxy.domain.PlatformStatistics;
+import com.fs.proxy.domain.ProxyServicePrice;
+import com.fs.proxy.domain.ProxyTenantRel;
+import com.fs.proxy.domain.TenantConsumeRecord;
+import com.fs.proxy.service.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 总后台统计控制器(统一使用 platform_statistics 表)
+ * 
+ * @author fs
+ * @date 2024-01-01
+ */
+@RestController
+@RequestMapping("/admin/statistics")
+public class AdminStatisticsController extends BaseController
+{
+    @Autowired
+    private ProxyTenantRelService proxyTenantRelService;
+
+    @Autowired
+    private TenantConsumeService tenantConsumeService;
+
+    @Autowired
+    private ProxyServicePriceService proxyServicePriceService;
+
+    @Autowired
+    private PlatformStatisticsService platformStatisticsService;
+
+    /**
+     * 获取平台总览统计
+     */
+    @PreAuthorize("@ss.hasPermi('admin:statistics:overview')")
+    @GetMapping("/overview")
+    public AjaxResult getOverview() {
+        Map<String, Object> result = new HashMap<>();
+        
+        List<ProxyTenantRel> allRelations = proxyTenantRelService.selectProxyTenantRelList(null);
+        result.put("totalTenantCount", allRelations.size());
+        
+        long proxyCount = allRelations.stream().map(ProxyTenantRel::getProxyId).distinct().count();
+        result.put("totalProxyCount", proxyCount);
+        
+        Date today = new java.sql.Date(System.currentTimeMillis());
+        List<PlatformStatistics> todayStats = platformStatisticsService.getHourlyStats(today, null);
+        BigDecimal todayConsume = todayStats.stream()
+            .map(s -> s.getConsumeAmount() != null ? s.getConsumeAmount() : BigDecimal.ZERO)
+            .reduce(BigDecimal.ZERO, BigDecimal::add);
+        BigDecimal todayProfit = todayStats.stream()
+            .map(s -> s.getProxyProfit() != null ? s.getProxyProfit() : BigDecimal.ZERO)
+            .reduce(BigDecimal.ZERO, BigDecimal::add);
+        result.put("todayConsume", todayConsume);
+        result.put("todayProfit", todayProfit);
+        
+        // 成本配置数
+        List<ProxyServicePrice> priceList = proxyServicePriceService.selectProxyServicePriceList(null);
+        result.put("serviceTypeCount", priceList.size());
+        
+        return AjaxResult.success(result);
+    }
+
+    /**
+     * 获取代理分佣统计
+     */
+    @PreAuthorize("@ss.hasPermi('admin:statistics:proxyProfit')")
+    @GetMapping("/proxyProfit")
+    public TableDataInfo getProxyProfitStatistics(@RequestParam(required = false) String startDate,
+                                                  @RequestParam(required = false) String endDate) {
+        Date start = startDate != null ? java.sql.Date.valueOf(startDate) : null;
+        Date end = endDate != null ? java.sql.Date.valueOf(endDate) : null;
+        List<PlatformStatistics> stats = platformStatisticsService.getProxyProfitStats(start, end);
+        return getDataTable(stats);
+    }
+
+    /**
+     * 获取租户消费统计
+     */
+    @PreAuthorize("@ss.hasPermi('admin:statistics:tenantConsume')")
+    @GetMapping("/tenantConsume")
+    public TableDataInfo getTenantConsumeStatistics(@RequestParam(required = false) String startDate,
+                                                     @RequestParam(required = false) String endDate) {
+        Date start = startDate != null ? java.sql.Date.valueOf(startDate) : null;
+        Date end = endDate != null ? java.sql.Date.valueOf(endDate) : null;
+        List<PlatformStatistics> stats = platformStatisticsService.getTenantConsumeStats(start, end);
+        return getDataTable(stats);
+    }
+
+    /**
+     * 获取消费类型统计
+     */
+    @PreAuthorize("@ss.hasPermi('admin:statistics:consumeType')")
+    @GetMapping("/consumeType")
+    public AjaxResult getConsumeTypeStatistics(@RequestParam(required = false) String startDate,
+                                               @RequestParam(required = false) String endDate) {
+        Date start = startDate != null ? java.sql.Date.valueOf(startDate) : null;
+        Date end = endDate != null ? java.sql.Date.valueOf(endDate) : null;
+        List<PlatformStatistics> stats = platformStatisticsService.getConsumeTypeStats(start, end);
+        
+        Map<String, Object> result = new HashMap<>();
+        Map<String, BigDecimal> consume = new HashMap<>();
+        Map<String, BigDecimal> cost = new HashMap<>();
+        Map<String, BigDecimal> profit = new HashMap<>();
+        for (PlatformStatistics s : stats) {
+            String t = s.getConsumeType() != null ? s.getConsumeType() : "未知";
+            consume.put(t, s.getConsumeAmount());
+            cost.put(t, s.getPlatformCost());
+            profit.put(t, s.getProxyProfit());
+        }
+        result.put("consumeByType", consume);
+        result.put("costByType", cost);
+        result.put("profitByType", profit);
+        return AjaxResult.success(result);
+    }
+
+    /**
+     * 获取平台成本汇总
+     */
+    @PreAuthorize("@ss.hasPermi('admin:statistics:costSummary')")
+    @GetMapping("/costSummary")
+    public AjaxResult getCostSummary(@RequestParam(required = false) String startDate,
+                                     @RequestParam(required = false) String endDate) {
+        Date start = startDate != null ? java.sql.Date.valueOf(startDate) : null;
+        Date end = endDate != null ? java.sql.Date.valueOf(endDate) : null;
+        
+        List<PlatformStatistics> typeStats = platformStatisticsService.getConsumeTypeStats(start, end);
+        List<PlatformStatistics> proxyStats = platformStatisticsService.getProxyProfitStats(start, end);
+
+        BigDecimal totalCost = typeStats.stream()
+            .map(s -> s.getPlatformCost() != null ? s.getPlatformCost() : BigDecimal.ZERO)
+            .reduce(BigDecimal.ZERO, BigDecimal::add);
+        BigDecimal totalConsume = typeStats.stream()
+            .map(s -> s.getConsumeAmount() != null ? s.getConsumeAmount() : BigDecimal.ZERO)
+            .reduce(BigDecimal.ZERO, BigDecimal::add);
+        BigDecimal totalProfit = proxyStats.stream()
+            .map(s -> s.getProxyProfit() != null ? s.getProxyProfit() : BigDecimal.ZERO)
+            .reduce(BigDecimal.ZERO, BigDecimal::add);
+        
+        Map<String, Object> result = new HashMap<>();
+        result.put("totalCost", totalCost);
+        result.put("totalConsume", totalConsume);
+        result.put("totalProfit", totalProfit);
+        result.put("platformRevenue", totalConsume.subtract(totalCost).subtract(totalProfit));
+        return AjaxResult.success(result);
+    }
+
+    /**
+     * 获取代理分佣详情
+     */
+    @PreAuthorize("@ss.hasPermi('admin:statistics:proxyProfit')")
+    @GetMapping("/proxyProfit/{proxyId}")
+    public AjaxResult getProxyProfitDetail(@PathVariable Long proxyId,
+                                           @RequestParam(required = false) String startDate,
+                                           @RequestParam(required = false) String endDate) {
+        Date start = startDate != null ? java.sql.Date.valueOf(startDate) : null;
+        Date end = endDate != null ? java.sql.Date.valueOf(endDate) : null;
+        
+        Map<String, Object> result = new HashMap<>();
+        List<ProxyTenantRel> tenantList = proxyTenantRelService.selectProxyTenantRelByProxyId(proxyId);
+        result.put("tenantList", tenantList);
+        
+        List<PlatformStatistics> detail = platformStatisticsService.getProxyDetail(proxyId, start, end);
+        BigDecimal total = detail.stream()
+            .map(s -> s.getProxyProfit() != null ? s.getProxyProfit() : BigDecimal.ZERO)
+            .reduce(BigDecimal.ZERO, BigDecimal::add);
+        result.put("totalProfit", total);
+        result.put("details", detail);
+        return AjaxResult.success(result);
+    }
+
+    /**
+     * 获取租户消费详情
+     */
+    @PreAuthorize("@ss.hasPermi('admin:statistics:tenantConsume')")
+    @GetMapping("/tenantDetail/{tenantId}")
+    public AjaxResult getTenantDetail(@PathVariable Long tenantId,
+                                      @RequestParam(required = false) String startDate,
+                                      @RequestParam(required = false) String endDate) {
+        Date start = startDate != null ? java.sql.Date.valueOf(startDate) : null;
+        Date end = endDate != null ? java.sql.Date.valueOf(endDate) : null;
+        List<PlatformStatistics> detail = platformStatisticsService.getTenantDetail(tenantId, start, end);
+        return AjaxResult.success(detail);
+    }
+
+    /**
+     * 获取平台趋势
+     */
+    @PreAuthorize("@ss.hasPermi('admin:statistics:trend')")
+    @GetMapping("/trend")
+    public AjaxResult getPlatformTrend(@RequestParam(required = false) String startDate,
+                                       @RequestParam(required = false) String endDate) {
+        Date start = startDate != null ? java.sql.Date.valueOf(startDate) : null;
+        Date end = endDate != null ? java.sql.Date.valueOf(endDate) : null;
+        List<PlatformStatistics> trend = platformStatisticsService.getTrend(start, end);
+        return AjaxResult.success(trend);
+    }
+
+    /**
+     * 获取小时统计
+     */
+    @PreAuthorize("@ss.hasPermi('admin:statistics:hourly')")
+    @GetMapping("/hourly")
+    public AjaxResult getHourlyStatistics(@RequestParam(required = false) String statDate,
+                                          @RequestParam(required = false) String dimension) {
+        if (statDate == null || statDate.isEmpty()) {
+            statDate = java.time.LocalDate.now().toString();
+        }
+        Date date = java.sql.Date.valueOf(statDate);
+        List<PlatformStatistics> stats = platformStatisticsService.getHourlyStats(date, dimension);
+        return AjaxResult.success(stats);
+    }
+
+    /**
+     * 获取服务成本配置
+     */
+    @PreAuthorize("@ss.hasPermi('admin:statistics:costConfig')")
+    @GetMapping("/costConfig")
+    public AjaxResult getCostConfigList() {
+        return AjaxResult.success(proxyServicePriceService.selectProxyServicePriceList(null));
+    }
+
+    /**
+     * 获取原始消费记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:statistics:tenantConsume')")
+    @GetMapping("/consumeRecords")
+    public TableDataInfo getConsumeRecords(TenantConsumeRecord query) {
+        startPage();
+        List<TenantConsumeRecord> list = tenantConsumeService.selectTenantConsumeRecordList(query);
+        return getDataTable(list);
+    }
+
+    /**
+     * 手动执行统计
+     */
+    @PreAuthorize("@ss.hasPermi('admin:statistics:execute')")
+    @PostMapping("/execute")
+    public AjaxResult executeStatistics(@RequestParam(required = false) String type) {
+        if ("daily".equals(type)) {
+            platformStatisticsService.executeDailySummary();
+            return AjaxResult.success("日汇总执行成功");
+        } else if ("monthly".equals(type)) {
+            platformStatisticsService.executeMonthlySummary();
+            return AjaxResult.success("月汇总执行成功");
+        } else {
+            platformStatisticsService.executeHourlyStats();
+            return AjaxResult.success("小时统计执行成功");
+        }
+    }
+}

+ 71 - 0
fs-admin/src/main/java/com/fs/admin/controller/AdminStoreOrderController.java

@@ -0,0 +1,71 @@
+package com.fs.admin.controller;
+
+import java.util.*;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.DataSourceType;
+import com.fs.framework.datasource.DynamicDataSourceContextHolder;
+import com.fs.framework.datasource.TenantDataSourceManager;
+import com.fs.tenant.domain.TenantInfo;
+import com.fs.tenant.service.TenantInfoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/admin/storeOrder")
+public class AdminStoreOrderController extends BaseController {
+
+    @Autowired
+    private TenantDataSourceManager tenantDataSourceManager;
+
+    @Autowired
+    private TenantInfoService tenantInfoService;
+
+    @Autowired
+    private JdbcTemplate jdbcTemplate;
+
+    @PreAuthorize("@ss.hasPermi('admin:storeOrder:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(@RequestParam(required = false) String orderNo,
+                              @RequestParam(required = false) String tenantCode) {
+        List<Map<String, Object>> allList = new ArrayList<>();
+
+        try {
+            DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
+            List<TenantInfo> tenants = tenantInfoService.selectTenantInfoList(new TenantInfo());
+            if (tenantCode != null && !tenantCode.isEmpty()) {
+                tenants.removeIf(t -> !t.getTenantCode().equals(tenantCode));
+            }
+
+            for (TenantInfo tenant : tenants) {
+                if (tenant.getStatus() == null || tenant.getStatus() != 1) continue;
+                try {
+                    tenantDataSourceManager.switchTenant(tenant);
+                    String tenantLabel = tenant.getTenantCode() + "|" + tenant.getTenantName();
+                    String sql = "SELECT *, ? AS tenant_label FROM fs_store_order WHERE 1=1";
+                    if (orderNo != null && !orderNo.isEmpty()) {
+                        sql += " AND order_no LIKE ?";
+                    }
+                    sql += " ORDER BY create_time DESC LIMIT 50";
+                    if (orderNo != null && !orderNo.isEmpty()) {
+                        allList.addAll(jdbcTemplate.queryForList(sql, tenantLabel, "%" + orderNo + "%"));
+                    } else {
+                        allList.addAll(jdbcTemplate.queryForList(sql, tenantLabel));
+                    }
+                } catch (Exception e) {
+                    // skip tenant
+                } finally {
+                    tenantDataSourceManager.clear();
+                    DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
+                }
+            }
+        } catch (Exception e) {
+            // ignore
+        }
+
+        return getDataTable(allList);
+    }
+}

+ 95 - 0
fs-admin/src/main/java/com/fs/admin/controller/AiChatQualityController.java

@@ -0,0 +1,95 @@
+package com.fs.admin.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.fastGpt.domain.FastGptChatMsg;
+import com.fs.fastGpt.domain.FastGptChatSession;
+import com.fs.fastGpt.service.IFastGptChatMsgService;
+import com.fs.fastGpt.service.IFastGptChatSessionService;
+import com.fs.proxy.domain.AiChatQualityRecord;
+import com.fs.proxy.service.AiChatQualityService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/admin/aiChatQuality")
+public class AiChatQualityController extends BaseController {
+
+    @Autowired
+    private IFastGptChatSessionService fastGptChatSessionService;
+
+    @Autowired
+    private IFastGptChatMsgService fastGptChatMsgService;
+
+    @Autowired
+    private AiChatQualityService aiChatQualityService;
+
+    @PreAuthorize("@ss.hasPermi('admin:aiChatQuality:list')")
+    @GetMapping("/sessions")
+    public TableDataInfo listSessions(FastGptChatSession session) {
+        startPage();
+        List<FastGptChatSession> list = fastGptChatSessionService.selectFastGptChatSessionList(session);
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('admin:aiChatQuality:query')")
+    @GetMapping("/session/{sessionId}")
+    public AjaxResult getSessionDetail(@PathVariable Long sessionId) {
+        return AjaxResult.success(fastGptChatSessionService.selectFastGptChatSessionBySessionId(sessionId));
+    }
+
+    @PreAuthorize("@ss.hasPermi('admin:aiChatQuality:query')")
+    @GetMapping("/messages/{sessionId}")
+    public AjaxResult getMessages(@PathVariable Long sessionId) {
+        FastGptChatMsg query = new FastGptChatMsg();
+        query.setSessionId(sessionId);
+        List<FastGptChatMsg> messages = fastGptChatMsgService.selectFastGptChatMsgList(query);
+        return AjaxResult.success(messages);
+    }
+
+    @PreAuthorize("@ss.hasPermi('admin:aiChatQuality:list')")
+    @GetMapping("/records")
+    public TableDataInfo listRecords(AiChatQualityRecord record) {
+        startPage();
+        List<AiChatQualityRecord> list = aiChatQualityService.selectAiChatQualityRecordList(record);
+        return getDataTable(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('admin:aiChatQuality:query')")
+    @GetMapping("/record/{id}")
+    public AjaxResult getRecordInfo(@PathVariable Long id) {
+        AiChatQualityRecord record = aiChatQualityService.selectAiChatQualityRecordById(id);
+        return AjaxResult.success(record);
+    }
+
+    @PreAuthorize("@ss.hasPermi('admin:aiChatQuality:add')")
+    @PostMapping("/record")
+    public AjaxResult addRecord(@RequestBody AiChatQualityRecord record) {
+        return toAjax(aiChatQualityService.insertAiChatQualityRecord(record));
+    }
+
+    @PreAuthorize("@ss.hasPermi('admin:aiChatQuality:edit')")
+    @PutMapping("/record")
+    public AjaxResult editRecord(@RequestBody AiChatQualityRecord record) {
+        return toAjax(aiChatQualityService.updateAiChatQualityRecord(record));
+    }
+
+    @PreAuthorize("@ss.hasPermi('admin:aiChatQuality:remove')")
+    @DeleteMapping("/record/{ids}")
+    public AjaxResult removeRecords(@PathVariable Long[] ids) {
+        return toAjax(aiChatQualityService.deleteAiChatQualityRecordByIds(ids));
+    }
+
+    @PreAuthorize("@ss.hasPermi('admin:aiChatQuality:batch')")
+    @PostMapping("/batchQuality")
+    public AjaxResult batchQuality(@RequestBody List<Long> sessionIds,
+                                   @RequestParam String result,
+                                   @RequestParam(required = false) String remark) {
+        int count = aiChatQualityService.batchQuality(sessionIds, result, remark);
+        return AjaxResult.success("批量质检完成,共处理 " + count + " 条记录");
+    }
+}

+ 102 - 0
fs-admin/src/main/java/com/fs/admin/controller/AiProviderAdminController.java

@@ -0,0 +1,102 @@
+package com.fs.admin.controller;
+
+import java.util.List;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.CompanyAiProvider;
+import com.fs.company.mapper.CompanyAiProviderMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/knowledge/ai-provider")
+public class AiProviderAdminController extends BaseController
+{
+    @Autowired
+    private CompanyAiProviderMapper aiProviderMapper;
+
+    @PreAuthorize("@ss.hasPermi('admin:aiProvider:list')")
+    @GetMapping("/list")
+    public AjaxResult list()
+    {
+        List<CompanyAiProvider> list = aiProviderMapper.selectList();
+        list.forEach(this::maskApiKey);
+        return AjaxResult.success(list);
+    }
+
+    @PreAuthorize("@ss.hasPermi('admin:aiProvider:list')")
+    @GetMapping("/{id}")
+    public AjaxResult getInfo(@PathVariable Long id)
+    {
+        CompanyAiProvider provider = aiProviderMapper.selectById(id);
+        if (provider != null) {
+            maskApiKey(provider);
+        }
+        return AjaxResult.success(provider);
+    }
+
+    @PreAuthorize("@ss.hasPermi('admin:aiProvider:add')")
+    @Log(title = "新增大模型供应商", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody CompanyAiProvider provider)
+    {
+        provider.setIsDefault(0);
+        provider.setDelFlag(0);
+        return toAjax(aiProviderMapper.insert(provider));
+    }
+
+    @PreAuthorize("@ss.hasPermi('admin:aiProvider:edit')")
+    @Log(title = "修改大模型供应商", businessType = BusinessType.UPDATE)
+    @PutMapping("/{id}")
+    public AjaxResult edit(@PathVariable Long id, @RequestBody CompanyAiProvider provider)
+    {
+        provider.setId(id);
+        if (provider.getApiKey() != null && provider.getApiKey().contains("*")) {
+            CompanyAiProvider existing = aiProviderMapper.selectById(id);
+            if (existing != null) {
+                provider.setApiKey(existing.getApiKey());
+            }
+        }
+        return toAjax(aiProviderMapper.updateById(provider));
+    }
+
+    @PreAuthorize("@ss.hasPermi('admin:aiProvider:remove')")
+    @Log(title = "删除大模型供应商", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{id}")
+    public AjaxResult remove(@PathVariable Long id)
+    {
+        return toAjax(aiProviderMapper.deleteById(id));
+    }
+
+    @PreAuthorize("@ss.hasPermi('admin:aiProvider:edit')")
+    @Log(title = "设置默认大模型供应商", businessType = BusinessType.UPDATE)
+    @PostMapping("/{id}/set-default")
+    public AjaxResult setDefault(@PathVariable Long id)
+    {
+        aiProviderMapper.clearAllDefault();
+        CompanyAiProvider provider = new CompanyAiProvider();
+        provider.setId(id);
+        provider.setIsDefault(1);
+        return toAjax(aiProviderMapper.updateById(provider));
+    }
+
+    @PreAuthorize("@ss.hasPermi('admin:aiProvider:list')")
+    @PostMapping("/test")
+    public AjaxResult test(@RequestBody CompanyAiProvider provider)
+    {
+        return AjaxResult.success("连接测试功能待实现");
+    }
+
+    private void maskApiKey(CompanyAiProvider provider) {
+        String apiKey = provider.getApiKey();
+        if (apiKey != null && apiKey.length() > 8) {
+            provider.setApiKey(apiKey.substring(0, 4) + "****" + apiKey.substring(apiKey.length() - 4));
+        } else if (apiKey != null && apiKey.length() > 0) {
+            provider.setApiKey("****");
+        }
+    }
+}

+ 103 - 0
fs-admin/src/main/java/com/fs/admin/controller/ArticleAdminController.java

@@ -0,0 +1,103 @@
+package com.fs.admin.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.his.domain.FsArticle;
+import com.fs.his.service.IFsArticleService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 总后台文章内容审计控制器
+ * 审计所有租户的文章内容
+ */
+@RestController
+@RequestMapping("/admin/article")
+public class ArticleAdminController extends BaseController {
+
+    @Autowired
+    private IFsArticleService fsArticleService;
+
+    /**
+     * 查询所有租户的文章列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:article:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsArticle article) {
+        startPage();
+        List<FsArticle> list = fsArticleService.selectFsArticleList(article);
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取文章详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('admin:article:query')")
+    @GetMapping(value = "/{articleId}")
+    public AjaxResult getInfo(@PathVariable("articleId") Long articleId) {
+        return AjaxResult.success(fsArticleService.selectFsArticleByArticleId(articleId));
+    }
+
+    /**
+     * 根据租户ID查询文章列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:article:query')")
+    @GetMapping("/byCompany/{companyId}")
+    public TableDataInfo getByCompanyId(@PathVariable Long companyId) {
+        startPage();
+        FsArticle article = new FsArticle();
+        List<FsArticle> list = fsArticleService.selectFsArticleList(article);
+        return getDataTable(list);
+    }
+
+    /**
+     * 审计文章(通过/拒绝)
+     */
+    @PreAuthorize("@ss.hasPermi('admin:article:audit')")
+    @PutMapping("/audit/{articleId}")
+    public AjaxResult audit(@PathVariable Long articleId,
+                           @RequestParam Integer status,
+                           @RequestParam(required = false) String auditRemark) {
+        FsArticle article = new FsArticle();
+        article.setArticleId(articleId);
+        return toAjax(fsArticleService.updateFsArticle(article));
+    }
+
+    /**
+     * 查询待审计文章列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:article:list')")
+    @GetMapping("/pending")
+    public TableDataInfo pendingList() {
+        startPage();
+        FsArticle article = new FsArticle();
+        List<FsArticle> list = fsArticleService.selectFsArticleList(article);
+        return getDataTable(list);
+    }
+
+    /**
+     * 删除文章
+     */
+    @PreAuthorize("@ss.hasPermi('admin:article:remove')")
+    @DeleteMapping("/{articleIds}")
+    public AjaxResult remove(@PathVariable Long[] articleIds) {
+        return toAjax(fsArticleService.deleteFsArticleByArticleIds(articleIds));
+    }
+
+    /**
+     * 文章统计信息
+     */
+    @PreAuthorize("@ss.hasPermi('admin:article:query')")
+    @GetMapping("/statistics")
+    public AjaxResult statistics() {
+        FsArticle query = new FsArticle();
+        List<FsArticle> all = fsArticleService.selectFsArticleList(query);
+        java.util.Map<String, Object> result = new java.util.HashMap<>();
+        result.put("totalCount", all.size());
+        return AjaxResult.success(result);
+    }
+}

+ 140 - 0
fs-admin/src/main/java/com/fs/admin/controller/CallRecordAdminController.java

@@ -0,0 +1,140 @@
+package com.fs.admin.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.company.domain.CompanyVoiceRoboticCallLogCallphone;
+import com.fs.company.service.ICompanyVoiceRoboticCallLogCallphoneService;
+import com.fs.proxy.domain.CallQualityRecord;
+import com.fs.proxy.service.CallQualityService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 总后台外呼记录和质检控制器
+ * 查看所有租户的外呼通话记录、录音和质检
+ */
+@RestController
+@RequestMapping("/admin/callRecord")
+public class CallRecordAdminController extends BaseController {
+
+    @Autowired
+    private ICompanyVoiceRoboticCallLogCallphoneService callLogService;
+
+    @Autowired
+    private CallQualityService callQualityService;
+
+    /**
+     * 查询所有租户的外呼通话记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:callRecord:list')")
+    @GetMapping("/list")
+    public TableDataInfo list() {
+        startPage();
+        List<CompanyVoiceRoboticCallLogCallphone> list = callLogService.list(new QueryWrapper<CompanyVoiceRoboticCallLogCallphone>().orderByDesc("run_time"));
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取外呼通话记录详情
+     */
+    @PreAuthorize("@ss.hasPermi('admin:callRecord:query')")
+    @GetMapping(value = "/{logId}")
+    public AjaxResult getInfo(@PathVariable("logId") Long logId) {
+        return AjaxResult.success(callLogService.getById(logId));
+    }
+
+    /**
+     * 根据租户ID查询外呼记录
+     */
+    @PreAuthorize("@ss.hasPermi('admin:callRecord:query')")
+    @GetMapping("/byCompany/{companyId}")
+    public TableDataInfo getByCompanyId(@PathVariable Long companyId) {
+        startPage();
+        List<CompanyVoiceRoboticCallLogCallphone> list = callLogService.list(new QueryWrapper<CompanyVoiceRoboticCallLogCallphone>().orderByDesc("run_time"));
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取通话录音路径
+     */
+    @PreAuthorize("@ss.hasPermi('admin:callRecord:query')")
+    @GetMapping("/audio/{logId}")
+    public AjaxResult getAudio(@PathVariable Long logId) {
+        CompanyVoiceRoboticCallLogCallphone callLog = callLogService.getById(logId);
+        if (callLog != null && callLog.getRecordPath() != null) {
+            return AjaxResult.success(callLog.getRecordPath());
+        }
+        return AjaxResult.error("录音不存在");
+    }
+
+    /**
+     * 查询质检记录列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:callRecord:qualityList')")
+    @GetMapping("/quality/list")
+    public TableDataInfo qualityList(CallQualityRecord record) {
+        startPage();
+        List<CallQualityRecord> list = callQualityService.selectCallQualityRecordList(record);
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取质检记录详情
+     */
+    @PreAuthorize("@ss.hasPermi('admin:callRecord:query')")
+    @GetMapping("/quality/{id}")
+    public AjaxResult getQualityInfo(@PathVariable Long id) {
+        return AjaxResult.success(callQualityService.selectCallQualityRecordById(id));
+    }
+
+    /**
+     * 新增质检记录
+     */
+    @PreAuthorize("@ss.hasPermi('admin:callRecord:addQuality')")
+    @PostMapping("/quality")
+    public AjaxResult addQuality(@RequestBody CallQualityRecord record) {
+        return toAjax(callQualityService.insertCallQualityRecord(record));
+    }
+
+    /**
+     * 修改质检记录
+     */
+    @PreAuthorize("@ss.hasPermi('admin:callRecord:editQuality')")
+    @PutMapping("/quality")
+    public AjaxResult editQuality(@RequestBody CallQualityRecord record) {
+        return toAjax(callQualityService.updateCallQualityRecord(record));
+    }
+
+    /**
+     * 删除质检记录
+     */
+    @PreAuthorize("@ss.hasPermi('admin:callRecord:removeQuality')")
+    @DeleteMapping("/quality/{ids}")
+    public AjaxResult removeQuality(@PathVariable Long[] ids) {
+        return toAjax(callQualityService.deleteCallQualityRecordByIds(ids));
+    }
+
+    /**
+     * 通话记录统计信息
+     */
+    @PreAuthorize("@ss.hasPermi('admin:callRecord:query')")
+    @GetMapping("/statistics")
+    public AjaxResult statistics() {
+        return AjaxResult.success(callLogService.count());
+    }
+
+    /**
+     * 报备质检
+     */
+    @PreAuthorize("@ss.hasPermi('admin:callRecord:report')")
+    @PostMapping("/report")
+    public AjaxResult report(@RequestBody List<Long> logIds) {
+        int count = callQualityService.batchReport(logIds);
+        return AjaxResult.success("报备成功,共报备 " + count + " 条通话记录");
+    }
+}

+ 118 - 0
fs-admin/src/main/java/com/fs/admin/controller/CompanyAdminController.java

@@ -0,0 +1,118 @@
+package com.fs.admin.controller;
+
+import com.fs.common.annotation.Log;
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.common.enums.BusinessType;
+import com.fs.company.domain.Company;
+import com.fs.company.service.ICompanyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 总后台租户管理控制器
+ * 管理所有租户,包括禁用启用租户
+ */
+@RestController
+@RequestMapping("/admin/company")
+public class CompanyAdminController extends BaseController {
+
+    @Autowired
+    private ICompanyService companyService;
+
+    /**
+     * 查询所有租户列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:company:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(Company company) {
+        startPage();
+        List<Company> list = companyService.selectCompanyList(company);
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取租户详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('admin:company:query')")
+    @GetMapping(value = "/{companyId}")
+    public AjaxResult getInfo(@PathVariable("companyId") Long companyId) {
+        return AjaxResult.success(companyService.selectCompanyById(companyId));
+    }
+
+    /**
+     * 新增租户
+     */
+    @PreAuthorize("@ss.hasPermi('admin:company:add')")
+    @Log(title = "租户管理", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody Company company) {
+        companyService.insertCompany(company);
+        return AjaxResult.success();
+    }
+
+    /**
+     * 修改租户
+     */
+    @PreAuthorize("@ss.hasPermi('admin:company:edit')")
+    @Log(title = "租户管理", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody Company company) {
+        return toAjax(companyService.updateCompany(company));
+    }
+
+    /**
+     * 删除租户
+     */
+    @PreAuthorize("@ss.hasPermi('admin:company:remove')")
+    @Log(title = "租户管理", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{companyIds}")
+    public AjaxResult remove(@PathVariable Long[] companyIds) {
+        return toAjax(companyService.deleteCompanyByIds(companyIds));
+    }
+
+    /**
+     * 禁用/启用租户
+     */
+    @PreAuthorize("@ss.hasPermi('admin:company:edit')")
+    @Log(title = "租户管理", businessType = BusinessType.UPDATE)
+    @PutMapping("/status/{companyId}")
+    public AjaxResult changeStatus(@PathVariable Long companyId, @RequestParam Integer status) {
+        Company company = new Company();
+        company.setCompanyId(companyId);
+        company.setStatus(status);
+        return toAjax(companyService.updateCompany(company));
+    }
+
+    /**
+     * 获取租户下拉列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:company:query')")
+    @GetMapping("/options")
+    public AjaxResult getOptions() {
+        Company company = new Company();
+        company.setStatus(1);
+        List<Company> list = companyService.selectCompanyList(company);
+        return AjaxResult.success(list);
+    }
+
+    /**
+     * 租户统计信息
+     */
+    @PreAuthorize("@ss.hasPermi('admin:company:query')")
+    @GetMapping("/statistics")
+    public AjaxResult statistics() {
+        Company company = new Company();
+        List<Company> all = companyService.selectCompanyList(company);
+        long activeCount = all.stream().filter(c -> c.getStatus() != null && c.getStatus() == 1).count();
+        java.util.Map<String, Object> result = new java.util.HashMap<>();
+        result.put("totalCount", all.size());
+        result.put("activeCount", activeCount);
+        result.put("disabledCount", all.size() - activeCount);
+        return AjaxResult.success(result);
+    }
+}

+ 124 - 0
fs-admin/src/main/java/com/fs/admin/controller/CompanyUserAdminController.java

@@ -0,0 +1,124 @@
+package com.fs.admin.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.company.domain.Company;
+import com.fs.company.domain.CompanyUser;
+import com.fs.company.domain.CompanyUserChangeApply;
+import com.fs.company.service.ICompanyService;
+import com.fs.company.service.ICompanyUserChangeApplyService;
+import com.fs.company.service.ICompanyUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 总后台员工账户管理控制器
+ * 查看所有租户的员工账户、禁用启用员工账户、查看账户变化记录
+ */
+@RestController
+@RequestMapping("/admin/companyUser")
+public class CompanyUserAdminController extends BaseController {
+
+    @Autowired
+    private ICompanyUserService companyUserService;
+
+    @Autowired
+    private ICompanyUserChangeApplyService companyUserChangeApplyService;
+
+    @Autowired
+    private ICompanyService companyService;
+
+    /**
+     * 查询所有租户的员工列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:companyUser:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(CompanyUser companyUser) {
+        startPage();
+        List<CompanyUser> list = companyUserService.selectCompanyUserList(companyUser);
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取员工详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('admin:companyUser:query')")
+    @GetMapping(value = "/{userId}")
+    public AjaxResult getInfo(@PathVariable("userId") Long userId) {
+        return AjaxResult.success(companyUserService.selectCompanyUserById(userId));
+    }
+
+    /**
+     * 根据租户ID查询员工列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:companyUser:query')")
+    @GetMapping("/byCompany/{companyId}")
+    public TableDataInfo getByCompanyId(@PathVariable Long companyId) {
+        startPage();
+        CompanyUser companyUser = new CompanyUser();
+        companyUser.setCompanyId(companyId);
+        List<CompanyUser> list = companyUserService.selectCompanyUserList(companyUser);
+        return getDataTable(list);
+    }
+
+    /**
+     * 禁用/启用员工账户
+     */
+    @PreAuthorize("@ss.hasPermi('admin:companyUser:edit')")
+    @PutMapping("/status/{userId}")
+    public AjaxResult changeStatus(@PathVariable Long userId, @RequestParam Integer status) {
+        CompanyUser companyUser = new CompanyUser();
+        companyUser.setUserId(userId);
+        companyUser.setStatus(status != null ? String.valueOf(status) : "1");
+        return toAjax(companyUserService.updateCompanyUser(companyUser));
+    }
+
+    /**
+     * 查询员工账户变化记录
+     */
+    @PreAuthorize("@ss.hasPermi('admin:companyUser:changeList')")
+    @GetMapping("/changeList")
+    public TableDataInfo changeList() {
+        startPage();
+        List<CompanyUserChangeApply> list = companyUserChangeApplyService.list();
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取员工账户变化记录详情
+     */
+    @PreAuthorize("@ss.hasPermi('admin:companyUser:query')")
+    @GetMapping("/change/{id}")
+    public AjaxResult getChangeInfo(@PathVariable Long id) {
+        return AjaxResult.success(companyUserChangeApplyService.getById(id));
+    }
+
+    /**
+     * 获取租户列表(用于筛选)
+     */
+    @PreAuthorize("@ss.hasPermi('admin:companyUser:query')")
+    @GetMapping("/companies")
+    public AjaxResult getCompanies() {
+        Company company = new Company();
+        company.setStatus(1);
+        List<Company> list = companyService.selectCompanyList(company);
+        return AjaxResult.success(list);
+    }
+
+    /**
+     * 统计各租户员工数量
+     */
+    @PreAuthorize("@ss.hasPermi('admin:companyUser:query')")
+    @GetMapping("/statistics")
+    public AjaxResult statistics() {
+        CompanyUser query = new CompanyUser();
+        List<CompanyUser> all = companyUserService.selectCompanyUserList(query);
+        java.util.Map<String, Object> result = new java.util.HashMap<>();
+        result.put("totalCount", all.size());
+        return AjaxResult.success(result);
+    }
+}

+ 90 - 0
fs-admin/src/main/java/com/fs/admin/controller/CourseAdminController.java

@@ -0,0 +1,90 @@
+package com.fs.admin.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.course.domain.FsUserCourseVideo;
+import com.fs.course.service.IFsUserCourseVideoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 总后台课程内容管理控制器
+ * 查看所有租户的课程内容
+ */
+@RestController
+@RequestMapping("/admin/course")
+public class CourseAdminController extends BaseController {
+
+    @Autowired
+    private IFsUserCourseVideoService fsUserCourseVideoService;
+
+    /**
+     * 查询所有租户的课程列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:course:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsUserCourseVideo course) {
+        startPage();
+        List<FsUserCourseVideo> list = fsUserCourseVideoService.selectFsUserCourseVideoList(course);
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取课程详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('admin:course:query')")
+    @GetMapping(value = "/{courseId}")
+    public AjaxResult getInfo(@PathVariable("courseId") Long courseId) {
+        return AjaxResult.success(fsUserCourseVideoService.selectFsUserCourseVideoByVideoId(courseId));
+    }
+
+    /**
+     * 根据租户ID查询课程列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:course:query')")
+    @GetMapping("/byCompany/{companyId}")
+    public TableDataInfo getByCompanyId(@PathVariable Long companyId) {
+        startPage();
+        FsUserCourseVideo course = new FsUserCourseVideo();
+        List<FsUserCourseVideo> list = fsUserCourseVideoService.selectFsUserCourseVideoList(course);
+        return getDataTable(list);
+    }
+
+    /**
+     * 审核课程(上架/下架)
+     */
+    @PreAuthorize("@ss.hasPermi('admin:course:audit')")
+    @PutMapping("/audit/{courseId}")
+    public AjaxResult audit(@PathVariable Long courseId, @RequestParam Integer status) {
+        FsUserCourseVideo course = new FsUserCourseVideo();
+        course.setCourseId(courseId);
+        return toAjax(fsUserCourseVideoService.updateFsUserCourseVideo(course));
+    }
+
+    /**
+     * 删除课程
+     */
+    @PreAuthorize("@ss.hasPermi('admin:course:remove')")
+    @DeleteMapping("/{courseIds}")
+    public AjaxResult remove(@PathVariable Long[] courseIds) {
+        String[] ids = new String[courseIds.length];
+        for (int i = 0; i < courseIds.length; i++) ids[i] = String.valueOf(courseIds[i]);
+        return toAjax(fsUserCourseVideoService.deleteFsUserCourseVideoByVideoIds(ids));
+    }
+
+    /**
+     * 课程统计信息
+     */
+    @PreAuthorize("@ss.hasPermi('admin:course:query')")
+    @GetMapping("/statistics")
+    public AjaxResult statistics() {
+        long total = fsUserCourseVideoService.count();
+        java.util.Map<String, Object> result = new java.util.HashMap<>();
+        result.put("totalCount", total);
+        return AjaxResult.success(result);
+    }
+}

+ 90 - 0
fs-admin/src/main/java/com/fs/admin/controller/LiveAdminController.java

@@ -0,0 +1,90 @@
+package com.fs.admin.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.live.domain.LiveVideo;
+import com.fs.live.service.ILiveVideoService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 总后台直播内容管理控制器
+ * 查看所有租户的直播内容
+ */
+@RestController
+@RequestMapping("/admin/live")
+public class LiveAdminController extends BaseController {
+
+    @Autowired
+    private ILiveVideoService liveVideoService;
+
+    /**
+     * 查询所有租户的直播列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:live:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(LiveVideo liveVideo) {
+        startPage();
+        List<LiveVideo> list = liveVideoService.selectLiveVideoList(liveVideo);
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取直播详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('admin:live:query')")
+    @GetMapping(value = "/{liveId}")
+    public AjaxResult getInfo(@PathVariable("liveId") Long liveId) {
+        return AjaxResult.success(liveVideoService.selectLiveVideoByVideoId(liveId));
+    }
+
+    /**
+     * 根据租户ID查询直播列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:live:query')")
+    @GetMapping("/byCompany/{companyId}")
+    public TableDataInfo getByCompanyId(@PathVariable Long companyId) {
+        startPage();
+        LiveVideo liveVideo = new LiveVideo();
+        // 不设置companyId过滤,查询所有
+        List<LiveVideo> list = liveVideoService.selectLiveVideoList(liveVideo);
+        return getDataTable(list);
+    }
+
+    /**
+     * 审核直播(上架/下架)
+     */
+    @PreAuthorize("@ss.hasPermi('admin:live:audit')")
+    @PutMapping("/audit/{liveId}")
+    public AjaxResult audit(@PathVariable Long liveId, @RequestParam Integer status) {
+        LiveVideo liveVideo = new LiveVideo();
+        liveVideo.setVideoId(liveId);
+        return toAjax(liveVideoService.updateLiveVideo(liveVideo));
+    }
+
+    /**
+     * 删除直播
+     */
+    @PreAuthorize("@ss.hasPermi('admin:live:remove')")
+    @DeleteMapping("/{liveIds}")
+    public AjaxResult remove(@PathVariable Long[] liveIds) {
+        return toAjax(liveVideoService.deleteLiveVideoByVideoIds(liveIds));
+    }
+
+    /**
+     * 直播统计信息
+     */
+    @PreAuthorize("@ss.hasPermi('admin:live:query')")
+    @GetMapping("/statistics")
+    public AjaxResult statistics() {
+        LiveVideo query = new LiveVideo();
+        List<LiveVideo> all = liveVideoService.selectLiveVideoList(query);
+        java.util.Map<String, Object> result = new java.util.HashMap<>();
+        result.put("totalCount", all.size());
+        return AjaxResult.success(result);
+    }
+}

+ 90 - 0
fs-admin/src/main/java/com/fs/admin/controller/LobsterAdminController.java

@@ -0,0 +1,90 @@
+package com.fs.admin.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.company.domain.LobsterWorkflowInstance;
+import com.fs.company.mapper.LobsterWorkflowInstanceMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 总后台龙虾引擎管理控制器
+ * 查看所有租户的工作流实例、运行统计
+ */
+@RestController
+@RequestMapping("/admin/lobster")
+public class LobsterAdminController extends BaseController {
+
+    @Autowired
+    private LobsterWorkflowInstanceMapper instanceMapper;
+
+    /**
+     * 查询所有租户的工作流实例列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:lobster:list')")
+    @GetMapping("/instance/list")
+    public TableDataInfo instanceList(LobsterWorkflowInstance query) {
+        startPage();
+        // 查询所有租户的实例(不限制companyId)
+        List<LobsterWorkflowInstance> list = instanceMapper.selectByCompanyId(null);
+        return getDataTable(list);
+    }
+
+    /**
+     * 查询指定实例详情
+     */
+    @PreAuthorize("@ss.hasPermi('admin:lobster:list')")
+    @GetMapping("/instance/{instanceId}")
+    public AjaxResult instanceDetail(@PathVariable Long instanceId) {
+        LobsterWorkflowInstance instance = instanceMapper.selectById(instanceId);
+        if (instance == null) {
+            return AjaxResult.error("实例不存在");
+        }
+        return AjaxResult.success(instance);
+    }
+
+    /**
+     * 查询指定实例的节点执行日志
+     */
+    @PreAuthorize("@ss.hasPermi('admin:lobster:list')")
+    @GetMapping("/instance/node-logs/{instanceId}")
+    public AjaxResult instanceNodeLogs(@PathVariable Long instanceId) {
+        // 节点日志通过instanceId查询,由LobsterNodeExecutionLogMapper处理
+        return AjaxResult.success();
+    }
+
+    /**
+     * 强制终止指定实例
+     */
+    @PreAuthorize("@ss.hasPermi('admin:lobster:list')")
+    @PostMapping("/instance/terminate/{instanceId}")
+    public AjaxResult terminateInstance(@PathVariable Long instanceId, @RequestParam(required = false) String reason) {
+        LobsterWorkflowInstance instance = instanceMapper.selectById(instanceId);
+        if (instance == null) {
+            return AjaxResult.error("实例不存在");
+        }
+        instanceMapper.updateStatus(instanceId, instance.getCompanyId(), "TERMINATED");
+        return AjaxResult.success("实例已终止");
+    }
+
+    /**
+     * 全局工作流运行统计
+     */
+    @PreAuthorize("@ss.hasPermi('admin:lobster:list')")
+    @GetMapping("/instance/stats")
+    public AjaxResult instanceStats() {
+        List<LobsterWorkflowInstance> allInstances = instanceMapper.selectByCompanyId(null);
+        Map<String, Object> stats = new HashMap<>();
+        stats.put("totalInstances", allInstances.size());
+        stats.put("runningInstances", allInstances.stream().filter(i -> "RUNNING".equals(i.getStatus())).count());
+        stats.put("completedInstances", allInstances.stream().filter(i -> "COMPLETED".equals(i.getStatus())).count());
+        stats.put("failedInstances", allInstances.stream().filter(i -> "FAILED".equals(i.getStatus())).count());
+        return AjaxResult.success(stats);
+    }
+}

+ 102 - 0
fs-admin/src/main/java/com/fs/admin/controller/ProductAdminController.java

@@ -0,0 +1,102 @@
+package com.fs.admin.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.his.domain.FsStoreProduct;
+import com.fs.his.service.IFsStoreProductService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 总后台商品审核控制器
+ * 审核所有租户的商品上架申请
+ */
+@RestController
+@RequestMapping("/admin/product")
+public class ProductAdminController extends BaseController {
+
+    @Autowired
+    private IFsStoreProductService fsStoreProductService;
+
+    /**
+     * 查询所有租户的商品列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:product:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(FsStoreProduct product) {
+        startPage();
+        List<FsStoreProduct> list = fsStoreProductService.selectFsStoreProductList(product);
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取商品详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('admin:product:query')")
+    @GetMapping(value = "/{productId}")
+    public AjaxResult getInfo(@PathVariable("productId") Long productId) {
+        return AjaxResult.success(fsStoreProductService.selectFsStoreProductById(productId));
+    }
+
+    /**
+     * 根据租户ID查询商品列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:product:query')")
+    @GetMapping("/byCompany/{companyId}")
+    public TableDataInfo getByCompanyId(@PathVariable Long companyId) {
+        startPage();
+        FsStoreProduct product = new FsStoreProduct();
+        List<FsStoreProduct> list = fsStoreProductService.selectFsStoreProductList(product);
+        return getDataTable(list);
+    }
+
+    /**
+     * 审核商品(上架/拒绝)
+     */
+    @PreAuthorize("@ss.hasPermi('admin:product:audit')")
+    @PutMapping("/audit/{productId}")
+    public AjaxResult audit(@PathVariable Long productId,
+                           @RequestParam Integer status,
+                           @RequestParam(required = false) String auditRemark) {
+        FsStoreProduct product = new FsStoreProduct();
+        product.setProductId(productId);
+        return toAjax(fsStoreProductService.updateFsStoreProduct(product));
+    }
+
+    /**
+     * 查询待审核商品列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:product:list')")
+    @GetMapping("/pending")
+    public TableDataInfo pendingList() {
+        startPage();
+        FsStoreProduct product = new FsStoreProduct();
+        List<FsStoreProduct> list = fsStoreProductService.selectFsStoreProductList(product);
+        return getDataTable(list);
+    }
+
+    /**
+     * 删除商品
+     */
+    @PreAuthorize("@ss.hasPermi('admin:product:remove')")
+    @DeleteMapping("/{productIds}")
+    public AjaxResult remove(@PathVariable Long[] productIds) {
+        return toAjax(fsStoreProductService.deleteFsStoreProductByProductIds(productIds));
+    }
+
+    /**
+     * 商品统计信息
+     */
+    @PreAuthorize("@ss.hasPermi('admin:product:query')")
+    @GetMapping("/statistics")
+    public AjaxResult statistics() {
+        long total = fsStoreProductService.selectFsStoreProductCount(0);
+        java.util.Map<String, Object> result = new java.util.HashMap<>();
+        result.put("totalCount", total);
+        return AjaxResult.success(result);
+    }
+}

+ 87 - 0
fs-admin/src/main/java/com/fs/admin/controller/QwExternalContactAdminController.java

@@ -0,0 +1,87 @@
+package com.fs.admin.controller;
+
+import com.fs.common.core.controller.BaseController;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.page.TableDataInfo;
+import com.fs.company.domain.Company;
+import com.fs.company.service.ICompanyService;
+import com.fs.qw.domain.QwExternalContact;
+import com.fs.qw.service.IQwExternalContactService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 总后台企微用户管理控制器
+ * 查看所有租户的企微用户
+ */
+@RestController
+@RequestMapping("/admin/qwContact")
+public class QwExternalContactAdminController extends BaseController {
+
+    @Autowired
+    private IQwExternalContactService qwExternalContactService;
+
+    @Autowired
+    private ICompanyService companyService;
+
+    /**
+     * 查询所有租户的企微用户列表
+     */
+    @PreAuthorize("@ss.hasPermi('admin:qwContact:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(QwExternalContact qwExternalContact) {
+        startPage();
+        // 不设置companyId,查询所有租户的数据
+        List<QwExternalContact> list = qwExternalContactService.selectQwExternalContactList(qwExternalContact);
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取企微用户详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('admin:qwContact:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
+        return AjaxResult.success(qwExternalContactService.selectQwExternalContactById(id));
+    }
+
+    /**
+     * 根据租户ID查询企微用户
+     */
+    @PreAuthorize("@ss.hasPermi('admin:qwContact:query')")
+    @GetMapping("/byCompany/{companyId}")
+    public TableDataInfo getByCompanyId(@PathVariable Long companyId) {
+        startPage();
+        QwExternalContact qwExternalContact = new QwExternalContact();
+        qwExternalContact.setCompanyId(companyId);
+        List<QwExternalContact> list = qwExternalContactService.selectQwExternalContactList(qwExternalContact);
+        return getDataTable(list);
+    }
+
+    /**
+     * 获取租户列表(用于筛选)
+     */
+    @PreAuthorize("@ss.hasPermi('admin:qwContact:query')")
+    @GetMapping("/companies")
+    public AjaxResult getCompanies() {
+        Company company = new Company();
+        company.setStatus(1); // 只查询启用的租户
+        List<Company> list = companyService.selectCompanyList(company);
+        return AjaxResult.success(list);
+    }
+
+    /**
+     * 统计各租户企微用户数量
+     */
+    @PreAuthorize("@ss.hasPermi('admin:qwContact:query')")
+    @GetMapping("/statistics")
+    public AjaxResult statistics() {
+        long total = qwExternalContactService.count();
+        java.util.Map<String, Object> result = new java.util.HashMap<>();
+        result.put("totalCount", total);
+        return AjaxResult.success(result);
+    }
+}

+ 3 - 2
fs-admin/src/main/java/com/fs/api/controller/IndexStatisticsController.java

@@ -16,7 +16,8 @@ import com.fs.statis.service.IStatisticsService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.service.ISysConfigService;
 import com.fs.system.service.ISysDeptService;
-import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -34,8 +35,8 @@ import static com.fs.statis.StatisticsRedisConstant.*;
  */
 @RestController
 @RequestMapping("/index/statistics")
-@Slf4j
 public class IndexStatisticsController {
+    private static final Logger log = LoggerFactory.getLogger(IndexStatisticsController.class);
     @Autowired
     private RedisCache redisCache;
 

+ 3 - 2
fs-admin/src/main/java/com/fs/api/controller/StatisticManageController.java

@@ -3,7 +3,8 @@ package com.fs.api.controller;
 import com.fs.common.core.domain.R;
 import com.fs.company.service.IStatisticManageService;
 import com.fs.statis.param.ComprehensiveStatisticsParam;
-import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.util.Assert;
 import org.springframework.web.bind.annotation.*;
 
@@ -14,10 +15,10 @@ import javax.annotation.Resource;
  * @author: Guos
  * @time: 2025/10/30 上午9:16
  */
-@Slf4j
 @RestController
 @RequestMapping("/statistic/manage")
 public class StatisticManageController {
+    private static final Logger log = LoggerFactory.getLogger(StatisticManageController.class);
 
     @Resource
     private IStatisticManageService statisticManageService;

+ 0 - 48
fs-admin/src/main/java/com/fs/company/controller/CompanyConfigController.java

@@ -1,48 +0,0 @@
-package com.fs.company.controller;
-
-
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.company.service.ICompanyConfigService;
-import com.fs.system.domain.SysConfig;
-import com.fs.system.service.ISysConfigService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * 系统配置
- *
-
- */
-@RestController
-@RequestMapping("/company/companyConfig")
-public class CompanyConfigController extends BaseController
-{
-
-    @Autowired
-    private ICompanyConfigService companyConfigService;
-
-
-    @Autowired
-    private ISysConfigService configService;
-
-
-
-    /**
-     * 根据参数键名查询总后台参数值
-     * @param configKey
-     * @return
-     */
-    @GetMapping(value = "/getConfigByKey/{configKey}")
-    public AjaxResult getConfigByKey(@PathVariable String configKey)
-    {
-        SysConfig config=configService.selectConfigByConfigKey(configKey);
-        return AjaxResult.success(config);
-    }
-
-
-
-}

+ 0 - 308
fs-admin/src/main/java/com/fs/company/controller/CompanyController.java

@@ -1,308 +0,0 @@
-package com.fs.company.controller;
-
-import cn.hutool.core.util.IdUtil;
-import cn.hutool.json.JSONUtil;
-import com.fs.common.annotation.Log;
-import com.fs.common.annotation.RepeatSubmit;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.domain.model.LoginUser;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.ParseUtils;
-import com.fs.common.utils.SecurityUtils;
-import com.fs.common.utils.ServletUtils;
-import com.fs.common.utils.StringUtils;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.common.utils.sign.Md5Utils;
-import com.fs.company.domain.*;
-import com.fs.company.param.*;
-import com.fs.company.service.*;
-import com.fs.company.vo.CompanyCrmVO;
-import com.fs.company.vo.CompanyVO;
-import com.fs.company.vo.CompanyVoiceCallerListVO;
-import com.fs.core.utils.OrderCodeUtils;
-import com.fs.course.config.CourseConfig;
-import com.fs.framework.web.service.TokenService;
-import com.fs.his.vo.OptionsVO;
-import com.fs.system.service.ISysConfigService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.*;
-
-import java.text.ParseException;
-import java.util.List;
-
-/**
- * 企业Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/company")
-public class CompanyController extends BaseController
-{
-    @Autowired
-    private TokenService tokenService;
-    @Autowired
-    private ICompanyService companyService;
-    @Autowired
-    private ICompanyUserService userService;
-    @Autowired
-    private ICompanyRechargeService rechargeService;
-    @Autowired
-    private ICompanyDeductService deductService;
-    @Autowired
-    private ICompanyVoiceCallerService callerService;
-    @Autowired
-    private ISysConfigService configService;
-
-    /**
-     * 查询企业列表
-     */
-    @PreAuthorize("@ss.hasPermi('live:liveMiniLives:list')")
-    @GetMapping("/liveShowList")
-    public TableDataInfo liveShowList(CompanyParam param) throws ParseException {
-        startPage();
-        List<CompanyVO> list = companyService.liveShowList(param);
-        for (CompanyVO vo : list){
-            vo.setCompanyMobile(ParseUtils.parsePhone(vo.getCompanyMobile()));
-        }
-        return getDataTable(list);
-    }
-
-    @PostMapping(value = "/batchUpdateLiveShow")
-    public R batchUpdateLiveShow(@RequestBody CompanyLiveShowParam param) {
-        if (param.getIds().isEmpty()) {
-            return R.error("请选择要操作的记录");
-        }
-        companyService.batchUpdateLiveShow(param);
-        return R.ok();
-    }
-
-    /**
-     * 查询企业列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:company:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyParam param)
-    {
-        startPage();
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        String json = configService.selectConfigByKey("course.config");
-        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
-            param.setDeptId(loginUser.getDeptId());
-        }
-        List<CompanyVO> list = companyService.selectCompanyVOList(param);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出企业列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:company:export')")
-    @Log(title = "企业", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyParam company)
-    {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        String json = configService.selectConfigByKey("course.config");
-        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
-            company.setDeptId(loginUser.getDeptId());
-        }
-        List<CompanyVO> list = companyService.selectCompanyVOList(company);
-        ExcelUtil<CompanyVO> util = new ExcelUtil<CompanyVO>(CompanyVO.class);
-        return util.exportExcel(list, "company");
-    }
-
-    /**
-     * 获取企业详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:company:query')")
-    @GetMapping(value = "/{companyId}")
-    public AjaxResult getInfo(@PathVariable("companyId") Long companyId)
-    {
-        return AjaxResult.success(companyService.selectCompanyById(companyId));
-    }
-
-    /**
-     * 新增企业
-     */
-    @PreAuthorize("@ss.hasPermi('company:company:add')")
-    @Log(title = "企业", businessType = BusinessType.INSERT, isStoreLog = true)
-    @PostMapping
-    public R add(@RequestBody Company company)
-    {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        if(company.getDeptId() != null){
-            company.setDeptId(loginUser.getDeptId());
-        }
-        company.setPassword(SecurityUtils.encryptPassword(company.getPassword()));
-        company.setAppId(Md5Utils.hash(company.getUserName()));
-        company.setAppKey(Md5Utils.hash(company.getPassword()));
-        company.setOmsCode("SF.1");
-        return companyService.insertCompany(company);
-    }
-
-    /**
-     * 修改企业
-     */
-    @PreAuthorize("@ss.hasPermi('company:company:edit')")
-    @Log(title = "企业", businessType = BusinessType.UPDATE, isStoreLog = true)
-    @PutMapping
-    public AjaxResult edit(@RequestBody Company company)
-    {
-        CompanyUser companyUser = new CompanyUser();
-        if (company.getStatus()==0){
-            companyUser.setStatus("1");
-            companyUser.setCompanyId(company.getCompanyId());
-            companyUser.setUserType("00");
-            userService.updateAllCompanyUser(companyUser);
-            CompanyVoiceCallerParam param = new CompanyVoiceCallerParam();
-            param.setCompanyId(company.getCompanyId());
-            List<CompanyVoiceCallerListVO> list = callerService.selectCompanyVoiceCallerListVO(param);
-            for (CompanyVoiceCallerListVO vo : list){
-                CompanyVoiceCaller caller=callerService.selectCompanyVoiceCallerById(vo.getCallerId());
-                caller.setCompanyId(0L);
-                caller.setCompanyUserId(0L);
-                caller.setMobile("");
-                caller.setStatus(1);
-                caller.setBindTime(null);
-                callerService.updateCompanyVoiceCaller(caller);
-            }
-        }
-        company.setUpdateMiniApp(true);
-        return toAjax(companyService.updateCompany(company));
-    }
-
-
-
-    /**
-     * 删除企业
-     */
-    @PreAuthorize("@ss.hasPermi('company:company:remove')")
-    @Log(title = "企业", businessType = BusinessType.DELETE, isStoreLog = true)
-	@DeleteMapping("/{companyIds}")
-    public AjaxResult remove(@PathVariable Long[] companyIds)
-    {
-        return toAjax(companyService.deleteCompanyByIds(companyIds));
-    }
-
-    @GetMapping("/getCompanyList")
-    public R getCompanyList()
-    {
-        Company map=new Company();
-        map.setIsDel(0);
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        String json = configService.selectConfigByKey("course.config");
-        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
-            map.setDeptId(loginUser.getDeptId());
-        }
-        List<Company> list = companyService.selectCompanyList(map);
-        return R.ok().put("data",list);
-    }
-
-
-//  @PreAuthorize("@ss.hasPermi('company:company:crmDayCountlist')")
-    @GetMapping("/crmDayCountlist")
-    public TableDataInfo companyCrmDayCountList(CompanyParam param)
-    {
-        startPage();
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        String json = configService.selectConfigByKey("course.config");
-        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
-            param.setDeptId(loginUser.getDeptId());
-        }
-        List<CompanyCrmVO> list = companyService.selectCompanyCrmDayCountList(param);
-        return getDataTable(list);
-    }
-
-
-
-    @PreAuthorize("@ss.hasPermi('company:company:resetPwd')")
-    @PostMapping("/resetPwd/{companyId}")
-    public AjaxResult resetPwd(@PathVariable Long companyId)
-    {
-        Company company=companyService.selectCompanyById(companyId);
-        return toAjax(userService.resetUserPwdByUserId(company.getUserId(),SecurityUtils.encryptPassword("cq654321!!")));
-    }
-
-//    @PreAuthorize("@ss.hasPermi('company:company:resetMoney')")
-//    @PostMapping("/resetMoney/{companyId}")
-//    public R resetMoney(@PathVariable Long companyId)
-//    {
-//        //companyService.resetMoney(companyId);
-//        return R.ok("功能已停用");
-//    }
-
-
-    @PreAuthorize("@ss.hasPermi('company:company:recharge')")
-    @Log(title = "企业转账", businessType = BusinessType.INSERT, isStoreLog = true)
-    @PostMapping(value = "/recharge")
-    @Transactional
-    @RepeatSubmit
-    public R recharge(@RequestBody CompanyRechargeParam param)
-    {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        CompanyRecharge recharge=new CompanyRecharge();
-        String orderSn =  OrderCodeUtils.getOrderSn();
-        if(StringUtils.isEmpty(orderSn)){
-            return R.error("订单生成失败,请重试");
-        }
-        recharge.setRechargeNo(orderSn);
-        recharge.setCompanyId(param.getCompanyId());
-        recharge.setMoney(param.getMoney());
-        recharge.setCreateUserId(loginUser.getUser().getUserId());
-        recharge.setIsAudit(0);
-        recharge.setStatus(0);
-        recharge.setRemark(param.getRemark());
-        recharge.setPayType(3);
-        rechargeService.insertCompanyRecharge(recharge);
-        return R.ok("提交成功,等待审核");
-
-    }
-
-    @PreAuthorize("@ss.hasPermi('company:company:deduct')")
-    @Log(title = "企业扣款", businessType = BusinessType.INSERT, isStoreLog = true)
-    @PostMapping(value = "/deduct")
-    @Transactional
-    @RepeatSubmit
-    public R deduct(@RequestBody CompanyDeductParam param)
-    {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        CompanyDeduct deduct=new CompanyDeduct();
-        String orderSn =  OrderCodeUtils.getOrderSn();
-        if(StringUtils.isEmpty(orderSn)){
-            return R.error("订单生成失败,请重试");
-        }
-        deduct.setDeductNo(orderSn);
-        deduct.setCompanyId(param.getCompanyId());
-        deduct.setMoney(param.getMoney());
-        deduct.setCreateUserId(loginUser.getUser().getUserId());
-        deduct.setIsAudit(0);
-        deduct.setRemark(param.getRemark());
-        deductService.insertCompanyDeduct(deduct);
-        return R.ok("提交成功,等待审核");
-    }
-
-    @GetMapping("/allList")
-    public TableDataInfo getHospital()
-    {
-        Long deptId = null;
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        String json = configService.selectConfigByKey("course.config");
-        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        if(!loginUser.isAdmin() && config.getDept() != null && config.getDept()){
-            deptId = loginUser.getDeptId();
-        }
-        List<OptionsVO> list = companyService.selectAllCompanyList(deptId);
-        return getDataTable(list);
-    }
-}

+ 0 - 153
fs-admin/src/main/java/com/fs/company/controller/CompanyDeductController.java

@@ -1,153 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.domain.model.LoginUser;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.ServletUtils;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.Company;
-import com.fs.company.domain.CompanyDeduct;
-import com.fs.company.domain.CompanyMoneyLogs;
-import com.fs.company.service.ICompanyDeductService;
-import com.fs.company.service.ICompanyMoneyLogsService;
-import com.fs.company.service.ICompanyRechargeService;
-import com.fs.company.service.ICompanyService;
-import com.fs.company.vo.CompanyDeductExportVO;
-import com.fs.company.vo.CompanyDeductVO;
-import com.fs.framework.web.service.TokenService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.*;
-
-import java.math.BigDecimal;
-import java.util.Date;
-import java.util.List;
-
-/**
- * 扣款Controller
- *
- * @author fs
- * @date 2023-02-27
- */
-@RestController
-@RequestMapping("/company/companyDeduct")
-public class CompanyDeductController extends BaseController
-{
-    @Autowired
-    private ICompanyDeductService companyDeductService;
-    @Autowired
-    private TokenService tokenService;
-    @Autowired
-    private ICompanyService companyService;
-    @Autowired
-    private ICompanyMoneyLogsService moneyLogsService;
-
-    @Autowired
-    private ICompanyRechargeService companyRechargeService;
-
-    /**
-     * 查询扣款列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDeduct:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyDeduct companyDeduct)
-    {
-        startPage();
-        List<CompanyDeductVO> list = companyDeductService.selectCompanyDeductVOList(companyDeduct);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出扣款列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDeduct:export')")
-    @Log(title = "扣款", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyDeduct companyDeduct)
-    {
-        List<CompanyDeductExportVO> list = companyDeductService.selectCompanyExportDeductList(companyDeduct);
-        ExcelUtil<CompanyDeductExportVO> util = new ExcelUtil<CompanyDeductExportVO>(CompanyDeductExportVO.class);
-        return util.exportExcel(list, "companyDeduct");
-    }
-
-    /**
-     * 获取扣款详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDeduct:query')")
-    @GetMapping(value = "/{deductId}")
-    public AjaxResult getInfo(@PathVariable("deductId") Long deductId)
-    {
-        return AjaxResult.success(companyDeductService.selectCompanyDeductById(deductId));
-    }
-
-    /**
-     * 新增扣款
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDeduct:add')")
-    @Log(title = "扣款", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyDeduct companyDeduct)
-    {
-        return toAjax(companyDeductService.insertCompanyDeduct(companyDeduct));
-    }
-
-    /**
-     * 修改扣款
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDeduct:edit')")
-    @Log(title = "扣款", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyDeduct companyDeduct)
-    {
-        return toAjax(companyDeductService.updateCompanyDeduct(companyDeduct));
-    }
-
-    /**
-     * 删除扣款
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDeduct:remove')")
-    @Log(title = "扣款", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{deductIds}")
-    public AjaxResult remove(@PathVariable Long[] deductIds)
-    {
-        return toAjax(companyDeductService.deleteCompanyDeductByIds(deductIds));
-    }
-
-
-    @PreAuthorize("@ss.hasPermi('company:companyDeduct:audit')")
-    @PostMapping("/audit")
-    @Transactional
-    public R audit(@RequestBody CompanyDeduct param)
-    {
-        CompanyDeduct deduct=companyDeductService.selectCompanyDeductById(param.getDeductId());
-        if(deduct.getIsAudit()!=0){
-            return R.error("非法操作");
-        }
-        deduct.setIsAudit(param.getIsAudit());
-        deduct.setRemark(param.getRemark());
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        if(deduct.getIsAudit()==1){
-            Company company=companyService.selectCompanyByIdForUpdate(deduct.getCompanyId());
-            company.setMoney(company.getMoney().subtract(deduct.getMoney()));
-            companyService.updateCompany(company);
-            CompanyMoneyLogs log=new CompanyMoneyLogs();
-            log.setCompanyId(deduct.getCompanyId());
-            log.setMoney(deduct.getMoney().multiply(new BigDecimal(-1)));
-            log.setRemark(deduct.getRemark());
-            log.setLogsType(2);
-            log.setBalance(company.getMoney());
-            log.setCreateTime(new Date());
-            moneyLogsService.insertCompanyMoneyLogs(log);
-        }
-        deduct.setAuditTime(new Date());
-        deduct.setAuditUserId(loginUser.getUser().getUserId());
-        companyDeductService.updateCompanyDeduct(deduct);
-        return R.ok("操作成功");
-
-    }
-}

+ 0 - 116
fs-admin/src/main/java/com/fs/company/controller/CompanyDeptController.java

@@ -1,116 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyDept;
-import com.fs.company.service.ICompanyDeptService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-
-@RestController
-@RequestMapping("/company/companyDept")
-public class CompanyDeptController extends BaseController
-{
-    @Autowired
-    private ICompanyDeptService companyDeptService;
-
-    /**
-     * 查询部门列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDept:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyDept companyDept)
-    {
-        startPage();
-        List<CompanyDept> list = companyDeptService.selectCompanyDeptList(companyDept);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出部门列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDept:export')")
-    @Log(title = "部门", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyDept companyDept)
-    {
-        List<CompanyDept> list = companyDeptService.selectCompanyDeptList(companyDept);
-        ExcelUtil<CompanyDept> util = new ExcelUtil<CompanyDept>(CompanyDept.class);
-        return util.exportExcel(list, "companyDept");
-    }
-
-    /**
-     * 获取部门详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDept:query')")
-    @GetMapping(value = "/{deptId}")
-    public AjaxResult getInfo(@PathVariable("deptId") Long deptId)
-    {
-        return AjaxResult.success(companyDeptService.selectCompanyDeptById(deptId));
-    }
-
-    /**
-     * 新增部门
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDept:add')")
-    @Log(title = "部门", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyDept companyDept)
-    {
-        return toAjax(companyDeptService.insertCompanyDept(companyDept));
-    }
-
-    /**
-     * 修改部门
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDept:edit')")
-    @Log(title = "部门", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyDept companyDept)
-    {
-        return toAjax(companyDeptService.updateCompanyDept(companyDept));
-    }
-
-    /**
-     * 删除部门
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDept:remove')")
-    @Log(title = "部门", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{deptIds}")
-    public AjaxResult remove(@PathVariable Long[] deptIds)
-    {
-        return toAjax(companyDeptService.deleteCompanyDeptByIds(deptIds));
-    }
-
-    /**
-     * 获取部门下拉树列表
-     */
-    @GetMapping("/treeselect")
-    public AjaxResult treeselect(CompanyDept dept)
-    {
-        dept.setStatus("0");
-        List<CompanyDept> depts = companyDeptService.selectCompanyDeptList(dept);
-        return AjaxResult.success(companyDeptService.buildDeptTreeSelect(depts));
-    }
-
-    /**
-     * 获取部门下拉树列表
-     */
-    @GetMapping("/treeselectByCompanyId/{companyId}")
-    public AjaxResult treeselectByCompanyId(@PathVariable("companyId") Long companyId)
-    {
-        CompanyDept dept = new CompanyDept();
-        dept.setStatus("0");
-        dept.setCompanyId(companyId);
-        List<CompanyDept> depts = companyDeptService.selectCompanyDeptList(dept);
-        return AjaxResult.success(companyDeptService.buildDeptTreeSelect(depts));
-    }
-}

+ 0 - 130
fs-admin/src/main/java/com/fs/company/controller/CompanyDomainBindController.java

@@ -1,130 +0,0 @@
-package com.fs.company.controller;
-
-import java.util.List;
-
-import cn.hutool.core.util.ObjectUtil;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.domain.model.LoginUser;
-import com.fs.common.utils.ServletUtils;
-import com.fs.company.param.CompanyDomainBindParam;
-import com.fs.company.vo.CompanyDomainBindVo;
-import com.fs.framework.web.service.TokenService;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.enums.BusinessType;
-import com.fs.company.domain.CompanyDomainBind;
-import com.fs.company.service.ICompanyDomainBindService;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.common.core.page.TableDataInfo;
-
-/**
- * 域名绑定销售公司Controller
- * 
- * @author fs
- * @date 2025-06-17
- */
-@RestController
-@RequestMapping("/company/companyDomainBind")
-public class CompanyDomainBindController extends BaseController
-{
-    @Autowired
-    private TokenService tokenService;
-    @Autowired
-    private ICompanyDomainBindService companyDomainBindService;
-
-    /**
-     * 查询域名绑定销售公司列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDomainBind:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyDomainBindParam companyDomainBind)
-    {
-        startPage();
-        List<CompanyDomainBindVo> list = companyDomainBindService.selectCompanyDomainBindList(companyDomainBind);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出域名绑定销售公司列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDomainBind:export')")
-    @Log(title = "域名绑定销售公司", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyDomainBindParam companyDomainBind)
-    {
-        List<CompanyDomainBindVo> list = companyDomainBindService.selectCompanyDomainBindList(companyDomainBind);
-        ExcelUtil<CompanyDomainBindVo> util = new ExcelUtil<CompanyDomainBindVo>(CompanyDomainBindVo.class);
-        return util.exportExcel(list, "域名绑定销售公司数据");
-    }
-
-    /**
-     * 获取域名绑定销售公司详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDomainBind:query')")
-    @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") Long id)
-    {
-        return AjaxResult.success(companyDomainBindService.selectCompanyDomainBindById(id));
-    }
-
-    /**
-     * 新增域名绑定销售公司
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDomainBind:add')")
-    @Log(title = "域名绑定销售公司", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyDomainBind companyDomainBind)
-    {
-        return toAjax(companyDomainBindService.insertCompanyDomainBind(companyDomainBind));
-    }
-
-    /**
-     * 修改域名绑定销售公司
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDomainBind:edit')")
-    @Log(title = "域名绑定销售公司", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyDomainBind companyDomainBind)
-    {
-        return toAjax(companyDomainBindService.updateCompanyDomainBind(companyDomainBind));
-    }
-
-    /**
-     * 删除域名绑定销售公司
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDomainBind:remove')")
-    @Log(title = "域名绑定销售公司", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{ids}")
-    public AjaxResult remove(@PathVariable Long[] ids)
-    {
-        return toAjax(companyDomainBindService.deleteCompanyDomainBindByIds(ids));
-    }
-
-    /**
-     * 域名批量绑定
-     **/
-    @PreAuthorize("@ss.hasPermi('company:companyDomain:domainBatchBinding')")
-    @PostMapping("/domainBatchBinding")
-    public R domainBatchBinding(@RequestBody CompanyDomainBindParam param) {
-        if (ObjectUtil.isEmpty(param.getCompanyIds()) || param.getCompanyIds().isEmpty()) {
-            return R.error("绑定失败,至少有一条域名分配信息!");
-        }
-        if (ObjectUtil.isEmpty(param.getCompanyUserIds()) || param.getCompanyUserIds().isEmpty()) {
-            return R.error("绑定失败,至少有一条分配人员信息!");
-        }
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        param.setUserId(loginUser.getUser().getUserId().toString());
-        return companyDomainBindService.domainBatchBinding(param);
-    }
-}

+ 0 - 99
fs-admin/src/main/java/com/fs/company/controller/CompanyDomainBindUserController.java

@@ -1,99 +0,0 @@
-package com.fs.company.controller;
-
-import java.util.List;
-
-import com.fs.company.param.CompanyDomainBindUserParam;
-import com.fs.company.vo.CompanyDomainBindUserVo;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.enums.BusinessType;
-import com.fs.company.domain.CompanyDomainBindUser;
-import com.fs.company.service.ICompanyDomainBindUserService;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.common.core.page.TableDataInfo;
-
-/**
- * 企业域名分配中间表Controller
- *
- * @author fs
- * @date 2025-06-19
- */
-@RestController
-@RequestMapping("/company/companyBindUser")
-public class CompanyDomainBindUserController extends BaseController {
-    @Autowired
-    private ICompanyDomainBindUserService companyDomainBindUserService;
-
-    /**
-     * 查询企业域名分配中间表列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyBindUser:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyDomainBindUserParam companyDomainBindUser) {
-        startPage();
-        List<CompanyDomainBindUserVo> list = companyDomainBindUserService.selectCompanyDomainBindUserList(companyDomainBindUser);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出企业域名分配中间表列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyBindUser:export')")
-    @Log(title = "企业域名分配中间表", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyDomainBindUserParam companyDomainBindUser) {
-        List<CompanyDomainBindUserVo> list = companyDomainBindUserService.selectCompanyDomainBindUserList(companyDomainBindUser);
-        ExcelUtil<CompanyDomainBindUserVo> util = new ExcelUtil<CompanyDomainBindUserVo>(CompanyDomainBindUserVo.class);
-        return util.exportExcel(list, "企业域名分配中间表数据");
-    }
-
-    /**
-     * 获取企业域名分配中间表详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyBindUser:query')")
-    @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") Long id) {
-        return AjaxResult.success(companyDomainBindUserService.selectCompanyDomainBindUserById(id));
-    }
-
-    /**
-     * 新增企业域名分配中间表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyBindUser:add')")
-    @Log(title = "企业域名分配中间表", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyDomainBindUser companyDomainBindUser) {
-        return toAjax(companyDomainBindUserService.insertCompanyDomainBindUser(companyDomainBindUser));
-    }
-
-    /**
-     * 修改企业域名分配中间表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyBindUser:edit')")
-    @Log(title = "企业域名分配中间表", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyDomainBindUser companyDomainBindUser) {
-        return toAjax(companyDomainBindUserService.updateCompanyDomainBindUser(companyDomainBindUser));
-    }
-
-    /**
-     * 删除企业域名分配中间表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyBindUser:remove')")
-    @Log(title = "企业域名分配中间表", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{ids}")
-    public AjaxResult remove(@PathVariable Long[] ids) {
-        return toAjax(companyDomainBindUserService.deleteCompanyDomainBindUserByIds(ids));
-    }
-}

+ 0 - 189
fs-admin/src/main/java/com/fs/company/controller/CompanyDomainController.java

@@ -1,189 +0,0 @@
-package com.fs.company.controller;
-
-import java.util.List;
-
-import cn.hutool.core.util.ObjectUtil;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.domain.model.LoginUser;
-import com.fs.common.exception.ServiceException;
-import com.fs.common.utils.ServletUtils;
-import com.fs.company.param.CompanyDomainParam;
-import com.fs.company.vo.CompanyDomainExportTemplateVo;
-import com.fs.company.vo.CompanyDomainVo;
-import com.fs.framework.web.service.TokenService;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.enums.BusinessType;
-import com.fs.company.domain.CompanyDomain;
-import com.fs.company.service.ICompanyDomainService;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.common.core.page.TableDataInfo;
-import org.springframework.web.multipart.MultipartFile;
-
-/**
- * 域名管路Controller
- *
- * @author fs
- * @date 2025-06-16
- */
-@RestController
-@RequestMapping("/company/companyDomain")
-public class CompanyDomainController extends BaseController {
-    @Autowired
-    private TokenService tokenService;
-    @Autowired
-    private ICompanyDomainService companyDomainService;
-
-    // 允许的文件扩展名
-    private static final String[] ALLOWED_EXCEL_EXTENSIONS = {".xlsx", ".xls"};
-    // 最大文件大小(5MB)
-    private static final long MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
-
-    /**
-     * 查询域名管路列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDomain:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyDomainParam companyDomain) {
-        startPage();
-        List<CompanyDomainVo> list = companyDomainService.selectCompanyDomainList(companyDomain);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出域名管路列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDomain:export')")
-    @Log(title = "域名管理", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyDomainParam companyDomain) {
-        List<CompanyDomainVo> list = companyDomainService.selectCompanyDomainList(companyDomain);
-        ExcelUtil<CompanyDomainVo> util = new ExcelUtil<CompanyDomainVo>(CompanyDomainVo.class);
-        return util.exportExcel(list, "域名管路数据");
-    }
-
-    /**
-     * 获取域名管路详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDomain:query')")
-    @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") Long id) {
-        return AjaxResult.success(companyDomainService.selectCompanyDomainById(id));
-    }
-
-    /**
-     * 新增域名管路
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDomain:add')")
-    @Log(title = "域名管理", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyDomain companyDomain) {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        companyDomain.setCreateBy(loginUser.getUser().getUserId().toString());
-        return toAjax(companyDomainService.insertCompanyDomain(companyDomain));
-    }
-
-    /**
-     * 修改域名管路
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDomain:edit')")
-    @Log(title = "域名管理", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyDomain companyDomain) {
-        if (ObjectUtil.isEmpty(companyDomain.getId())) {
-            throw new ServiceException("修改关键信息不能为空!");
-        }
-        return toAjax(companyDomainService.updateCompanyDomain(companyDomain));
-    }
-
-    /**
-     * 删除域名管路
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyDomain:remove')")
-    @Log(title = "域名管理", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{ids}")
-    public AjaxResult remove(@PathVariable Long[] ids) {
-        if (ObjectUtil.isEmpty(ids)) {
-            throw new ServiceException("删除关键信息不能为空!");
-        }
-        return toAjax(companyDomainService.deleteCompanyDomainByIds(ids));
-    }
-
-    /**
-     * 域名批量绑定
-     **/
-    @PreAuthorize("@ss.hasPermi('company:companyDomain:domainBatchBinding')")
-    @PostMapping("/domainBatchBinding")
-    public R domainBatchBinding(@RequestBody CompanyDomainParam param) {
-        if (ObjectUtil.isEmpty(param.getDomainIds()) || param.getDomainIds().isEmpty()) {
-            return R.error("绑定失败,至少有一条绑定域名信息!");
-        }
-        if (ObjectUtil.isEmpty(param.getCompanyIds()) || param.getCompanyIds().isEmpty()) {
-            return R.error("绑定失败,至少有一条绑定公司信息!");
-        }
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        param.setUserId(loginUser.getUser().getUserId().toString());
-        return companyDomainService.domainBatchBinding(param);
-    }
-
-    /**
-     * 导出模板
-     **/
-    @GetMapping("/exportTemplate")
-    public AjaxResult exportTemplate() {
-        ExcelUtil<CompanyDomainExportTemplateVo> util = new ExcelUtil<>(CompanyDomainExportTemplateVo.class);
-        return util.importTemplateExcel("域名导入模板");
-    }
-
-    @Log(title = "域名导入", businessType = BusinessType.IMPORT)
-    @PostMapping("/importDomainData")
-    public R importDomainData(MultipartFile file) {
-        // 1. 检查文件是否为空
-        if (file.isEmpty()) {
-            return R.error("上传的文件不能为空");
-        }
-
-        // 2. 检查文件大小
-        if (file.getSize() > MAX_FILE_SIZE) {
-            return R.error("文件大小不能超过5MB");
-        }
-
-        // 3. 检查文件扩展名
-        String fileName = file.getOriginalFilename();
-        if (fileName == null || !isValidExcelFile(fileName)) {
-            return R.error("请上传Excel文件(.xlsx或.xls格式)");
-        }
-        CompanyDomainParam param = new CompanyDomainParam();
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        param.setUserId(loginUser.getUser().getUserId().toString());
-        ExcelUtil<CompanyDomainExportTemplateVo> util = new ExcelUtil<>(CompanyDomainExportTemplateVo.class);
-        try {
-            List<CompanyDomainExportTemplateVo> companyDomainList = util.importExcel(file.getInputStream());
-            return companyDomainService.importDomainData(param, companyDomainList);
-        } catch (Exception e) {
-            e.getStackTrace();
-            return R.error("导入失败!");
-        }
-    }
-
-    // 检查文件是否为有效的Excel文件
-    private boolean isValidExcelFile(String fileName) {
-        for (String ext : ALLOWED_EXCEL_EXTENSIONS) {
-            if (fileName.toLowerCase().endsWith(ext)) {
-                return true;
-            }
-        }
-        return false;
-    }
-}

+ 0 - 97
fs-admin/src/main/java/com/fs/company/controller/CompanyLogininforController.java

@@ -1,97 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyLogininfor;
-import com.fs.company.service.ICompanyLogininforService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 系统访问记录Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/companyLogininfor")
-public class CompanyLogininforController extends BaseController
-{
-    @Autowired
-    private ICompanyLogininforService companyLogininforService;
-
-    /**
-     * 查询系统访问记录列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyLogininfor:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyLogininfor companyLogininfor)
-    {
-        startPage();
-        List<CompanyLogininfor> list = companyLogininforService.selectCompanyLogininforList(companyLogininfor);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出系统访问记录列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyLogininfor:export')")
-    @Log(title = "系统访问记录", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyLogininfor companyLogininfor)
-    {
-        List<CompanyLogininfor> list = companyLogininforService.selectCompanyLogininforList(companyLogininfor);
-        ExcelUtil<CompanyLogininfor> util = new ExcelUtil<CompanyLogininfor>(CompanyLogininfor.class);
-        return util.exportExcel(list, "companyLogininfor");
-    }
-
-    /**
-     * 获取系统访问记录详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyLogininfor:query')")
-    @GetMapping(value = "/{infoId}")
-    public AjaxResult getInfo(@PathVariable("infoId") Long infoId)
-    {
-        return AjaxResult.success(companyLogininforService.selectCompanyLogininforById(infoId));
-    }
-
-    /**
-     * 新增系统访问记录
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyLogininfor:add')")
-    @Log(title = "系统访问记录", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyLogininfor companyLogininfor)
-    {
-        return toAjax(companyLogininforService.insertCompanyLogininfor(companyLogininfor));
-    }
-
-    /**
-     * 修改系统访问记录
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyLogininfor:edit')")
-    @Log(title = "系统访问记录", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyLogininfor companyLogininfor)
-    {
-        return toAjax(companyLogininforService.updateCompanyLogininfor(companyLogininfor));
-    }
-
-    /**
-     * 删除系统访问记录
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyLogininfor:remove')")
-    @Log(title = "系统访问记录", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{infoIds}")
-    public AjaxResult remove(@PathVariable Long[] infoIds)
-    {
-        return toAjax(companyLogininforService.deleteCompanyLogininforByIds(infoIds));
-    }
-}

+ 0 - 121
fs-admin/src/main/java/com/fs/company/controller/CompanyMenuController.java

@@ -1,121 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.model.LoginUser;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.ServletUtils;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyMenu;
-import com.fs.company.service.ICompanyMenuService;
-import com.fs.framework.web.service.TokenService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-import com.fs.common.core.domain.entity.SysMenu;
-import com.fs.common.utils.ServletUtils;
-
-/**
- * 菜单权限Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/companyMenu")
-public class CompanyMenuController extends BaseController
-{
-    @Autowired
-    private ICompanyMenuService companyMenuService;
-
-    @Autowired
-    private TokenService tokenService;
-    /**
-     * 查询菜单权限列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyMenu:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyMenu companyMenu)
-    {
-        startPage();
-        List<CompanyMenu> list = companyMenuService.selectCompanyMenuList(companyMenu);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出菜单权限列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyMenu:export')")
-    @Log(title = "菜单权限", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyMenu companyMenu)
-    {
-        List<CompanyMenu> list = companyMenuService.selectCompanyMenuList(companyMenu);
-        ExcelUtil<CompanyMenu> util = new ExcelUtil<CompanyMenu>(CompanyMenu.class);
-        return util.exportExcel(list, "companyMenu");
-    }
-
-    /**
-     * 获取菜单权限详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyMenu:query')")
-    @GetMapping(value = "/{menuId}")
-    public AjaxResult getInfo(@PathVariable("menuId") Long menuId)
-    {
-        return AjaxResult.success(companyMenuService.selectCompanyMenuById(menuId));
-    }
-
-    /**
-     * 新增菜单权限
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyMenu:add')")
-    @Log(title = "菜单权限", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyMenu companyMenu)
-    {
-        return toAjax(companyMenuService.insertCompanyMenu(companyMenu));
-    }
-
-    /**
-     * 修改菜单权限
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyMenu:edit')")
-    @Log(title = "菜单权限", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyMenu companyMenu)
-    {
-        return toAjax(companyMenuService.updateCompanyMenu(companyMenu));
-    }
-
-    /**
-     * 删除菜单权限
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyMenu:remove')")
-    @Log(title = "菜单权限", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{menuIds}")
-    public AjaxResult remove(@PathVariable Long[] menuIds)
-    {
-        return toAjax(companyMenuService.deleteCompanyMenuByIds(menuIds));
-    }
-
-
-    /**
-     * 获取菜单下拉树列表
-     */
-    /**
-     * 获取菜单下拉树列表
-     */
-    @GetMapping("/treeselect")
-    public AjaxResult treeselect(CompanyMenu menu)
-    {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        Long userId = loginUser.getUser().getUserId();
-        List<CompanyMenu> menus = companyMenuService.selectMenuList(menu, userId,"00");
-        return AjaxResult.success(companyMenuService.buildMenuTreeSelect(menus));
-    }
-
-}

+ 0 - 188
fs-admin/src/main/java/com/fs/company/controller/CompanyMoneyLogsController.java

@@ -1,188 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.ParseUtils;
-import com.fs.common.utils.SecurityUtils;
-import com.fs.common.utils.StringUtils;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.Company;
-import com.fs.company.domain.CompanyDept;
-import com.fs.company.domain.CompanyMoneyLogs;
-import com.fs.company.domain.CompanyUser;
-import com.fs.company.param.CompanyMoneyLogsParam;
-import com.fs.company.service.ICompanyDeptService;
-import com.fs.company.service.ICompanyMoneyLogsService;
-import com.fs.company.service.ICompanyService;
-import com.fs.company.service.ICompanyUserService;
-import com.fs.company.vo.CompanyMoneyLogsExport1VO;
-import com.fs.company.vo.CompanyMoneyLogsExport2VO;
-import com.fs.company.vo.CompanyMoneyLogsExportVO;
-import com.fs.company.vo.CompanyMoneyLogsVO;
-import com.fs.his.domain.FsExportTask;
-import com.fs.his.domain.FsInquiryOrder;
-import com.fs.his.domain.FsStoreOrder;
-import com.fs.his.domain.FsStorePayment;
-import com.fs.his.param.FsCompanyMoneyLogsExportParam;
-import com.fs.his.service.IFsExportTaskService;
-import com.fs.his.service.IFsInquiryOrderService;
-import com.fs.his.service.IFsStoreOrderService;
-import com.fs.his.service.IFsStorePaymentService;
-import com.fs.his.vo.FsStoreOrderExportVO;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-/**
- * 企业账户记录Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/companyMoneyLogs")
-public class CompanyMoneyLogsController extends BaseController
-{
-    @Autowired
-    private ICompanyMoneyLogsService companyMoneyLogsService;
-
-    @Autowired
-    private IFsExportTaskService exportTaskService;
-
-    /**
-     * 查询企业账户记录列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogs:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyMoneyLogsParam companyMoneyLogs)
-    {
-        startPage();
-        if(!StringUtils.isEmpty(companyMoneyLogs.getCreateTimeRange())){
-            companyMoneyLogs.setCreateTimeList(companyMoneyLogs.getCreateTimeRange().split("--"));
-        }
-        if(companyMoneyLogs.getLogsType()!=null){
-            if(companyMoneyLogs.getLogsType()==3 || companyMoneyLogs.getLogsType()==4 || companyMoneyLogs.getLogsType()==5 || companyMoneyLogs.getLogsType()==6 || companyMoneyLogs.getLogsType()==13|| companyMoneyLogs.getLogsType()==14){
-                // 根据type字段判断,支持商城订单(type=0)和直播订单(type=1)
-                List<CompanyMoneyLogsVO> list = companyMoneyLogsService.selectCompanyMoneyLogsMallVOList(companyMoneyLogs);
-                return getDataTable(list);
-            }
-        }
-        List<CompanyMoneyLogsVO> list = companyMoneyLogsService.selectCompanyMoneyLogsVOList(companyMoneyLogs);
-        return getDataTable(list);
-    }
-
-
-    //转账记录
-    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogs:list1')")
-    @GetMapping("/list1")
-
-    public TableDataInfo list1(CompanyMoneyLogsParam companyMoneyLogs)
-    {
-        startPage();
-        companyMoneyLogs.setLogsType(1);
-        List<CompanyMoneyLogsVO> list = companyMoneyLogsService.selectCompanyMoneyLogsVOList(companyMoneyLogs);
-        return getDataTable(list);
-    }
-    //转账记录
-    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogs:list2')")
-    @GetMapping("/list2")
-
-    public TableDataInfo list2(CompanyMoneyLogsParam companyMoneyLogs) {
-        startPage();
-        companyMoneyLogs.setLogsType(2);
-        List<CompanyMoneyLogsVO> list = companyMoneyLogsService.selectCompanyMoneyLogsVOList(companyMoneyLogs);
-        return getDataTable(list);
-    }
-    //扣款
-    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogs:list3')")
-    @GetMapping("/list3")
-    public TableDataInfo list3(CompanyMoneyLogsParam companyMoneyLogs) {
-        startPage();
-        companyMoneyLogs.setLogsType(3);
-        List<CompanyMoneyLogsVO> list = companyMoneyLogsService.selectCompanyMoneyLogsVOList(companyMoneyLogs);
-        return getDataTable(list);
-    }
-    /**
-     * 导出企业账户记录列表
-     */
-    @PreAuthorize("@ss.hasAnyPermi('company:companyMoneyLogs:export,company:companyMoneyLogs:export1,company:companyMoneyLogs:export2')")
-    @Log(title = "企业账户记录", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(FsCompanyMoneyLogsExportParam param)   {
-        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
-            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
-        }
-        Integer exportType1 = exportTaskService.isExportType1(SecurityUtils.getUserId());
-        if (exportType1>0){
-            return AjaxResult.error("你已经有正在导出的任务");
-        }
-        //导出全部
-        if(param.getType().equals(0)){
-            //判断是否达到数据上线
-            Integer count=companyMoneyLogsService.selectCompanyMoneyLogsExportCounts(param);
-            if(count>30000){
-                return AjaxResult.error("导出数据已超出上限,最多可导出30000条数据");
-            }
-            FsExportTask task=new FsExportTask();
-            task.setTaskType(1);
-            task.setStatus(0);
-            task.setStartTime(new Date());
-            task.setRemark("账户流水导出");
-            task.setSysType(1);
-            task.setUserId(SecurityUtils.getUserId());
-            exportTaskService.insertFsExportTask(task);
-            param.setTaskId(task.getTaskId());
-            companyMoneyLogsService.exportData(param);
-            return new AjaxResult(200,"后台正在导出,请等待...任务ID:"+task.getTaskId(),task.getTaskId());
-        }
-        else if(param.getType().equals(1))
-        {
-            Integer count=companyMoneyLogsService.selectCompanyMoneyLogsExport1Counts(param);
-            if(count>30000){
-                return AjaxResult.error("导出数据已超出上限,最多可导出30000条数据");
-            }
-            FsExportTask task=new FsExportTask();
-            task.setTaskType(1);
-            task.setStatus(0);
-            task.setStartTime(new Date());
-            task.setSysType(1);
-            String remark = "导出订单明细";
-            if (param.getOrderType() != null) {
-                if (param.getOrderType() == 0) {
-                    remark = "导出商城订单明细";
-                } else if (param.getOrderType() == 1) {
-                    remark = "导出直播订单明细";
-                }
-            }
-            task.setRemark(remark);
-            task.setUserId(SecurityUtils.getUserId());
-            exportTaskService.insertFsExportTask(task);
-            param.setTaskId(task.getTaskId());
-            companyMoneyLogsService.exportData(param);
-            return new AjaxResult(200,"后台正在导出,任务ID:"+task.getTaskId(),task.getTaskId());
-        }
-        return new AjaxResult(500,"导出失败");
-
-    }
-
-    /**
-     * 获取企业账户记录详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyMoneyLogs:query')")
-    @GetMapping(value = "/{logsId}")
-    public AjaxResult getInfo(@PathVariable("logsId") Long logsId) {
-        return AjaxResult.success(companyMoneyLogsService.selectCompanyMoneyLogsById(logsId));
-    }
-
-}

+ 0 - 97
fs-admin/src/main/java/com/fs/company/controller/CompanyOperLogController.java

@@ -1,97 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyOperLog;
-import com.fs.company.service.ICompanyOperLogService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 操作日志记录Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/companyOperLog")
-public class CompanyOperLogController extends BaseController
-{
-    @Autowired
-    private ICompanyOperLogService companyOperLogService;
-
-    /**
-     * 查询操作日志记录列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyOperLog:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyOperLog companyOperLog)
-    {
-        startPage();
-        List<CompanyOperLog> list = companyOperLogService.selectCompanyOperLogList(companyOperLog);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出操作日志记录列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyOperLog:export')")
-    @Log(title = "操作日志记录", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyOperLog companyOperLog)
-    {
-        List<CompanyOperLog> list = companyOperLogService.selectCompanyOperLogList(companyOperLog);
-        ExcelUtil<CompanyOperLog> util = new ExcelUtil<CompanyOperLog>(CompanyOperLog.class);
-        return util.exportExcel(list, "companyOperLog");
-    }
-
-    /**
-     * 获取操作日志记录详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyOperLog:query')")
-    @GetMapping(value = "/{operId}")
-    public AjaxResult getInfo(@PathVariable("operId") Long operId)
-    {
-        return AjaxResult.success(companyOperLogService.selectCompanyOperLogById(operId));
-    }
-
-    /**
-     * 新增操作日志记录
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyOperLog:add')")
-    @Log(title = "操作日志记录", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyOperLog companyOperLog)
-    {
-        return toAjax(companyOperLogService.insertCompanyOperLog(companyOperLog));
-    }
-
-    /**
-     * 修改操作日志记录
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyOperLog:edit')")
-    @Log(title = "操作日志记录", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyOperLog companyOperLog)
-    {
-        return toAjax(companyOperLogService.updateCompanyOperLog(companyOperLog));
-    }
-
-    /**
-     * 删除操作日志记录
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyOperLog:remove')")
-    @Log(title = "操作日志记录", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{operIds}")
-    public AjaxResult remove(@PathVariable Long[] operIds)
-    {
-        return toAjax(companyOperLogService.deleteCompanyOperLogByIds(operIds));
-    }
-}

+ 0 - 97
fs-admin/src/main/java/com/fs/company/controller/CompanyPostController.java

@@ -1,97 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyPost;
-import com.fs.company.service.ICompanyPostService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 岗位信息Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/companyPost")
-public class CompanyPostController extends BaseController
-{
-    @Autowired
-    private ICompanyPostService companyPostService;
-
-    /**
-     * 查询岗位信息列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyPost:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyPost companyPost)
-    {
-        startPage();
-        List<CompanyPost> list = companyPostService.selectCompanyPostList(companyPost);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出岗位信息列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyPost:export')")
-    @Log(title = "岗位信息", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyPost companyPost)
-    {
-        List<CompanyPost> list = companyPostService.selectCompanyPostList(companyPost);
-        ExcelUtil<CompanyPost> util = new ExcelUtil<CompanyPost>(CompanyPost.class);
-        return util.exportExcel(list, "companyPost");
-    }
-
-    /**
-     * 获取岗位信息详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyPost:query')")
-    @GetMapping(value = "/{postId}")
-    public AjaxResult getInfo(@PathVariable("postId") Long postId)
-    {
-        return AjaxResult.success(companyPostService.selectCompanyPostById(postId));
-    }
-
-    /**
-     * 新增岗位信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyPost:add')")
-    @Log(title = "岗位信息", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyPost companyPost)
-    {
-        return toAjax(companyPostService.insertCompanyPost(companyPost));
-    }
-
-    /**
-     * 修改岗位信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyPost:edit')")
-    @Log(title = "岗位信息", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyPost companyPost)
-    {
-        return toAjax(companyPostService.updateCompanyPost(companyPost));
-    }
-
-    /**
-     * 删除岗位信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyPost:remove')")
-    @Log(title = "岗位信息", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{postIds}")
-    public AjaxResult remove(@PathVariable Long[] postIds)
-    {
-        return toAjax(companyPostService.deleteCompanyPostByIds(postIds));
-    }
-}

+ 0 - 276
fs-admin/src/main/java/com/fs/company/controller/CompanyProfitController.java

@@ -1,276 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.domain.model.LoginUser;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.ServletUtils;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.Company;
-import com.fs.company.domain.CompanyMoneyLogs;
-import com.fs.company.domain.CompanyProfit;
-import com.fs.company.domain.CompanyProfitLogs;
-import com.fs.company.param.CompanyProfitAuditParam;
-import com.fs.company.service.ICompanyMoneyLogsService;
-import com.fs.company.service.ICompanyProfitLogsService;
-import com.fs.company.service.ICompanyProfitService;
-import com.fs.company.service.ICompanyService;
-import com.fs.company.vo.CompanyProfitVO;
-import com.fs.framework.web.service.TokenService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.Date;
-import java.util.List;
-
-/**
- * 提现Controller
- *
- * @author fs
- * @date 2022-07-04
- */
-@RestController
-@RequestMapping("/company/companyProfit")
-public class CompanyProfitController extends BaseController
-{
-    @Autowired
-    private ICompanyProfitService companyProfitService;
-    @Autowired
-    private ICompanyService companyService;
-    @Autowired
-    private ICompanyMoneyLogsService moneyLogsService;
-    @Autowired
-    private ICompanyProfitLogsService logsService;
-    @Autowired
-    private TokenService tokenService;
-    /**
-     * 查询提现列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyProfit:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyProfit companyProfit)
-    {
-        startPage();
-        List<CompanyProfitVO> list = companyProfitService.selectCompanyProfitListVO(companyProfit);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出提现列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyProfit:export')")
-    @Log(title = "提现", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyProfit companyProfit)
-    {
-        List<CompanyProfitVO> list = companyProfitService.selectCompanyProfitListVO(companyProfit);
-        ExcelUtil<CompanyProfitVO> util = new ExcelUtil<CompanyProfitVO>(CompanyProfitVO.class);
-        return util.exportExcel(list, "公司提现记录");
-    }
-
-    /**
-     * 获取提现详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyProfit:query')")
-    @GetMapping(value = "/{profitId}")
-    public R getInfo(@PathVariable("profitId") Long profitId)
-    {
-        CompanyProfit profit=companyProfitService.selectCompanyProfitById(profitId);
-        CompanyProfitLogs map=new CompanyProfitLogs();
-        map.setProfitId(profitId);
-        List<CompanyProfitLogs> logs= logsService.selectCompanyProfitLogsList(map);
-        return R.ok().put("profit",profit).put("logs",logs);
-    }
-
-    /**
-     * 新增提现
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyProfit:add')")
-    @Log(title = "提现", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyProfit companyProfit)
-    {
-        return toAjax(companyProfitService.insertCompanyProfit(companyProfit));
-    }
-
-    /**
-     * 修改提现
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyProfit:edit')")
-    @Log(title = "提现", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyProfit companyProfit)
-    {
-        return toAjax(companyProfitService.updateCompanyProfit(companyProfit));
-    }
-
-    /**
-     * 删除提现
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyProfit:remove')")
-    @Log(title = "提现", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{profitIds}")
-    public AjaxResult remove(@PathVariable Long[] profitIds)
-    {
-        return toAjax(companyProfitService.deleteCompanyProfitByIds(profitIds));
-    }
-
-    @PreAuthorize("@ss.hasPermi('company:companyProfit:audit1')")
-    @PostMapping("/audit1")
-    @Transactional
-    public R audit1(@RequestBody CompanyProfitAuditParam param)
-    {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        CompanyProfit profit=companyProfitService.selectCompanyProfitById(param.getProfitId());
-        if(profit.getProfitStatus()!=1){
-            return R.error("非法操作");
-        }
-        Company company=companyService.selectCompanyByIdForUpdate(profit.getCompanyId());
-        if(param.getStatus()==1){
-            profit.setRemark(param.getRemark());
-            profit.setProfitStatus(2);
-            profit.setUpdateTime(new Date());
-            companyProfitService.updateCompanyProfit(profit);
-            CompanyProfitLogs logs=new CompanyProfitLogs();
-            logs.setProfitId(profit.getProfitId());
-            logs.setReason(param.getRemark());
-            logs.setCreateTime(new Date());
-            logs.setTitle(loginUser.getUser().getNickName()+"审核通过");
-            logsService.insertCompanyProfitLogs(logs);
-        }
-        else if(param.getStatus()==0){
-            //驳回退款
-            profit.setRemark(param.getRemark());
-            profit.setProfitStatus(0);
-            profit.setUpdateTime(new Date());
-            companyProfitService.updateCompanyProfit(profit);
-            company.setMoney(company.getMoney().add(profit.getMoney()));
-            companyService.updateCompany(company);
-            CompanyMoneyLogs logs=new CompanyMoneyLogs();
-            logs.setCompanyId(company.getCompanyId());
-            logs.setMoney(profit.getMoney());
-            logs.setLogsType(8);
-            logs.setBalance(company.getMoney());
-            logs.setRemark("驳回退款:"+profit.getMoney());
-            logs.setCreateTime(new Date());
-            moneyLogsService.insertCompanyMoneyLogs(logs);
-
-            CompanyProfitLogs profitLogs=new CompanyProfitLogs();
-            profitLogs.setProfitId(profit.getProfitId());
-            profitLogs.setReason(param.getRemark());
-            profitLogs.setCreateTime(new Date());
-            profitLogs.setTitle(loginUser.getUser().getNickName()+"驳回退款");
-            logsService.insertCompanyProfitLogs(profitLogs);
-        }
-        return R.ok("操作成功");
-    }
-
-    @PreAuthorize("@ss.hasPermi('company:companyProfit:audit2')")
-    @PostMapping("/audit2")
-    @Transactional
-    public R audit2(@RequestBody CompanyProfitAuditParam param)
-    {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        CompanyProfit profit=companyProfitService.selectCompanyProfitById(param.getProfitId());
-        if(profit.getProfitStatus()!=2){
-            return R.error("非法操作");
-        }
-
-        if(param.getStatus()==1){
-            profit.setRemark(param.getRemark());
-            profit.setProfitStatus(4);
-            profit.setUpdateTime(new Date());
-            companyProfitService.updateCompanyProfit(profit);
-            CompanyProfitLogs logs=new CompanyProfitLogs();
-            logs.setProfitId(profit.getProfitId());
-            logs.setReason(param.getRemark());
-            logs.setCreateTime(new Date());
-            logs.setTitle(loginUser.getUser().getNickName()+"审核通过");
-            logsService.insertCompanyProfitLogs(logs);
-        }
-        else if(param.getStatus()==0){
-            //驳回退款
-            profit.setRemark(param.getRemark());
-            profit.setProfitStatus(0);
-            profit.setUpdateTime(new Date());
-            companyProfitService.updateCompanyProfit(profit);
-            Company company=companyService.selectCompanyByIdForUpdate(profit.getCompanyId());
-            company.setMoney(company.getMoney().add(profit.getMoney()));
-            companyService.updateCompany(company);
-            CompanyMoneyLogs logs=new CompanyMoneyLogs();
-            logs.setCompanyId(company.getCompanyId());
-            logs.setMoney(profit.getMoney());
-            logs.setLogsType(8);
-            logs.setBalance(company.getMoney());
-            logs.setRemark("驳回退款:"+profit.getMoney());
-            logs.setCreateTime(new Date());
-            moneyLogsService.insertCompanyMoneyLogs(logs);
-
-            CompanyProfitLogs profitLogs=new CompanyProfitLogs();
-            profitLogs.setProfitId(profit.getProfitId());
-            profitLogs.setReason(param.getRemark());
-            profitLogs.setCreateTime(new Date());
-            profitLogs.setTitle(loginUser.getUser().getNickName()+"驳回退款");
-            logsService.insertCompanyProfitLogs(profitLogs);
-        }
-        return R.ok("操作成功");
-    }
-
-    @PreAuthorize("@ss.hasPermi('company:companyProfit:audit3')")
-    @PostMapping("/audit3")
-    @Transactional
-    public R audit3(@RequestBody CompanyProfitAuditParam param)
-    {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        CompanyProfit profit=companyProfitService.selectCompanyProfitById(param.getProfitId());
-        if(profit.getProfitStatus()!=3){
-            return R.error("非法操作");
-        }
-        Company company=companyService.selectCompanyByIdForUpdate(profit.getCompanyId());
-        if(param.getStatus()==1){
-            profit.setRemark(param.getRemark());
-            profit.setProfitStatus(4);
-            profit.setUpdateTime(new Date());
-            profit.setImgUrl(param.getImgUrl());
-            companyProfitService.updateCompanyProfit(profit);
-            CompanyProfitLogs logs=new CompanyProfitLogs();
-            logs.setProfitId(profit.getProfitId());
-            logs.setReason(param.getRemark());
-            logs.setCreateTime(new Date());
-            logs.setTitle(loginUser.getUser().getNickName()+"审核通过");
-            logsService.insertCompanyProfitLogs(logs);
-        }
-        else if(param.getStatus()==0){
-            //驳回退款
-            profit.setRemark(param.getRemark());
-            profit.setProfitStatus(0);
-            profit.setUpdateTime(new Date());
-            companyProfitService.updateCompanyProfit(profit);
-            company.setMoney(company.getMoney().add(profit.getMoney()));
-            companyService.updateCompany(company);
-            CompanyMoneyLogs logs=new CompanyMoneyLogs();
-            logs.setCompanyId(company.getCompanyId());
-            logs.setMoney(profit.getMoney());
-            logs.setLogsType(8);
-            logs.setBalance(company.getMoney());
-            logs.setRemark("驳回退款:"+profit.getMoney());
-            logs.setCreateTime(new Date());
-            moneyLogsService.insertCompanyMoneyLogs(logs);
-
-            CompanyProfitLogs profitLogs=new CompanyProfitLogs();
-            profitLogs.setProfitId(profit.getProfitId());
-            profitLogs.setReason(param.getRemark());
-            profitLogs.setCreateTime(new Date());
-            profitLogs.setTitle(loginUser.getUser().getNickName()+"驳回退款");
-            logsService.insertCompanyProfitLogs(profitLogs);
-        }
-        return R.ok("操作成功");
-    }
-
-
-}

+ 0 - 144
fs-admin/src/main/java/com/fs/company/controller/CompanyRechargeController.java

@@ -1,144 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.domain.model.LoginUser;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.ServletUtils;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.Company;
-import com.fs.company.domain.CompanyMoneyLogs;
-import com.fs.company.domain.CompanyRecharge;
-import com.fs.company.service.ICompanyMoneyLogsService;
-import com.fs.company.service.ICompanyRechargeService;
-import com.fs.company.service.ICompanyService;
-import com.fs.company.vo.CompanyRechargeExportVO;
-import com.fs.company.vo.CompanyRechargeVO;
-import com.fs.framework.web.service.TokenService;
-import lombok.Synchronized;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.*;
-
-import java.math.BigDecimal;
-import java.util.Date;
-import java.util.List;
-
-/**
- * 充值Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/companyRecharge")
-public class CompanyRechargeController extends BaseController
-{
-    @Autowired
-    private TokenService tokenService;
-    @Autowired
-    private ICompanyRechargeService companyRechargeService;
-    @Autowired
-    private ICompanyService companyService;
-    @Autowired
-    private ICompanyMoneyLogsService moneyLogsService;
-    /**
-     * 查询充值列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRecharge:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyRecharge companyRecharge)
-    {
-        startPage();
-        List<CompanyRechargeVO> list = companyRechargeService.selectCompanyRechargeVOList(companyRecharge);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出充值列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRecharge:export')")
-    @Log(title = "充值", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyRecharge companyRecharge)
-    {
-        List<CompanyRechargeExportVO> list = companyRechargeService.selectCompanyRechargeExportList(companyRecharge);
-        ExcelUtil<CompanyRechargeExportVO> util = new ExcelUtil<CompanyRechargeExportVO>(CompanyRechargeExportVO.class);
-        return util.exportExcel(list, "公司充值明细");
-    }
-
-    /**
-     * 获取充值详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRecharge:query')")
-    @GetMapping(value = "/{rechargeId}")
-    public AjaxResult getInfo(@PathVariable("rechargeId") Long rechargeId)
-    {
-        return AjaxResult.success(companyRechargeService.selectCompanyRechargeById(rechargeId));
-    }
-
-    /**
-     * 新增充值
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRecharge:add')")
-    @Log(title = "充值", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyRecharge companyRecharge)
-    {
-        return toAjax(companyRechargeService.insertCompanyRecharge(companyRecharge));
-    }
-
-
-
-    /**
-     * 删除充值
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRecharge:remove')")
-    @Log(title = "充值", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{rechargeIds}")
-    public AjaxResult remove(@PathVariable Long[] rechargeIds)
-    {
-        return toAjax(companyRechargeService.deleteCompanyRechargeByIds(rechargeIds));
-    }
-
-
-
-    @PreAuthorize("@ss.hasPermi('company:companyRecharge:audit')")
-    @PostMapping("/audit")
-    @Transactional
-    @Synchronized
-    public R audit(@RequestBody CompanyRecharge param)
-    {
-        CompanyRecharge companyRecharge=companyRechargeService.selectCompanyRechargeById(param.getRechargeId());
-        if(companyRecharge.getIsAudit()!=0){
-            return R.error("非法操作");
-        }
-        companyRecharge.setIsAudit(param.getIsAudit());
-        companyRecharge.setRemark(param.getRemark());
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        if(companyRecharge.getIsAudit()==1){
-            Company company=companyService.selectCompanyById(companyRecharge.getCompanyId());
-            company.setMoney(company.getMoney().add(companyRecharge.getMoney()));
-            companyService.updateCompany(company);
-            CompanyMoneyLogs log=new CompanyMoneyLogs();
-            log.setCompanyId(companyRecharge.getCompanyId());
-            log.setMoney(companyRecharge.getMoney());
-            log.setRemark(companyRecharge.getRemark());
-            log.setLogsType(1);
-            log.setBalance(company.getMoney());
-            log.setCreateTime(new Date());
-            moneyLogsService.insertCompanyMoneyLogs(log);
-            companyRecharge.setPayTime(new Date());
-            companyRecharge.setStatus(1);
-        }
-        companyRecharge.setAuditTime(new Date());
-        companyRecharge.setAuditUserId(loginUser.getUser().getUserId());
-        companyRechargeService.updateCompanyRecharge(companyRecharge);
-        return R.ok("操作成功");
-
-    }
-}

+ 0 - 63
fs-admin/src/main/java/com/fs/company/controller/CompanyRedPackageController.java

@@ -1,63 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.*;
-import com.fs.company.service.ICompanyMoneyLogsService;
-import com.fs.company.service.ICompanyProfitLogsService;
-import com.fs.company.service.ICompanyProfitService;
-import com.fs.company.service.ICompanyService;
-import com.fs.framework.web.service.TokenService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 提现Controller
- *
- * @author fs
- * @date 2022-07-04
- */
-@RestController
-@RequestMapping("/company/redPackage")
-public class CompanyRedPackageController extends BaseController
-{
-    @Autowired
-    private ICompanyMoneyLogsService moneyLogsService;
-    /**
-     * 查询提现列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:redPackage:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyRedPackage companyRedPackage)
-    {
-        startPage();
-        List<CompanyRedPackage> list = moneyLogsService.selectCompanyRedPackageListVO(companyRedPackage);
-        String dateTime = companyRedPackage.getDateTime();
-        list.forEach(m -> m.setDateTime(dateTime));
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出提现列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:redPackage:export')")
-    @Log(title = "提现", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyRedPackage companyRedPackage)
-    {
-        List<CompanyRedPackage> list = moneyLogsService.selectCompanyRedPackageListVO(companyRedPackage);
-        String dateTime = companyRedPackage.getDateTime();
-        list.forEach(m -> m.setDateTime(dateTime));
-        ExcelUtil<CompanyRedPackage> util = new ExcelUtil<CompanyRedPackage>(CompanyRedPackage.class);
-        return util.exportExcel(list, "红包金额记录");
-    }
-
-
-}

+ 0 - 103
fs-admin/src/main/java/com/fs/company/controller/CompanyRedPacketBalanceLogsController.java

@@ -1,103 +0,0 @@
-package com.fs.company.controller;
-
-import java.util.List;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.enums.BusinessType;
-import com.fs.company.domain.CompanyRedPacketBalanceLogs;
-import com.fs.company.service.ICompanyRedPacketBalanceLogsService;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.common.core.page.TableDataInfo;
-
-/**
- * 企业红包余额记录Controller
- * 
- * @author fs
- * @date 2025-11-19
- */
-@RestController
-@RequestMapping("/company/companyRedPacketBalanceLogs")
-public class CompanyRedPacketBalanceLogsController extends BaseController
-{
-    @Autowired
-    private ICompanyRedPacketBalanceLogsService companyRedPacketBalanceLogsService;
-
-    /**
-     * 查询企业红包余额记录列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRedPacketBalanceLogs:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyRedPacketBalanceLogs companyRedPacketBalanceLogs)
-    {
-        startPage();
-        List<CompanyRedPacketBalanceLogs> list = companyRedPacketBalanceLogsService.selectCompanyRedPacketBalanceLogsList(companyRedPacketBalanceLogs);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出企业红包余额记录列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRedPacketBalanceLogs:export')")
-    @Log(title = "企业红包余额记录", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyRedPacketBalanceLogs companyRedPacketBalanceLogs)
-    {
-        List<CompanyRedPacketBalanceLogs> list = companyRedPacketBalanceLogsService.selectCompanyRedPacketBalanceLogsList(companyRedPacketBalanceLogs);
-        ExcelUtil<CompanyRedPacketBalanceLogs> util = new ExcelUtil<CompanyRedPacketBalanceLogs>(CompanyRedPacketBalanceLogs.class);
-        return util.exportExcel(list, "企业红包余额记录数据");
-    }
-
-    /**
-     * 获取企业红包余额记录详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRedPacketBalanceLogs:query')")
-    @GetMapping(value = "/{logsId}")
-    public AjaxResult getInfo(@PathVariable("logsId") Long logsId)
-    {
-        return AjaxResult.success(companyRedPacketBalanceLogsService.selectCompanyRedPacketBalanceLogsByLogsId(logsId));
-    }
-
-    /**
-     * 新增企业红包余额记录
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRedPacketBalanceLogs:add')")
-    @Log(title = "企业红包余额记录", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyRedPacketBalanceLogs companyRedPacketBalanceLogs)
-    {
-        return toAjax(companyRedPacketBalanceLogsService.insertCompanyRedPacketBalanceLogs(companyRedPacketBalanceLogs));
-    }
-
-    /**
-     * 修改企业红包余额记录
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRedPacketBalanceLogs:edit')")
-    @Log(title = "企业红包余额记录", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyRedPacketBalanceLogs companyRedPacketBalanceLogs)
-    {
-        return toAjax(companyRedPacketBalanceLogsService.updateCompanyRedPacketBalanceLogs(companyRedPacketBalanceLogs));
-    }
-
-    /**
-     * 删除企业红包余额记录
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRedPacketBalanceLogs:remove')")
-    @Log(title = "企业红包余额记录", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{logsIds}")
-    public AjaxResult remove(@PathVariable Long[] logsIds)
-    {
-        return toAjax(companyRedPacketBalanceLogsService.deleteCompanyRedPacketBalanceLogsByLogsIds(logsIds));
-    }
-}

+ 0 - 97
fs-admin/src/main/java/com/fs/company/controller/CompanyRoleController.java

@@ -1,97 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyRole;
-import com.fs.company.service.ICompanyRoleService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 角色信息Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/companyRole")
-public class CompanyRoleController extends BaseController
-{
-    @Autowired
-    private ICompanyRoleService companyRoleService;
-
-    /**
-     * 查询角色信息列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRole:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyRole companyRole)
-    {
-        startPage();
-        List<CompanyRole> list = companyRoleService.selectCompanyRoleList(companyRole);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出角色信息列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRole:export')")
-    @Log(title = "角色信息", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyRole companyRole)
-    {
-        List<CompanyRole> list = companyRoleService.selectCompanyRoleList(companyRole);
-        ExcelUtil<CompanyRole> util = new ExcelUtil<CompanyRole>(CompanyRole.class);
-        return util.exportExcel(list, "companyRole");
-    }
-
-    /**
-     * 获取角色信息详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRole:query')")
-    @GetMapping(value = "/{roleId}")
-    public AjaxResult getInfo(@PathVariable("roleId") Long roleId)
-    {
-        return AjaxResult.success(companyRoleService.selectCompanyRoleById(roleId));
-    }
-
-    /**
-     * 新增角色信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRole:add')")
-    @Log(title = "角色信息", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyRole companyRole)
-    {
-        return toAjax(companyRoleService.insertCompanyRole(companyRole));
-    }
-
-    /**
-     * 修改角色信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRole:edit')")
-    @Log(title = "角色信息", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyRole companyRole)
-    {
-        return toAjax(companyRoleService.updateCompanyRole(companyRole));
-    }
-
-    /**
-     * 删除角色信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRole:remove')")
-    @Log(title = "角色信息", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{roleIds}")
-    public AjaxResult remove(@PathVariable Long[] roleIds)
-    {
-        return toAjax(companyRoleService.deleteCompanyRoleByIds(roleIds));
-    }
-}

+ 0 - 97
fs-admin/src/main/java/com/fs/company/controller/CompanyRoleDeptController.java

@@ -1,97 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyRoleDept;
-import com.fs.company.service.ICompanyRoleDeptService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 角色和部门关联Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/companyRoleDept")
-public class CompanyRoleDeptController extends BaseController
-{
-    @Autowired
-    private ICompanyRoleDeptService companyRoleDeptService;
-
-    /**
-     * 查询角色和部门关联列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRoleDept:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyRoleDept companyRoleDept)
-    {
-        startPage();
-        List<CompanyRoleDept> list = companyRoleDeptService.selectCompanyRoleDeptList(companyRoleDept);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出角色和部门关联列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRoleDept:export')")
-    @Log(title = "角色和部门关联", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyRoleDept companyRoleDept)
-    {
-        List<CompanyRoleDept> list = companyRoleDeptService.selectCompanyRoleDeptList(companyRoleDept);
-        ExcelUtil<CompanyRoleDept> util = new ExcelUtil<CompanyRoleDept>(CompanyRoleDept.class);
-        return util.exportExcel(list, "companyRoleDept");
-    }
-
-    /**
-     * 获取角色和部门关联详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRoleDept:query')")
-    @GetMapping(value = "/{roleId}")
-    public AjaxResult getInfo(@PathVariable("roleId") Long roleId)
-    {
-        return AjaxResult.success(companyRoleDeptService.selectCompanyRoleDeptById(roleId));
-    }
-
-    /**
-     * 新增角色和部门关联
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRoleDept:add')")
-    @Log(title = "角色和部门关联", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyRoleDept companyRoleDept)
-    {
-        return toAjax(companyRoleDeptService.insertCompanyRoleDept(companyRoleDept));
-    }
-
-    /**
-     * 修改角色和部门关联
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRoleDept:edit')")
-    @Log(title = "角色和部门关联", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyRoleDept companyRoleDept)
-    {
-        return toAjax(companyRoleDeptService.updateCompanyRoleDept(companyRoleDept));
-    }
-
-    /**
-     * 删除角色和部门关联
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRoleDept:remove')")
-    @Log(title = "角色和部门关联", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{roleIds}")
-    public AjaxResult remove(@PathVariable Long[] roleIds)
-    {
-        return toAjax(companyRoleDeptService.deleteCompanyRoleDeptByIds(roleIds));
-    }
-}

+ 0 - 97
fs-admin/src/main/java/com/fs/company/controller/CompanyRoleMenuController.java

@@ -1,97 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyRoleMenu;
-import com.fs.company.service.ICompanyRoleMenuService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 角色和菜单关联Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/companyRoleMenu")
-public class CompanyRoleMenuController extends BaseController
-{
-    @Autowired
-    private ICompanyRoleMenuService companyRoleMenuService;
-
-    /**
-     * 查询角色和菜单关联列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRoleMenu:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyRoleMenu companyRoleMenu)
-    {
-        startPage();
-        List<CompanyRoleMenu> list = companyRoleMenuService.selectCompanyRoleMenuList(companyRoleMenu);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出角色和菜单关联列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRoleMenu:export')")
-    @Log(title = "角色和菜单关联", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyRoleMenu companyRoleMenu)
-    {
-        List<CompanyRoleMenu> list = companyRoleMenuService.selectCompanyRoleMenuList(companyRoleMenu);
-        ExcelUtil<CompanyRoleMenu> util = new ExcelUtil<CompanyRoleMenu>(CompanyRoleMenu.class);
-        return util.exportExcel(list, "companyRoleMenu");
-    }
-
-    /**
-     * 获取角色和菜单关联详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRoleMenu:query')")
-    @GetMapping(value = "/{roleId}")
-    public AjaxResult getInfo(@PathVariable("roleId") Long roleId)
-    {
-        return AjaxResult.success(companyRoleMenuService.selectCompanyRoleMenuById(roleId));
-    }
-
-    /**
-     * 新增角色和菜单关联
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRoleMenu:add')")
-    @Log(title = "角色和菜单关联", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyRoleMenu companyRoleMenu)
-    {
-        return toAjax(companyRoleMenuService.insertCompanyRoleMenu(companyRoleMenu));
-    }
-
-    /**
-     * 修改角色和菜单关联
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRoleMenu:edit')")
-    @Log(title = "角色和菜单关联", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyRoleMenu companyRoleMenu)
-    {
-        return toAjax(companyRoleMenuService.updateCompanyRoleMenu(companyRoleMenu));
-    }
-
-    /**
-     * 删除角色和菜单关联
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyRoleMenu:remove')")
-    @Log(title = "角色和菜单关联", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{roleIds}")
-    public AjaxResult remove(@PathVariable Long[] roleIds)
-    {
-        return toAjax(companyRoleMenuService.deleteCompanyRoleMenuByIds(roleIds));
-    }
-}

+ 0 - 98
fs-admin/src/main/java/com/fs/company/controller/CompanySmsController.java

@@ -1,98 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanySms;
-import com.fs.company.service.ICompanySmsService;
-import com.fs.company.vo.CompanySmsListVO;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 公司短信Controller
- *
- * @author fs
- * @date 2023-01-09
- */
-@RestController
-@RequestMapping("/company/companySms")
-public class CompanySmsController extends BaseController
-{
-    @Autowired
-    private ICompanySmsService companySmsService;
-
-    /**
-     * 查询公司短信列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySms:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanySms companySms)
-    {
-        startPage();
-        List<CompanySmsListVO> list = companySmsService.selectCompanySmsList(companySms);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出公司短信列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySms:export')")
-    @Log(title = "公司短信", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanySms companySms)
-    {
-        List<CompanySmsListVO> list = companySmsService.selectCompanySmsList(companySms);
-        ExcelUtil<CompanySmsListVO> util = new ExcelUtil<CompanySmsListVO>(CompanySmsListVO.class);
-        return util.exportExcel(list, "companySms");
-    }
-
-    /**
-     * 获取公司短信详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySms:query')")
-    @GetMapping(value = "/{smsId}")
-    public AjaxResult getInfo(@PathVariable("smsId") Long smsId)
-    {
-        return AjaxResult.success(companySmsService.selectCompanySmsById(smsId));
-    }
-
-    /**
-     * 新增公司短信
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySms:add')")
-    @Log(title = "公司短信", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanySms companySms)
-    {
-        return toAjax(companySmsService.insertCompanySms(companySms));
-    }
-
-    /**
-     * 修改公司短信
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySms:edit')")
-    @Log(title = "公司短信", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanySms companySms)
-    {
-        return toAjax(companySmsService.updateCompanySms(companySms));
-    }
-
-    /**
-     * 删除公司短信
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySms:remove')")
-    @Log(title = "公司短信", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{smsIds}")
-    public AjaxResult remove(@PathVariable Long[] smsIds)
-    {
-        return toAjax(companySmsService.deleteCompanySmsByIds(smsIds));
-    }
-}

+ 0 - 122
fs-admin/src/main/java/com/fs/company/controller/CompanySmsLogsController.java

@@ -1,122 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.StringUtils;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanySmsLogs;
-import com.fs.company.param.CompanySmsLogsListParam;
-import com.fs.company.service.ICompanySmsLogsService;
-import com.fs.company.vo.CompanySmsLogsListVO;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 短信发送记录Controller
- *
- * @author fs
- * @date 2023-01-09
- */
-@RestController
-@RequestMapping("/company/companySmsLogs")
-public class CompanySmsLogsController extends BaseController
-{
-    @Autowired
-    private ICompanySmsLogsService companySmsLogsService;
-
-    /**
-     * 查询短信发送记录列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsLogs:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanySmsLogsListParam companySmsLogs)
-    {
-        startPage();
-        if(!StringUtils.isEmpty(companySmsLogs.getCreateTimeRange())){
-            companySmsLogs.setCreateTimeList(companySmsLogs.getCreateTimeRange().split("--"));
-        }
-        List<CompanySmsLogsListVO> list = companySmsLogsService.selectCompanySmsLogsList(companySmsLogs);
-        if (list != null) {
-            for (CompanySmsLogsListVO vo : list) {
-                if(vo.getPhone()!=null){
-                    vo.setPhone(vo.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
-                }
-
-            }
-        }
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出短信发送记录列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsLogs:export')")
-    @Log(title = "短信发送记录", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanySmsLogsListParam companySmsLogs)
-    {
-        if(!StringUtils.isEmpty(companySmsLogs.getCreateTimeRange())){
-            companySmsLogs.setCreateTimeList(companySmsLogs.getCreateTimeRange().split("--"));
-        }
-        List<CompanySmsLogsListVO> list = companySmsLogsService.selectCompanySmsLogsList(companySmsLogs);
-        if (list != null) {
-            for (CompanySmsLogsListVO vo : list) {
-                if(vo.getPhone()!=null){
-                    vo.setPhone(vo.getPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2"));
-                }
-
-            }
-        }
-        ExcelUtil<CompanySmsLogsListVO> util = new ExcelUtil<CompanySmsLogsListVO>(CompanySmsLogsListVO.class);
-        return util.exportExcel(list, "companySmsLogs");
-    }
-
-    /**
-     * 获取短信发送记录详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsLogs:query')")
-    @GetMapping(value = "/{logsId}")
-    public AjaxResult getInfo(@PathVariable("logsId") Long logsId)
-    {
-        return AjaxResult.success(companySmsLogsService.selectCompanySmsLogsById(logsId));
-    }
-
-    /**
-     * 新增短信发送记录
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsLogs:add')")
-    @Log(title = "短信发送记录", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanySmsLogs companySmsLogs)
-    {
-        return toAjax(companySmsLogsService.insertCompanySmsLogs(companySmsLogs));
-    }
-
-    /**
-     * 修改短信发送记录
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsLogs:edit')")
-    @Log(title = "短信发送记录", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanySmsLogs companySmsLogs)
-    {
-        return toAjax(companySmsLogsService.updateCompanySmsLogs(companySmsLogs));
-    }
-
-    /**
-     * 删除短信发送记录
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsLogs:remove')")
-    @Log(title = "短信发送记录", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{logsIds}")
-    public AjaxResult remove(@PathVariable Long[] logsIds)
-    {
-        return toAjax(companySmsLogsService.deleteCompanySmsLogsByIds(logsIds));
-    }
-}

+ 0 - 99
fs-admin/src/main/java/com/fs/company/controller/CompanySmsOrderController.java

@@ -1,99 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanySmsOrder;
-import com.fs.company.param.CompanySmsOrderListParam;
-import com.fs.company.service.ICompanySmsOrderService;
-import com.fs.company.vo.CompanySmsOrderListVO;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 短信购买订单Controller
- *
- * @author fs
- * @date 2023-01-09
- */
-@RestController
-@RequestMapping("/company/companySmsOrder")
-public class CompanySmsOrderController extends BaseController
-{
-    @Autowired
-    private ICompanySmsOrderService companySmsOrderService;
-
-    /**
-     * 查询短信购买订单列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsOrder:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanySmsOrderListParam param)
-    {
-        startPage();
-        List<CompanySmsOrderListVO> list = companySmsOrderService.selectCompanySmsOrderList(param);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出短信购买订单列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsOrder:export')")
-    @Log(title = "短信购买订单", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanySmsOrderListParam param)
-    {
-        List<CompanySmsOrderListVO> list = companySmsOrderService.selectCompanySmsOrderList(param);
-        ExcelUtil<CompanySmsOrderListVO> util = new ExcelUtil<CompanySmsOrderListVO>(CompanySmsOrderListVO.class);
-        return util.exportExcel(list, "companySmsOrder");
-    }
-
-    /**
-     * 获取短信购买订单详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsOrder:query')")
-    @GetMapping(value = "/{orderId}")
-    public AjaxResult getInfo(@PathVariable("orderId") Long orderId)
-    {
-        return AjaxResult.success(companySmsOrderService.selectCompanySmsOrderById(orderId));
-    }
-
-    /**
-     * 新增短信购买订单
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsOrder:add')")
-    @Log(title = "短信购买订单", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanySmsOrder companySmsOrder)
-    {
-        return toAjax(companySmsOrderService.insertCompanySmsOrder(companySmsOrder));
-    }
-
-    /**
-     * 修改短信购买订单
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsOrder:edit')")
-    @Log(title = "短信购买订单", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanySmsOrder companySmsOrder)
-    {
-        return toAjax(companySmsOrderService.updateCompanySmsOrder(companySmsOrder));
-    }
-
-    /**
-     * 删除短信购买订单
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsOrder:remove')")
-    @Log(title = "短信购买订单", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{orderIds}")
-    public AjaxResult remove(@PathVariable Long[] orderIds)
-    {
-        return toAjax(companySmsOrderService.deleteCompanySmsOrderByIds(orderIds));
-    }
-}

+ 0 - 97
fs-admin/src/main/java/com/fs/company/controller/CompanySmsPackageController.java

@@ -1,97 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanySmsPackage;
-import com.fs.company.service.ICompanySmsPackageService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 短信套餐包Controller
- *
- * @author fs
- * @date 2023-01-09
- */
-@RestController
-@RequestMapping("/company/companySmsPackage")
-public class CompanySmsPackageController extends BaseController
-{
-    @Autowired
-    private ICompanySmsPackageService companySmsPackageService;
-
-    /**
-     * 查询短信套餐包列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsPackage:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanySmsPackage companySmsPackage)
-    {
-        startPage();
-        List<CompanySmsPackage> list = companySmsPackageService.selectCompanySmsPackageList(companySmsPackage);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出短信套餐包列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsPackage:export')")
-    @Log(title = "短信套餐包", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanySmsPackage companySmsPackage)
-    {
-        List<CompanySmsPackage> list = companySmsPackageService.selectCompanySmsPackageList(companySmsPackage);
-        ExcelUtil<CompanySmsPackage> util = new ExcelUtil<CompanySmsPackage>(CompanySmsPackage.class);
-        return util.exportExcel(list, "companySmsPackage");
-    }
-
-    /**
-     * 获取短信套餐包详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsPackage:query')")
-    @GetMapping(value = "/{packageId}")
-    public AjaxResult getInfo(@PathVariable("packageId") Long packageId)
-    {
-        return AjaxResult.success(companySmsPackageService.selectCompanySmsPackageById(packageId));
-    }
-
-    /**
-     * 新增短信套餐包
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsPackage:add')")
-    @Log(title = "短信套餐包", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanySmsPackage companySmsPackage)
-    {
-        return toAjax(companySmsPackageService.insertCompanySmsPackage(companySmsPackage));
-    }
-
-    /**
-     * 修改短信套餐包
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsPackage:edit')")
-    @Log(title = "短信套餐包", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanySmsPackage companySmsPackage)
-    {
-        return toAjax(companySmsPackageService.updateCompanySmsPackage(companySmsPackage));
-    }
-
-    /**
-     * 删除短信套餐包
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsPackage:remove')")
-    @Log(title = "短信套餐包", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{packageIds}")
-    public AjaxResult remove(@PathVariable Long[] packageIds)
-    {
-        return toAjax(companySmsPackageService.deleteCompanySmsPackageByIds(packageIds));
-    }
-}

+ 0 - 115
fs-admin/src/main/java/com/fs/company/controller/CompanySmsTempController.java

@@ -1,115 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanySmsTemp;
-import com.fs.company.service.ICompanySmsTempService;
-import com.fs.company.vo.CompanySmsTempListVO;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 短信模板Controller
- *
- * @author fs
- * @date 2023-01-09
- */
-@RestController
-@RequestMapping("/company/companySmsTemp")
-public class CompanySmsTempController extends BaseController
-{
-    @Autowired
-    private ICompanySmsTempService companySmsTempService;
-
-    /**
-     * 查询短信模板列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsTemp:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanySmsTemp companySmsTemp)
-    {
-        startPage();
-        List<CompanySmsTempListVO> list = companySmsTempService.selectCompanySmsTempListVO(companySmsTemp);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出短信模板列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsTemp:export')")
-    @Log(title = "短信模板", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanySmsTemp companySmsTemp)
-    {
-        List<CompanySmsTemp> list = companySmsTempService.selectCompanySmsTempList(companySmsTemp);
-        ExcelUtil<CompanySmsTemp> util = new ExcelUtil<CompanySmsTemp>(CompanySmsTemp.class);
-        return util.exportExcel(list, "companySmsTemp");
-    }
-
-    /**
-     * 获取短信模板详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsTemp:query')")
-    @GetMapping(value = "/{tempId}")
-    public AjaxResult getInfo(@PathVariable("tempId") Long tempId)
-    {
-        return AjaxResult.success(companySmsTempService.selectCompanySmsTempById(tempId));
-    }
-
-    /**
-     * 新增短信模板
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsTemp:add')")
-    @Log(title = "短信模板", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanySmsTemp companySmsTemp)
-    {
-        return toAjax(companySmsTempService.insertCompanySmsTemp(companySmsTemp));
-    }
-
-    /**
-     * 修改短信模板
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsTemp:edit')")
-    @Log(title = "短信模板", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanySmsTemp companySmsTemp)
-    {
-        return toAjax(companySmsTempService.updateCompanySmsTemp(companySmsTemp));
-    }
-
-    /**
-     * 删除短信模板
-     */
-    @PreAuthorize("@ss.hasPermi('company:companySmsTemp:remove')")
-    @Log(title = "短信模板", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{tempIds}")
-    public AjaxResult remove(@PathVariable Long[] tempIds)
-    {
-        return toAjax(companySmsTempService.deleteCompanySmsTempByIds(tempIds));
-    }
-
-
-    @PreAuthorize("@ss.hasPermi('company:companySmsTemp:audit')")
-    @PostMapping("/audit")
-    public R audit(@RequestBody CompanySmsTemp companySmsTemp)
-    {
-        CompanySmsTemp map=new CompanySmsTemp();
-        map.setIsAudit(1);
-        map.setTempId(companySmsTemp.getTempId());
-        if(companySmsTempService.updateCompanySmsTemp(map)>0){
-            return R.ok("操作成功");
-        }
-        else{
-            return R.error("操作失败");
-        }
-    }
-}

+ 0 - 793
fs-admin/src/main/java/com/fs/company/controller/CompanyStatisticsController.java

@@ -1,793 +0,0 @@
-package com.fs.company.controller;
-
-import com.alibaba.fastjson.JSONObject;
-import com.fs.common.annotation.Excel;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.utils.DateUtils;
-import com.fs.common.utils.StringUtils;
-import com.fs.common.utils.TimeUtils;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyUser;
-import com.fs.company.param.CompanyStatisticsParam;
-import com.fs.company.param.FsStoreStatisticsParam;
-import com.fs.company.service.ICompanySmsLogsService;
-import com.fs.company.service.ICompanyUserService;
-import com.fs.company.service.ICompanyVoiceLogsService;
-import com.fs.company.vo.*;
-import com.fs.course.param.FsCourseWatchLogStatisticsListParam;
-import com.fs.course.service.IFinishCourseStatisticsSyncService;
-import com.fs.course.service.IFsCourseWatchLogService;
-import com.fs.course.vo.FsCourseReportVO;
-import com.fs.crm.param.CrmCustomerStatisticsParam;
-import com.fs.crm.service.ICrmCustomerService;
-import com.fs.crm.service.ICrmCustomerVisitService;
-import com.fs.crm.vo.CrmCustomerStatisticsVO;
-import com.fs.crm.vo.CrmCustomerVisitStatisticsVO;
-import com.fs.his.dto.FsStoreOrderAmountScrmStatsQueryDto;
-import com.fs.his.dto.FsStoreOrderAmountStatsQueryDto;
-import com.fs.his.service.IFsStoreAfterSalesService;
-import com.fs.his.service.IFsStoreOrderService;
-import com.fs.his.service.IFsStorePaymentService;
-import com.fs.his.vo.FsStoreOrderAmountScrmStatsVo;
-import com.fs.his.vo.FsStoreOrderAmountStatsVo;
-import com.fs.hisStore.service.IFsStoreOrderScrmService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.lang.reflect.Field;
-import java.math.BigDecimal;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * 统计
- *
- * @author fs
- * @date 2021-03-22
- */
-@RestController
-@RequestMapping("/company/statistics")
-public class CompanyStatisticsController extends BaseController
-{
-
-    @Autowired
-    private ICompanyUserService userService;
-
-    @Autowired
-    private IFsStoreOrderService storeOrderService;
-
-    @Autowired
-    private IFsStoreAfterSalesService storeAfterSalesService;
-
-    @Autowired
-    private IFsStorePaymentService storePaymentService;
-    @Autowired
-    private ICompanyVoiceLogsService voiceLogsService;
-    @Autowired
-    private ICompanySmsLogsService smsLogsService;
-
-
-    @Autowired
-    private ICrmCustomerService crmCustomerService;
-    @Autowired
-    private ICrmCustomerVisitService crmCustomerVisitService;
-
-    //app商城订单接口Service
-    @Autowired
-    private IFsStoreOrderScrmService fsStoreOrderScrmService;
-
-    @Autowired
-    private IFsCourseWatchLogService fsCourseWatchLogService;
-
-    @Autowired
-    private IFinishCourseStatisticsSyncService finishCourseStatisticsSyncService;
-    @GetMapping("/storeOrder")
-    public R storeOrder(FsStoreStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取部门下的所有用户
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-        if(param.getUsers()!=null&&param.getUsers().length>0){
-            List<FsStoreOrderStatisticsVO> list= storeOrderService.selectFsStoreOrderStatisticsList(param);
-
-            TimeUtils.TimeEntity timeEntity= TimeUtils.parseTime(param.getType().toString(),param.getStartTime(),param.getEndTime());
-            timeEntity.setUserIds(param.getUsers());
-            Integer cycleNum = timeEntity.getCycleNum();
-            Integer beginTime = timeEntity.getBeginTime();
-            List<Integer> timeList = new ArrayList<>();
-            for (int i = 1; i <= cycleNum; i++) {
-                timeList.add(beginTime);
-                beginTime = TimeUtils.formatTime(beginTime);
-            }
-            List<JSONObject> jsonObjectList = storeOrderService.selectFsStoreOrderCounts(timeEntity.toMap());
-            List<String> dates = jsonObjectList.stream().map(jsonObject -> jsonObject.getString("type")).collect(Collectors.toList());
-            List<Integer> orderCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("orderCount")).collect(Collectors.toList());
-            List<Integer> payPrice = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("payPrice")).collect(Collectors.toList());
-            return R.ok().put("list",list).put("dates",dates).put("orderCount",orderCount).put("payPrice",payPrice);
-        }
-        else {
-            return R.ok("未查找到数据");
-        }
-    }
-
-
-    @GetMapping("/packageOrder")
-    public R storePackageOrder(FsStoreStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取部门下的所有用户
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-        if(param.getUsers()!=null&&param.getUsers().length>0){
-            List<FsStoreOrderStatisticsVO> list= storeOrderService.selectFsPackageOrderStatisticsList(param);
-
-            TimeUtils.TimeEntity timeEntity= TimeUtils.parseTime(param.getType().toString(),param.getStartTime(),param.getEndTime());
-            timeEntity.setUserIds(param.getUsers());
-            Integer cycleNum = timeEntity.getCycleNum();
-            Integer beginTime = timeEntity.getBeginTime();
-            List<Integer> timeList = new ArrayList<>();
-            for (int i = 1; i <= cycleNum; i++) {
-                timeList.add(beginTime);
-                beginTime = TimeUtils.formatTime(beginTime);
-            }
-            List<JSONObject> jsonObjectList = storeOrderService.selectFsPackageOrderCounts(timeEntity.toMap());
-            List<String> dates = jsonObjectList.stream().map(jsonObject -> jsonObject.getString("type")).collect(Collectors.toList());
-            List<Integer> orderCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("orderCount")).collect(Collectors.toList());
-            List<Integer> payPrice = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("payPrice")).collect(Collectors.toList());
-            return R.ok().put("list",list).put("dates",dates).put("orderCount",orderCount).put("payPrice",payPrice);
-        }
-        else {
-            return R.ok("未查找到数据");
-        }
-    }
-
-    @GetMapping("/afterSalesOrder")
-    public R afterSalesOrder(FsStoreStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取部门下的所有用户
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-        if(param.getUsers()!=null&&param.getUsers().length>0){
-            List<FsStoreOrderStatisticsVO> list= storeAfterSalesService.selectFsStoreAfterSalesServiceStatisticsList(param);
-
-            TimeUtils.TimeEntity timeEntity= TimeUtils.parseTime(param.getType().toString(),param.getStartTime(),param.getEndTime());
-            timeEntity.setUserIds(param.getUsers());
-            Integer cycleNum = timeEntity.getCycleNum();
-            Integer beginTime = timeEntity.getBeginTime();
-            List<Integer> timeList = new ArrayList<>();
-            for (int i = 1; i <= cycleNum; i++) {
-                timeList.add(beginTime);
-                beginTime = TimeUtils.formatTime(beginTime);
-            }
-            Map<String, Object> map = timeEntity.toMap();
-            if (StringUtils.isNotBlank(param.getStartTime())){
-                map.put("startTime",param.getStartTime());
-            }
-            if (StringUtils.isNotBlank(param.getEndTime())){
-                map.put("endTime",param.getEndTime());
-            }
-            List<JSONObject> jsonObjectList = storeAfterSalesService.selectFsStoreAfterSales(map);
-            List<String> dates = jsonObjectList.stream().map(jsonObject -> jsonObject.getString("type")).collect(Collectors.toList());
-            List<Integer> orderCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("orderCount")).collect(Collectors.toList());
-            List<BigDecimal> payPrice = jsonObjectList.stream().map(jsonObject -> jsonObject.getBigDecimal("payPrice")).collect(Collectors.toList());
-            return R.ok().put("list",list).put("dates",dates).put("orderCount",orderCount).put("payPrice",payPrice);
-        }
-        else {
-            return R.ok("未查找到数据");
-        }
-    }
-
-
-    @GetMapping("/inquiryOrder")
-    public R storeInquiryOrder(FsStoreStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取部门下的所有用户
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-        if(param.getUsers()!=null&&param.getUsers().length>0){
-            List<FsStoreOrderStatisticsVO> list= storeOrderService.selectFsInquiryOrderStatisticsList(param);
-
-            TimeUtils.TimeEntity timeEntity= TimeUtils.parseTime(param.getType().toString(),param.getStartTime(),param.getEndTime());
-            timeEntity.setUserIds(param.getUsers());
-            Integer cycleNum = timeEntity.getCycleNum();
-            Integer beginTime = timeEntity.getBeginTime();
-            List<Integer> timeList = new ArrayList<>();
-            for (int i = 1; i <= cycleNum; i++) {
-                timeList.add(beginTime);
-                beginTime = TimeUtils.formatTime(beginTime);
-            }
-            List<JSONObject> jsonObjectList = storeOrderService.selectFsInquiryOrderCounts(timeEntity.toMap());
-            List<String> dates = jsonObjectList.stream().map(jsonObject -> jsonObject.getString("type")).collect(Collectors.toList());
-            List<Integer> orderCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("orderCount")).collect(Collectors.toList());
-            List<Integer> payPrice = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("payPrice")).collect(Collectors.toList());
-            return R.ok().put("list",list).put("dates",dates).put("orderCount",orderCount).put("payPrice",payPrice);
-        }
-        else {
-            return R.ok("未查找到数据");
-        }
-    }
-
-
-
-
-    @GetMapping("/exportStoreOrder")
-    public AjaxResult exportStoreOrder(FsStoreStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取所有员工
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-
-        List<FsStoreOrderStatisticsVO> list= storeOrderService.selectFsStoreOrderStatisticsList(param);
-
-        ExcelUtil<FsStoreOrderStatisticsVO> util = new ExcelUtil<FsStoreOrderStatisticsVO>(FsStoreOrderStatisticsVO.class);
-        return util.exportExcel(list, "orderLogs");
-    }
-
-    @GetMapping("/exportPackageOrder")
-    public AjaxResult exportPackageOrder(FsStoreStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取所有员工
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-
-        List<FsStoreOrderStatisticsVO> list= storeOrderService.selectFsPackageOrderStatisticsList(param);
-
-        ExcelUtil<FsStoreOrderStatisticsVO> util = new ExcelUtil<FsStoreOrderStatisticsVO>(FsStoreOrderStatisticsVO.class);
-        return util.exportExcel(list, "orderLogs");
-    }
-
-    @GetMapping("/exportAfterSalesOrder")
-    public AjaxResult exportAfterSalesOrder(FsStoreStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取所有员工
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-
-        List<FsStoreOrderStatisticsVO> list= storeAfterSalesService.selectFsStoreAfterSalesServiceStatisticsList(param);
-
-        ExcelUtil<FsStoreOrderStatisticsVO> util = new ExcelUtil<FsStoreOrderStatisticsVO>(FsStoreOrderStatisticsVO.class);
-        return util.exportExcel(list, "orderLogs");
-    }
-
-
-    @GetMapping("/exportInquiryOrder")
-    public AjaxResult exportInquiryOrder(FsStoreStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取所有员工
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-
-        List<FsStoreOrderStatisticsVO> list= storeOrderService.selectFsInquiryOrderStatisticsList(param);
-
-        ExcelUtil<FsStoreOrderStatisticsVO> util = new ExcelUtil<FsStoreOrderStatisticsVO>(FsStoreOrderStatisticsVO.class);
-        return util.exportExcel(list, "orderLogs");
-    }
-
-    @GetMapping("/storePayment")
-    public R storePayment(FsStoreStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取部门下的所有用户
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-        if(param.getUsers()!=null&&param.getUsers().length>0){
-            List<FsStorePaymentStatisticsVO> list= storePaymentService.selectFsStorePaymentStatisticsList(param);
-            TimeUtils.TimeEntity timeEntity= TimeUtils.parseTime(param.getType().toString(),param.getStartTime(),param.getEndTime());
-            timeEntity.setUserIds(param.getUsers());
-            Integer cycleNum = timeEntity.getCycleNum();
-            Integer beginTime = timeEntity.getBeginTime();
-            List<Integer> timeList = new ArrayList<>();
-            for (int i = 1; i <= cycleNum; i++) {
-                timeList.add(beginTime);
-                beginTime = TimeUtils.formatTime(beginTime);
-            }
-            List<JSONObject> jsonObjectList = storePaymentService.selectFsStorePaymentCounts(timeEntity.toMap());
-            List<String> dates = jsonObjectList.stream().map(jsonObject -> jsonObject.getString("type")).collect(Collectors.toList());
-            List<Integer> orderCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("orderCount")).collect(Collectors.toList());
-            List<Integer> payMoney = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("payMoney")).collect(Collectors.toList());
-            return R.ok().put("list",list).put("dates",dates).put("orderCount",orderCount).put("payMoney",payMoney);
-        }
-        else {
-            return R.ok("未查找到数据");
-        }
-    }
-
-    @GetMapping("/exportStorePayment")
-    public AjaxResult exportStorePayment(FsStoreStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取所有员工
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.selectCompanyUserList(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-
-        List<FsStorePaymentStatisticsVO> list= storePaymentService.selectFsStorePaymentStatisticsList(param);
-
-        ExcelUtil<FsStorePaymentStatisticsVO> util = new ExcelUtil<FsStorePaymentStatisticsVO>(FsStorePaymentStatisticsVO.class);
-        return util.exportExcel(list, "paymentLogs");
-    }
-
-//分割
-
-    @GetMapping("/voiceLogs")
-    public R voiceLogs(CompanyStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取部门下的所有用户
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-        if(param.getUsers()!=null&&param.getUsers().length>0){
-            List<CompanyVoiceLogsStatisticsVO> list= voiceLogsService.selectVoiceLogsStatisticsList(param);
-            if(list!=null){
-                for(CompanyVoiceLogsStatisticsVO vo:list){
-                    double f1 = new BigDecimal((float)vo.getCallSuccessCount()/vo.getCallCount()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()*100;
-                    vo.setCallRate(f1);
-                }
-            }
-            TimeUtils.TimeEntity timeEntity= TimeUtils.parseTime(param.getType().toString(),param.getStartTime(),param.getEndTime());
-            timeEntity.setUserIds(param.getUsers());
-            Integer cycleNum = timeEntity.getCycleNum();
-            Integer beginTime = timeEntity.getBeginTime();
-            List<Integer> timeList = new ArrayList<>();
-            for (int i = 1; i <= cycleNum; i++) {
-                timeList.add(beginTime);
-                beginTime = TimeUtils.formatTime(beginTime);
-            }
-            List<JSONObject> jsonObjectList = voiceLogsService.selectVoiceLogsTotalCount(timeEntity.toMap());
-            List<String> dates = jsonObjectList.stream().map(jsonObject -> jsonObject.getString("type")).collect(Collectors.toList());
-            List<Integer> callCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("callCount")).collect(Collectors.toList());
-            List<Integer> callSuccessCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("callSuccessCount")).collect(Collectors.toList());
-            List<Integer> times = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("times")).collect(Collectors.toList());
-            List<Integer> billingTime = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("billingTime")).collect(Collectors.toList());
-            return R.ok().put("list",list).put("dates",dates).put("callCount",callCount).put("callSuccessCount",callSuccessCount).put("times",times).put("billingTime",billingTime);
-        }
-        else {
-            return R.ok("未查找到数据");
-        }
-    }
-
-    @GetMapping("/exportVoiceLogs")
-    public AjaxResult exportVoiceLogs(CompanyStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取所有员工
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-
-        List<CompanyVoiceLogsStatisticsVO> list= voiceLogsService.selectVoiceLogsStatisticsList(param);
-        if(list!=null){
-            for(CompanyVoiceLogsStatisticsVO vo:list){
-                double f1 = new BigDecimal((float)vo.getCallSuccessCount()/vo.getCallCount()).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()*100;
-                vo.setCallRate(f1);
-            }
-        }
-        ExcelUtil<CompanyVoiceLogsStatisticsVO> util = new ExcelUtil<CompanyVoiceLogsStatisticsVO>(CompanyVoiceLogsStatisticsVO.class);
-        return util.exportExcel(list, "voiceLogs");
-    }
-
-
-
-
-
-
-
-
-    @GetMapping("/smsLogs")
-    public R smsLogs(CompanyStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取部门下的所有用户
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-        if(param.getUsers()!=null&&param.getUsers().length>0){
-            List<CompanySmsLogsStatisticsVO> list= smsLogsService.selectSmsLogsStatisticsList(param);
-            TimeUtils.TimeEntity timeEntity= TimeUtils.parseTime(param.getType().toString(),param.getStartTime(),param.getEndTime());
-            timeEntity.setUserIds(param.getUsers());
-            Integer cycleNum = timeEntity.getCycleNum();
-            Integer beginTime = timeEntity.getBeginTime();
-            List<Integer> timeList = new ArrayList<>();
-            for (int i = 1; i <= cycleNum; i++) {
-                timeList.add(beginTime);
-                beginTime = TimeUtils.formatTime(beginTime);
-            }
-            List<JSONObject> jsonObjectList = smsLogsService.selectSmsLogsCounts(timeEntity.toMap());
-            List<String> dates = jsonObjectList.stream().map(jsonObject -> jsonObject.getString("type")).collect(Collectors.toList());
-            List<Integer> smsCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("smsCount")).collect(Collectors.toList());
-            List<Integer> successCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("successCount")).collect(Collectors.toList());
-            return R.ok().put("list",list).put("dates",dates).put("smsCount",smsCount).put("successCount",successCount);
-        }
-        else {
-            return R.ok("未查找到数据");
-        }
-    }
-
-    @GetMapping("/exportSmsLogs")
-    public AjaxResult exportSmsLogs(CompanyStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取所有员工
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-
-        List<CompanySmsLogsStatisticsVO> list= smsLogsService.selectSmsLogsStatisticsList(param);
-
-        ExcelUtil<CompanySmsLogsStatisticsVO> util = new ExcelUtil<CompanySmsLogsStatisticsVO>(CompanySmsLogsStatisticsVO.class);
-        return util.exportExcel(list, "voiceLogs");
-    }
-
-
-    @GetMapping("/customer")
-    public R customer(CrmCustomerStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取部门下的所有用户
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-        if(param.getUsers()!=null&&param.getUsers().length>0){
-            List<CrmCustomerStatisticsVO> list= crmCustomerService.selectCrmCustomerStatisticsList(param);
-
-            TimeUtils.TimeEntity timeEntity= TimeUtils.parseTime(param.getType().toString(),param.getStartTime(),param.getEndTime());
-            timeEntity.setUserIds(param.getUsers());
-            Integer cycleNum = timeEntity.getCycleNum();
-            Integer beginTime = timeEntity.getBeginTime();
-            List<Integer> timeList = new ArrayList<>();
-            for (int i = 1; i <= cycleNum; i++) {
-                timeList.add(beginTime);
-                beginTime = TimeUtils.formatTime(beginTime);
-            }
-            List<JSONObject> jsonObjectList = crmCustomerService.selectCrmCustomerCounts(timeEntity.toMap());
-            List<String> dates = jsonObjectList.stream().map(jsonObject -> jsonObject.getString("type")).collect(Collectors.toList());
-            List<Integer> receiveCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("receiveCount")).collect(Collectors.toList());
-            List<Integer> poolCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("poolCount")).collect(Collectors.toList());
-            return R.ok().put("list",list).put("dates",dates).put("receiveCount",receiveCount).put("poolCount",poolCount);
-        }
-        else {
-            return R.ok("未查找到数据");
-        }
-    }
-
-    @GetMapping("/exportCustomer")
-    public AjaxResult exportCustomer(CrmCustomerStatisticsParam param)
-    {
-
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取所有员工
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-
-        List<CrmCustomerStatisticsVO> list= crmCustomerService.selectCrmCustomerStatisticsList(param);
-        ExcelUtil<CrmCustomerStatisticsVO> util = new ExcelUtil<CrmCustomerStatisticsVO>(CrmCustomerStatisticsVO.class);
-        return util.exportExcel(list, "customer");
-    }
-
-
-    @GetMapping("/customerVisit")
-    public R customerVisit(CrmCustomerStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取部门下的所有用户
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-        if(param.getUsers()!=null&&param.getUsers().length>0){
-            List<CrmCustomerVisitStatisticsVO> list= crmCustomerVisitService.selectCrmCustomerVisitStatisticsList(param);
-
-            TimeUtils.TimeEntity timeEntity= TimeUtils.parseTime(param.getType().toString(),param.getStartTime(),param.getEndTime());
-            timeEntity.setUserIds(param.getUsers());
-            Integer cycleNum = timeEntity.getCycleNum();
-            Integer beginTime = timeEntity.getBeginTime();
-            List<Integer> timeList = new ArrayList<>();
-            for (int i = 1; i <= cycleNum; i++) {
-                timeList.add(beginTime);
-                beginTime = TimeUtils.formatTime(beginTime);
-            }
-            List<JSONObject> jsonObjectList = crmCustomerVisitService.selectCrmCustomerVisitCounts(timeEntity.toMap());
-            List<String> dates = jsonObjectList.stream().map(jsonObject -> jsonObject.getString("type")).collect(Collectors.toList());
-            List<Integer> customerCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("customerCount")).collect(Collectors.toList());
-            List<Integer> visitCount = jsonObjectList.stream().map(jsonObject -> jsonObject.getInteger("visitCount")).collect(Collectors.toList());
-            return R.ok().put("list",list).put("dates",dates).put("customerCount",customerCount).put("visitCount",visitCount);
-        }
-        else {
-            return R.ok("未查找到数据");
-        }
-    }
-
-    @GetMapping("/exportCustomerVisit")
-    public AjaxResult exportCustomerVisit(CrmCustomerStatisticsParam param)
-    {
-        if(StringUtils.isNotEmpty(param.getUserIds())){
-            String[] userIds=param.getUserIds().split(",");
-            Long[] ids=new Long[userIds.length];
-            for(int i=0;i<ids.length; i++){
-                ids[i]=Long.parseLong(userIds[i]);
-            }
-            param.setUsers(ids);
-        }
-        else{
-            //获取所有员工
-            CompanyUser usermap=new CompanyUser();
-            usermap.setDeptId(param.getDeptId());
-            List<CompanyUser> users = userService.getUserListByDeptId(usermap);
-            List<Long> userIds = users.stream().map(element -> element.getUserId()).collect(Collectors.toList());
-            param.setUsers(userIds.toArray(new Long[userIds.size()]));
-        }
-        List<CrmCustomerVisitStatisticsVO> list= crmCustomerVisitService.selectCrmCustomerVisitStatisticsList(param);
-        ExcelUtil<CrmCustomerVisitStatisticsVO> util = new ExcelUtil<CrmCustomerVisitStatisticsVO>(CrmCustomerVisitStatisticsVO.class);
-        return util.exportExcel(list, "visit");
-    }
-
-    @GetMapping("/ipadStaticTotal/{dateTime}")
-    public R ipadStaticTotal(@PathVariable("dateTime") String dateTime){
-        List<QwIpadTotalVo> qwIpadTotalVos = userService.selectCompanyByIpadStatus(dateTime);
-        return R.ok().put("list",qwIpadTotalVos);
-    }
-
-    @GetMapping("/exportIpadStaticByTime/{dateTime}")
-    public AjaxResult exportIpadStaticByTime(@PathVariable("dateTime") String dateTime){
-        List<QwIpadTotalVo> qwIpadTotalVos = userService.selectCompanyByIpadStatus(dateTime);
-        ExcelUtil<QwIpadTotalVo> util = new ExcelUtil<QwIpadTotalVo>(QwIpadTotalVo.class);
-        return util.exportExcel(qwIpadTotalVos, "visit");
-    }
-
-    /**
-     * 获取互联网医院订单统计数据
-     * */
-    @GetMapping("/hisOrderCountStats")
-    public AjaxResult getHisOrderCount(FsStoreOrderAmountStatsQueryDto statsQueryDto){
-        FsStoreOrderAmountStatsVo fsStoreOrderAmountStatsVo = storeOrderService.selectFsStoreOrderAmountStats(statsQueryDto);
-        return AjaxResult.success(fsStoreOrderAmountStatsVo);
-    }
-
-    /**
-     * 获取App商城订单统计数据
-     * */
-    @GetMapping("/appOrderCountStats")
-    public AjaxResult getAppOrderCount(FsStoreOrderAmountScrmStatsQueryDto statsQueryDto){
-        FsStoreOrderAmountScrmStatsVo scrmStatsVo = fsStoreOrderScrmService.selectFsStoreOrderAmountScrmStats(statsQueryDto);
-        return AjaxResult.success(scrmStatsVo);
-    }
-
-    /**
-     * 木易华康特殊处理 课程完课统计数据
-     */
-    @GetMapping("/courseReport")
-    public TableDataInfo selectFsCourseReportVO(FsCourseWatchLogStatisticsListParam param) {
-        startPage();
-        List<FsCourseReportVO> fsCourseReportVOS = fsCourseWatchLogService.selectFsCourseReportVO(param);
-        return getDataTable(fsCourseReportVOS);
-    }
-
-    @GetMapping("/exportFsCourseReportVO")
-    public AjaxResult exportFsCourseReportVO(FsCourseWatchLogStatisticsListParam param) {
-        List<FsCourseReportVO> list = fsCourseWatchLogService.selectFsCourseReportVO(param);
-        List<String> allFields = Arrays.stream(FsCourseReportVO.class.getDeclaredFields())
-                .filter(field -> field.isAnnotationPresent(Excel.class))
-                .map(Field::getName)
-                .collect(Collectors.toList());
-        ExcelUtil<FsCourseReportVO> util = new ExcelUtil<FsCourseReportVO>(FsCourseReportVO.class);
-        return util.exportExcelSelectedColumns(list, "完课统计报表", allFields);
-    }
-
-    @PostMapping("/syncYesterday")
-    public AjaxResult syncYesterday() {
-        try {
-            finishCourseStatisticsSyncService.syncMultiDimensionStatistics();
-            return AjaxResult.success("同步昨天数据成功");
-        } catch (Exception e) {
-            return AjaxResult.error("同步失败:" + e.getMessage());
-        }
-    }
-}

+ 0 - 261
fs-admin/src/main/java/com/fs/company/controller/CompanyTcmReportController.java

@@ -1,261 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.model.LoginUser;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.ServletUtils;
-import com.fs.common.utils.StringUtils;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyTcmSchedule;
-import com.fs.company.param.CompanyTcmReportListQueryParam;
-import com.fs.company.service.ICompanyTcmReportService;
-import com.fs.company.service.ICompanyTcmScheduleService;
-import com.fs.company.vo.CompanyTcmReportExportVO;
-import com.fs.company.vo.CompanyTcmReportListVO;
-import com.fs.company.vo.CompanyTcmStatisticsExportVO;
-import com.fs.framework.web.service.TokenService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.util.List;
-
-/**
- * 中医档期业绩报表Controller
- *
- * @author fs
- * @date 2023-09-05
- */
-@RestController
-@RequestMapping("/company/scheduleReport")
-public class CompanyTcmReportController extends BaseController
-{
-    @Autowired
-    private ICompanyTcmReportService companyTcmReportService;
-
-    @Autowired
-    private ICompanyTcmScheduleService companyTcmScheduleService;
-
-    @Autowired
-    private TokenService tokenService;
-
-    @PreAuthorize("@ss.hasPermi('company:scheduleReport:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyTcmReportListQueryParam param)
-    {
-        startPage();
-        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
-            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
-        }
-        if(!StringUtils.isEmpty(param.getDateRange())){
-            param.setStartTimeList(param.getDateRange().split("--"));
-        }
-        List<CompanyTcmReportListVO> list = companyTcmReportService.selectCompanyTcmReportListVOList(param);
-        return getDataTable(list);
-    }
-
-    @PreAuthorize("@ss.hasPermi('company:scheduleReport:statistics')")
-    @GetMapping("/statistics")
-    public TableDataInfo statisticsList(CompanyTcmReportListQueryParam param)
-    {
-        startPage();
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
-            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
-        }
-        if(!StringUtils.isEmpty(param.getDateRange())){
-            param.setStartTimeList(param.getDateRange().split("--"));
-        }
-        List<CompanyTcmReportListVO> list = companyTcmReportService.selectCompanyTcmReportStatisticsVOList(param);
-        return getDataTable(list);
-    }
-
-    @PreAuthorize("@ss.hasPermi('company:scheduleReport:statistics')")
-    @GetMapping("/getStatisticsByScheduleId")
-    public TableDataInfo getReportStatisticsListByScheduleId(CompanyTcmReportListQueryParam param)
-    {
-        startPage();
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
-            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
-        }
-        if(!StringUtils.isEmpty(param.getDateRange())){
-            param.setStartTimeList(param.getDateRange().split("--"));
-        }
-        List<CompanyTcmReportListVO> list = companyTcmReportService.selectReportStatisticsByScheduleId(param);
-        return getDataTable(list);
-    }
-
-    @PreAuthorize("@ss.hasPermi('company:scheduleReport:export')")
-    @Log(title = "中医档期业绩报表", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyTcmReportListQueryParam param)
-    {
-        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
-            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
-        }
-        if(!StringUtils.isEmpty(param.getDateRange())){
-            param.setStartTimeList(param.getDateRange().split("--"));
-        }
-        List<CompanyTcmReportExportVO> list = companyTcmReportService.selectCompanyTcmReportExportVOList(param);
-        ExcelUtil<CompanyTcmReportExportVO> util = new ExcelUtil<CompanyTcmReportExportVO>(CompanyTcmReportExportVO.class);
-        return util.exportExcel(list, "companyTcmScheduleReport");
-    }
-
-    /**
-     * 导出中医档期业绩报表列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:scheduleReport:export')")
-    @Log(title = "中医档期业绩统计报表", businessType = BusinessType.EXPORT)
-    @GetMapping("/exportStatistics")
-    public AjaxResult exportStatistics(CompanyTcmReportListQueryParam param)
-    {
-        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
-            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
-        }
-        if(!StringUtils.isEmpty(param.getDateRange())){
-            param.setStartTimeList(param.getDateRange().split("--"));
-        }
-        List<CompanyTcmStatisticsExportVO> list = companyTcmReportService.selectCompanyTcmStatisticsExportVOList(param);
-        for(CompanyTcmStatisticsExportVO item:list){
-            if(item.getTotalNum()!=null && item.getTotalNum().doubleValue()>0){
-                item.setRegisterRate(String.format("%.3f",getLongRate(item.getRegisterNum().doubleValue(),item.getTotalNum())*100.0).toString()+"%");
-                item.setOnlineRate(String.format("%.3f",getLongRate(item.getOnlineNum().doubleValue(),item.getTotalNum())*100.0).toString()+"%");
-                item.setFinishRate(String.format("%.3f", getLongRate(item.getFinishNum().doubleValue(),item.getTotalNum())*100.0).toString()+"%");
-                item.setRLine(new BigDecimal(getLongRate(item.getTotalMoney().doubleValue(),item.getTotalNum())*1.0).setScale(3, RoundingMode.HALF_UP));
-
-            }else{
-                item.setRegisterRate("0%");
-                item.setOnlineRate("0%");
-                item.setFinishRate("0%");
-                item.setRLine(new BigDecimal(0.0));
-            }
-
-            if(item.getCuCount()!=null && item.getCuCount().doubleValue()>0){
-                item.setPersonMoney(String.format("%.3f",getLongRate(item.getTotalMoney().doubleValue(),Long.valueOf(item.getCuCount()))*1.0).toString());
-            }else{
-                item.setCuCount(0);
-            }
-
-            if(item.getTargetMoney()!=null && item.getTargetMoney().doubleValue()>0){
-                item.setTargetRate(String.format("%.3f", item.getTotalMoney().doubleValue()/item.getTargetMoney().doubleValue()*100.0).toString()+"%");
-            }else{
-                item.setTargetRate("0%");
-            }
-            if(item.getMoney()!=null && item.getMoney().doubleValue()>0){
-                item.setZroi(new BigDecimal(item.getTotalMoney().doubleValue()/item.getMoney().doubleValue()*1.0).setScale(3, RoundingMode.HALF_UP));
-            }else{
-                item.setZroi(new BigDecimal(0.0));
-            }
-            if(item.getRound1Order()!=null){
-                item.setRound1Rate(getRoundRate(item.getRound1Order(),item.getTotalNum()));
-                item.setRound1Unit(new BigDecimal(getRoundUnit(item.getRound1Money(),item.getRound1Order())).setScale(3, RoundingMode.HALF_UP));
-            }
-            if(item.getRound2Order()!=null){
-                item.setRound2Rate(getRoundRate(item.getRound2Order(),item.getTotalNum()));
-                item.setRound2Unit(new BigDecimal(getRoundUnit(item.getRound2Money(),item.getRound2Order())).setScale(3, RoundingMode.HALF_UP));
-            }
-            if(item.getRound3Order()!=null){
-                item.setRound3Rate(getRoundRate(item.getRound3Order(),item.getTotalNum()));
-                item.setRound3Unit(new BigDecimal(getRoundUnit(item.getRound3Money(),item.getRound3Order())).setScale(3, RoundingMode.HALF_UP));
-            }
-            if(item.getRound4Order()!=null){
-                item.setRound4Rate(getRoundRate(item.getRound4Order(),item.getTotalNum()));
-                item.setRound4Unit(new BigDecimal(getRoundUnit(item.getRound4Money(),item.getRound4Order())).setScale(3, RoundingMode.HALF_UP));
-            }
-            if(item.getRound5Order()!=null){
-                item.setRound5Rate(getRoundRate(item.getRound5Order(),item.getTotalNum()));
-                item.setRound5Unit(new BigDecimal(getRoundUnit(item.getRound5Money(),item.getRound5Order())).setScale(3, RoundingMode.HALF_UP));
-            }
-            if(item.getRound6Order()!=null){
-                item.setRound6Rate(getRoundRate(item.getRound6Order(),item.getTotalNum()));
-                item.setRound6Unit(new BigDecimal(getRoundUnit(item.getRound6Money(),item.getRound6Order())).setScale(3, RoundingMode.HALF_UP));
-            }
-            if(item.getRound7Order()!=null) {
-                item.setRound7Rate(getRoundRate(item.getRound7Order(), item.getTotalNum()));
-                item.setRound7Unit(new BigDecimal(getRoundUnit(item.getRound7Money(), item.getRound7Order())).setScale(3, RoundingMode.HALF_UP));
-            }
-            if (item.getRound8Order() != null) {
-                item.setRound8Rate(getRoundRate(item.getRound8Order(), item.getTotalNum()));
-                item.setRound8Unit(new BigDecimal(getRoundUnit(item.getRound8Money(), item.getRound8Order())).setScale(3, RoundingMode.HALF_UP));
-            }
-            if (item.getRound9Order() != null) {
-                item.setRound9Rate(getRoundRate(item.getRound9Order(), item.getTotalNum()));
-                item.setRound9Unit(new BigDecimal(getRoundUnit(item.getRound9Money(), item.getRound9Order())).setScale(3, RoundingMode.HALF_UP));
-            }
-
-        }
-
-        ExcelUtil<CompanyTcmStatisticsExportVO> util = new ExcelUtil<CompanyTcmStatisticsExportVO>(CompanyTcmStatisticsExportVO.class);
-        return util.exportExcel(list, "statisticsScheduleReport");
-    }
-
-
-
-    /**
-     * 查询可用中医档期列表
-     */
-    @GetMapping("/getScheduleList")
-    public TableDataInfo getScheduleList()
-    {
-        startPage();
-        List<CompanyTcmSchedule> list = companyTcmScheduleService.selectUseableScheduleList();
-        return getDataTable(list);
-    }
-
-    /**
-     * 查询中医档期列表
-     */
-    @GetMapping("/getAllScheduleList")
-    public TableDataInfo getAllScheduleList()
-    {
-        startPage();
-        List<CompanyTcmSchedule> list = companyTcmScheduleService.selectCompanyTcmScheduleList(new CompanyTcmSchedule());
-        return getDataTable(list);
-    }
-
-    /**
-     * 获取中医档期业绩报表详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:scheduleReport:query')")
-    @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") Long id)
-    {
-        return AjaxResult.success(companyTcmReportService.selectCompanyTcmReportById(id));
-    }
-
-    public String getRoundRate(Long roundOrder,Long totalNum){
-        String sorStr="0%";
-        if(totalNum.longValue()>0){
-            sorStr=String.format("%.3f", roundOrder.doubleValue()/totalNum*100.0).toString()+"%";
-        }
-        return sorStr;
-    }
-
-    public double getRoundUnit(BigDecimal roundMoney,Long roundOrder){
-        double sorNum=0;
-        if(roundOrder.longValue()>0){
-            sorNum=roundMoney.doubleValue()/roundOrder*1.0;
-        }
-        return sorNum;
-    }
-
-
-    public double getLongRate(double num1,Long num2){
-        double sorNum=0;
-        if(num2.longValue()>0){
-            sorNum=num1/num2*1.0;
-        }
-        return sorNum;
-    }
-
-
-}

+ 0 - 120
fs-admin/src/main/java/com/fs/company/controller/CompanyTcmScheduleController.java

@@ -1,120 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.domain.model.LoginUser;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.ServletUtils;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyTcmSchedule;
-import com.fs.company.service.ICompanyTcmScheduleService;
-import com.fs.framework.web.service.TokenService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 中医档期管理Controller
- *
- * @author fs
- * @date 2023-09-05
- */
-@RestController
-@RequestMapping("/company/schedule")
-public class CompanyTcmScheduleController extends BaseController
-{
-    @Autowired
-    private ICompanyTcmScheduleService companyTcmScheduleService;
-
-    @Autowired
-    private TokenService tokenService;
-    /**
-     * 查询中医档期管理列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:schedule:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyTcmSchedule companyTcmSchedule)
-    {
-        startPage();
-        List<CompanyTcmSchedule> list = companyTcmScheduleService.selectCompanyTcmScheduleList(companyTcmSchedule);
-        return getDataTable(list);
-    }
-
-    @GetMapping("/getTcmScheduleList")
-    public R getCompanyTcmScheduleList()
-    {
-        CompanyTcmSchedule map = new CompanyTcmSchedule();
-        map.setStatus(1L);
-        List<CompanyTcmSchedule> list = companyTcmScheduleService.selectCompanyTcmScheduleList(map);
-        return R.ok().put("data",list);
-    }
-
-    /**
-     * 导出中医档期管理列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:schedule:export')")
-    @Log(title = "中医档期管理", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyTcmSchedule companyTcmSchedule)
-    {
-        List<CompanyTcmSchedule> list = companyTcmScheduleService.selectCompanyTcmScheduleList(companyTcmSchedule);
-        ExcelUtil<CompanyTcmSchedule> util = new ExcelUtil<CompanyTcmSchedule>(CompanyTcmSchedule.class);
-        return util.exportExcel(list, "schedule");
-    }
-
-    /**
-     * 获取中医档期管理详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:schedule:query')")
-    @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") Long id)
-    {
-        return AjaxResult.success(companyTcmScheduleService.selectCompanyTcmScheduleById(id));
-    }
-
-    /**
-     * 新增中医档期管理
-     */
-    @PreAuthorize("@ss.hasPermi('company:schedule:add')")
-    @Log(title = "中医档期管理", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyTcmSchedule companyTcmSchedule)
-    {
-
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        List<CompanyTcmSchedule> scheduleList=companyTcmScheduleService.selectCompanyTcmScheduleList(companyTcmSchedule);
-        if(scheduleList.size()>0){
-            return AjaxResult.error("档期名称已经存在");
-        }
-        companyTcmSchedule.setCreateUserId(loginUser.getUser().getUserId());
-        //companyTcmSchedule.setUpdateUserId(loginUser.getUser().getUserId());
-        return toAjax(companyTcmScheduleService.insertCompanyTcmSchedule(companyTcmSchedule));
-    }
-
-    /**
-     * 修改中医档期管理
-     */
-    @PreAuthorize("@ss.hasPermi('company:schedule:edit')")
-    @Log(title = "中医档期管理", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyTcmSchedule companyTcmSchedule)
-    {
-        return toAjax(companyTcmScheduleService.updateCompanyTcmSchedule(companyTcmSchedule));
-    }
-
-    /**
-     * 删除中医档期管理
-     */
-    @PreAuthorize("@ss.hasPermi('company:schedule:remove')")
-    @Log(title = "中医档期管理", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{ids}")
-    public AjaxResult remove(@PathVariable Long[] ids)
-    {
-        return toAjax(companyTcmScheduleService.deleteCompanyTcmScheduleByIds(ids));
-    }
-}

+ 0 - 118
fs-admin/src/main/java/com/fs/company/controller/CompanyTrafficController.java

@@ -1,118 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.domain.model.LoginUser;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.ServletUtils;
-import com.fs.company.domain.CompanyTrafficRecord;
-import com.fs.company.param.CompanyTrafficRecordChargeParam;
-import com.fs.company.param.CompanyTrafficRecordQueryParam;
-import com.fs.company.service.ICompanyTrafficRecordService;
-import com.fs.framework.task.TenantTaskRunner;
-import com.fs.framework.web.service.TokenService;
-import com.fs.hisStore.config.MedicalMallConfig;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import javax.annotation.PostConstruct;
-import java.util.List;
-
-@RestController
-@RequestMapping("/company/traffic")
-public class CompanyTrafficController extends BaseController {
-
-    @Autowired
-    private ICompanyTrafficRecordService companyTrafficRecordService;
-
-    @Autowired
-    private TokenService tokenService;
-
-    @Autowired
-    private MedicalMallConfig medicalMallConfig;
-
-    @Autowired
-    private TenantTaskRunner tenantTaskRunner;
-
-    /** SaaS 模式:为 true 时定时任务按租户执行 */
-    @Value("${saas.task.enabled:true}")
-    private boolean saasTaskEnabled;
-
-    /**
-     * 每天扣除流量余额。SaaS 开启时按租户执行。
-     */
-    @Scheduled(cron = "0 1 0 * * ?")
-    public void refreshTraffic() {
-        if (!medicalMallConfig.isStatics()) {
-            return;
-        }
-        if (saasTaskEnabled) {
-            tenantTaskRunner.runForEachTenant("refreshTraffic", () -> companyTrafficRecordService.refreshTraffic());
-        } else {
-            companyTrafficRecordService.refreshTraffic();
-        }
-    }
-
-    /**
-     * 重启时重新计算并更新公司缓存
-     * */
-    @PostConstruct
-    public void init() {
-        if(medicalMallConfig.isStatics())
-            companyTrafficRecordService.init();
-    }
-
-    /** 充值流量 */
-    @PreAuthorize("@ss.hasPermi('company:traffic:charge')")
-    @Log(title = "公司流量充值", businessType = BusinessType.INSERT)
-    @PostMapping(value = "/rechargeTraffic")
-    public R rechargeTraffic(@RequestBody CompanyTrafficRecordChargeParam companyTrafficRecord) {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        companyTrafficRecord.setUserId(loginUser.getUser().getUserId());
-        companyTrafficRecord.setUserName(loginUser.getUser().getUserName());
-        companyTrafficRecordService.recharge(companyTrafficRecord);
-        return R.ok();
-    }
-
-    /** 流量充值记录查询 */
-    @PreAuthorize("@ss.hasPermi('company:traffic:list')")
-    @GetMapping(value = "/list")
-    public TableDataInfo list(CompanyTrafficRecordQueryParam param) {
-        startPage();
-        List<CompanyTrafficRecord> list = companyTrafficRecordService.selectList(param);
-        return getDataTable(list);
-    }
-
-    /** 流量充值详情 */
-    @PreAuthorize("@ss.hasPermi('company:traffic:detail')")
-    @GetMapping(value = "/detail/{logId}")
-    public R detail(@PathVariable("logId") Long logId) {
-        CompanyTrafficRecord record = companyTrafficRecordService.selectById(logId);
-        return R.ok().put("data", record);
-    }
-
-    /** 流量换算*/
-    @GetMapping(value = "/trafficConversion")
-    public R trafficConversion(@RequestParam("traffic") Long amount) {
-        Long trafficKB = companyTrafficRecordService.trafficConversion(amount);
-        return R.ok().put("data", trafficKB);
-    }
-
-    /** 刷新单价*/
-    @GetMapping(value = "/refreshPrice")
-    public R refreshPrice() {
-        companyTrafficRecordService.refreshPrice();
-        return R.ok();
-    }
-
-    /** 流量统计*/
-    @GetMapping(value = "/trafficStatistics")
-    public R trafficStatistics(CompanyTrafficRecord record) {
-        return R.ok().put("tatol","").put("dept","").put("company","");
-    }
-}

+ 0 - 49
fs-admin/src/main/java/com/fs/company/controller/CompanyTrafficLogController.java

@@ -1,49 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyTrafficRecordLog;
-import com.fs.company.param.CompanyTrafficRecordLogQueryParam;
-import com.fs.company.service.ICompanyTrafficRecordLogService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-@RestController
-@RequestMapping("/company/trafficLog")
-public class CompanyTrafficLogController extends BaseController {
-
-    @Autowired
-    private ICompanyTrafficRecordLogService companyTrafficRecordLogService;
-
-
-    /** 流量充值记录查询 */
-    @PreAuthorize("@ss.hasPermi('company:trafficLog:list')")
-    @GetMapping(value = "/list")
-    public TableDataInfo list(CompanyTrafficRecordLogQueryParam param) {
-        startPage();
-        List<CompanyTrafficRecordLog> list = companyTrafficRecordLogService.selectList(param);
-        return getDataTable(list);
-    }
-
-
-    /** 导出 */
-    @PreAuthorize("@ss.hasPermi('company:trafficLog:export')")
-    @Log(title = "流量充值记录导出", businessType = BusinessType.EXPORT)
-    @GetMapping(value = "/export")
-    public AjaxResult export(CompanyTrafficRecordLogQueryParam param) {
-        List<CompanyTrafficRecordLog> list = companyTrafficRecordLogService.selectList(param);
-        ExcelUtil<CompanyTrafficRecordLog> util = new ExcelUtil<>(CompanyTrafficRecordLog.class);
-        return util.exportExcel(list, "流量充值记录");
-    }
-
-
-
-}

+ 0 - 586
fs-admin/src/main/java/com/fs/company/controller/CompanyUserAllController.java

@@ -1,586 +0,0 @@
-package com.fs.company.controller;
-
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.http.HttpRequest;
-import cn.hutool.json.JSONUtil;
-import com.baidu.dev2.thirdparty.jackson.databind.JsonMappingException;
-import com.baidu.dev2.thirdparty.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fs.common.annotation.Log;
-import com.fs.common.constant.UserConstants;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.domain.model.LoginUser;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.core.redis.RedisCache;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.PatternUtils;
-import com.fs.common.utils.SecurityUtils;
-import com.fs.common.utils.ServletUtils;
-import com.fs.common.utils.StringUtils;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.*;
-import com.fs.company.param.CompanyUserAreaParam;
-import com.fs.company.param.CompanyUserCodeParam;
-import com.fs.company.param.CompanyUserQwParam;
-import com.fs.company.service.*;
-import com.fs.company.vo.BatchUserRolesVO;
-import com.fs.company.vo.CompanyUserImportVO;
-import com.fs.company.vo.CompanyUserQwListVO;
-import com.fs.company.vo.CompanyUserVO;
-import com.fs.config.saas.ProjectConfig;
-import com.fs.course.config.CourseConfig;
-import com.fs.framework.web.service.TokenService;
-import com.fs.his.utils.qrcode.QRCodeUtils;
-import com.fs.his.vo.OptionsVO;
-import com.fs.hisStore.vo.FsStoreProductExportVO;
-import com.fs.im.dto.OpenImResponseDTO;
-import com.fs.im.service.OpenIMService;
-import com.fs.qw.domain.QwCompany;
-import com.fs.qw.service.IQwCompanyService;
-import com.fs.qw.service.IQwUserService;
-import com.fs.qw.vo.CompanyUserQwVO;
-import com.fs.qw.vo.QwUserVO;
-import com.fs.system.domain.SysConfig;
-import com.fs.system.mapper.SysConfigMapper;
-import com.fs.system.service.ISysConfigService;
-import com.fs.utils.DomainUtil;
-import com.fs.utils.QwStatusEnum;
-import com.fs.voice.utils.StringUtil;
-import com.github.pagehelper.PageHelper;
-import com.github.pagehelper.PageInfo;
-import io.swagger.annotations.ApiOperation;
-import org.json.JSONArray;
-import org.json.JSONObject;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.util.Assert;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-import java.util.*;
-import java.util.concurrent.CompletableFuture;
-import java.util.stream.Collectors;
-
-
-/**
- * 用户信息
- */
-@RestController
-@RequestMapping("/company/CompanyUserAll")
-public class CompanyUserAllController extends BaseController {
-
-    @Autowired
-    private ICompanyRoleService roleService;
-    @Autowired
-    private SysConfigMapper sysConfigMapper;
-    @Autowired
-    private ICompanyPostService postService;
-
-    @Autowired
-    private ICompanyUserService companyUserService;
-
-    @Autowired
-    private ICompanyService companyService;
-
-    @Autowired
-    private ICompanyUserDelayTimeService companyUserDelayTimeService;
-
-    @Autowired
-    private ISysConfigService configService;
-
-    @Autowired
-    private RedisCache redisCache;
-
-    @Autowired
-    private OpenIMService openIMService;
-
-    @Autowired
-    IQwCompanyService iQwCompanyService;
-
-    @Autowired
-    private IQwUserService qwUserService;
-
-    @Autowired
-    private TokenService tokenService;
-
-    private static final String appLink = "https://jump.ylrztop.com/jumpapp/pages/index/index?link=";
-
-
-    @GetMapping("/getList")
-    public TableDataInfo getList(CompanyUser user)
-    {
-        startPage();
-        List<CompanyUser> list = companyUserService.selectCompanyUserList(user);
-        return getDataTable(list);
-    }
-    @GetMapping("/qwList")
-    public TableDataInfo qwList(CompanyUserQwParam user) {
-        List<CompanyUserQwListVO> list = companyUserService.selectCompanyUserQwListVO(user);
-        if (!list.isEmpty()){
-            String json = configService.selectConfigByKey("course.config");
-            CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-            Long sendDelayTime = config.getSendDelayTime();
-            List<CompletableFuture<Void>> futures = new ArrayList<>();
-            for (CompanyUserQwListVO companyUserQwListVO : list) {
-                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
-                    CompanyUserDelayTime companyUserDelayTime = companyUserDelayTimeService.selectCompanyUserDelayTimeByCompanyUser(companyUserQwListVO.getCompanyId(), companyUserQwListVO.getUserId());
-                    if (ObjectUtil.isEmpty(companyUserDelayTime)) {
-                        companyUserQwListVO.setSendDelayTime(sendDelayTime);
-                    } else {
-                        companyUserQwListVO.setSendDelayTime(companyUserDelayTime.getSendDelayTime());
-                    }
-                    //是否绑定
-                    if(QwStatusEnum.BOUND.getCode() == companyUserQwListVO.getQwStatus()){
-                        if(!companyUserQwListVO.getQwUserId().isEmpty()){
-                            Long[] ids = Arrays.stream(companyUserQwListVO.getQwUserId().split(","))
-                                    .map(Long::parseLong)
-                                    .toArray(Long[]::new);
-                            List<QwUserVO> qwUserVOS = qwUserService.selectQwUserVOByIds(ids);
-                            companyUserQwListVO.setQwUsers(qwUserVOS);
-                        }
-                    }
-                });
-                futures.add(future);
-            }
-            CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
-        }
-        return getDataTable(list);
-    }
-
-    @Log(title = "用户管理导出", businessType = BusinessType.EXPORT)
-    @PreAuthorize("@ss.hasPermi('company:user:export')")
-    @GetMapping("/export")
-    public AjaxResult export(CompanyUser user)
-    {
-        List<CompanyUser> list = companyUserService.selectCompanyUserList(user);
-        ExcelUtil<CompanyUser> util = new ExcelUtil<CompanyUser>(CompanyUser.class);
-        return util.exportExcel(list, "用户数据");
-    }
-
-
-    @Log(title = "销售信息导入", businessType = BusinessType.IMPORT,isStoreLog = true,logParam = {"销售","信息导入"})
-    @PreAuthorize("@ss.hasPermi('company:user:import')")
-    @PostMapping("/importCompanyUser")
-    public AjaxResult importData(@RequestParam("file") MultipartFile file, boolean updateSupport) throws Exception
-    {
-        ExcelUtil<CompanyUserImportVO> util = new ExcelUtil<>(CompanyUserImportVO.class);
-        List<CompanyUserImportVO> list = util.importExcel(file.getInputStream());
-        String message = companyUserService.importCompanyUser(list, updateSupport);
-        return AjaxResult.success(message);
-    }
-
-
-    @GetMapping("/importTemplate")
-    public AjaxResult importTemplate()
-    {
-        ExcelUtil<CompanyUserImportVO> util = new ExcelUtil<>(CompanyUserImportVO.class);
-        return util.importTemplateExcel("销售数据");
-    }
-
-
-
-    /**
-     * 根据用户编号获取详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:user:query')")
-    @GetMapping(value = { "/", "/{userId}" })
-    public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
-    {
-        AjaxResult ajax = AjaxResult.success();
-        CompanyRole companyRoleMap=new CompanyRole();
-
-        CompanyUser userById = companyUserService.selectCompanyUserById(userId);
-        companyRoleMap.setCompanyId(userById.getCompanyId());
-        List<CompanyRole> roles = roleService.selectCompanyRoleList(companyRoleMap);
-
-        ajax.put("roles", CompanyUser.isAdmin(userById.getUserType()) ? roles : roles.stream().filter(r -> r.getRoleKey()!="admin").collect(Collectors.toList()));
-
-        CompanyPost postMap=new CompanyPost();
-        postMap.setCompanyId(userById.getCompanyId());
-        ajax.put("posts", postService.selectCompanyPostList(postMap));
-        if (StringUtils.isNotNull(userId))
-        {
-            CompanyUser companyUser=companyUserService.selectCompanyUserById(userId);
-            ajax.put(AjaxResult.DATA_TAG, companyUser);
-            ajax.put("postIds", postService.selectPostListByUserId(userId));
-            ajax.put("roleIds", roleService.selectRoleListByUserId(userId));
-
-
-        }
-        return ajax;
-    }
-
-    /**
-     * 根据用户编号获取详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:user:query')")
-    @GetMapping("/addInfo/{companyId}")
-    public AjaxResult addInfo(@PathVariable(value = "companyId", required = true) Long companyId)
-    {
-        AjaxResult ajax = AjaxResult.success();
-
-        CompanyRole companyRoleMap=new CompanyRole();
-        companyRoleMap.setCompanyId(companyId);
-        List<CompanyRole> roles = roleService.selectCompanyRoleList(companyRoleMap);
-
-        ajax.put("roles", CompanyUser.isAdmin("01") ? roles : roles.stream().filter(r -> r.getRoleKey()!="admin").collect(Collectors.toList()));
-
-        CompanyPost postMap=new CompanyPost();
-        postMap.setCompanyId(companyId);
-        ajax.put("posts", postService.selectCompanyPostList(postMap));
-
-        return ajax;
-    }
-
-    /**
-     * 新增用户
-     */
-    @PreAuthorize("@ss.hasPermi('company:user:add')")
-    @Log(title = "用户管理", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@Validated @RequestBody CompanyUser user)
-    {
-        if (!PatternUtils.checkPassword(user.getPassword())) {
-            return AjaxResult.error("密码格式不正确,需包含字母、数字和特殊字符,长度为 8-20 位");
-        }
-
-        //判断用户数量是否已达到上线
-
-        Integer count=companyUserService.selectCompanyUserCountByCompanyId(user.getCompanyId());
-        Company company=companyService.selectCompanyById(user.getCompanyId());
-
-        if(count>company.getLimitUserCount()){
-            return AjaxResult.error("用户数量已达到上限");
-        }
-        user.setCompanyId(user.getCompanyId());
-        if (UserConstants.NOT_UNIQUE.equals(String.valueOf(companyUserService.checkUserName(user.getUserName()))))
-        {
-            return AjaxResult.error("新增用户'" + user.getUserName() + "'失败,登录账号已存在");
-        }
-        if (!StringUtil.strIsNullOrEmpty(user.getDomain())){
-            user.setDomain(user.getDomain().replaceAll("^[\\s\\u2005]+", ""));
-        }
-
-        user.setCreateBy(SecurityUtils.getUsername());
-        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
-        user.setCreateTime(new Date());
-        user.setUserType("01");//一般用户
-        user.setIsAudit(1);
-        return toAjax(companyUserService.insertUser(user));
-    }
-
-    /**
-     * 生成创建销售的二维码
-     */
-
-    @PreAuthorize("@ss.hasPermi('company:user:addCodeUrl')")
-    @Log(title = "生成创建销售的二维码", businessType = BusinessType.INSERT)
-    @PostMapping("/addCodeUrl")
-    public R addCodeUrl( @RequestBody CompanyUserCodeParam user) throws Exception {
-
-        QwCompany qwCompany = iQwCompanyService.getQwCompanyByRedis(user.getCorpId());
-        if (qwCompany == null || qwCompany.getCorpId() == null){
-            return R.error("企业信息不存在");
-        }
-
-        //部门
-        Long deptId = user.getDeptId();
-
-        //角色组
-        Long[] roleIds = user.getRoleIds();
-
-        //区域
-        String addressId = user.getAddressId();
-
-
-        Map<String, Object> stateMap = new HashMap<>();
-        stateMap.put("companyId", user.getCompanyId());
-        stateMap.put("deptId", deptId);
-        stateMap.put("roleIds", roleIds); // 数组可以直接存放
-        stateMap.put("addressId", addressId);
-
-        // 使用JSON库将Map转换为字符串
-        ObjectMapper objectMapper = new ObjectMapper();
-        String status = objectMapper.writeValueAsString(stateMap);
-
-        // 如果要将status作为URL参数传递,记得进行URL编码!
-        String encodedStatus = URLEncoder.encode(status, StandardCharsets.UTF_8.toString());
-
-        String url="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+user.getCorpId()+"&redirect_uri=" +
-                "http://"+qwCompany.getRealmNameUrl()+"/loginqw/pages/companyLogin/index?corpId="+user.getCorpId() +
-                "&response_type=code&scope=snsapi_base&state="+encodedStatus+"&agentid="+qwCompany.getServerAgentId()+"#wechat_redirect";
-
-        R andUpload = QRCodeUtils.createAndUpload(url);
-        return  R.ok().put("data",andUpload);
-    }
-    /**
-     * 修改用户
-     */
-    @PreAuthorize("@ss.hasPermi('company:user:edit')")
-    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@Validated @RequestBody CompanyUser user)
-    {
-
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        user.setUpdateBy(SecurityUtils.getUsername());
-
-        if (!StringUtil.strIsNullOrEmpty(user.getDomain())){
-            user.setDomain(user.getDomain().replaceAll("^[\\s\\u2005]+", ""));
-        }
-
-        CompanyUser companyUser = companyUserService.selectCompanyUserById(user.getUserId());
-
-        if (!companyUser.getUserName().equals(user.getUserName())){
-            if (UserConstants.NOT_UNIQUE.equals(String.valueOf(companyUserService.checkUserName(user.getUserName()))))
-            {
-                return AjaxResult.error("修改员工账号'" + user.getUserName() + "'失败,员工账号已存在");
-            }
-        }
-
-
-        logger.info("用户管理-修改用户:"+user.getUserName()+"/登陆人:"+loginUser.getUser().getUserId()+"/名字:"+loginUser.getUser().getUserName()+"/修改的角色:"+ Arrays.toString(user.getRoleIds()));
-        return toAjax(companyUserService.updateUser(user));
-    }
-
-    /**
-     * 删除用户
-     */
-    @PreAuthorize("@ss.hasPermi('company:user:remove')")
-    @Log(title = "用户管理", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{userIds}")
-    public AjaxResult remove(@PathVariable Long[] userIds)
-    {
-        for (Long userId : userIds) {
-            CompanyUser companyUser = companyUserService.selectCompanyUserById(userId);
-            CompanyUserDelayTime companyUserDelayTime = companyUserDelayTimeService.selectCompanyUserDelayTimeByCompanyUser(companyUser.getCompanyId(),userId);
-            if (ObjectUtil.isNotEmpty(companyUserDelayTime)){
-                companyUserDelayTimeService.deleteCompanyUserDelayTimeById(companyUserDelayTime.getId());
-            }
-        }
-        return toAjax(companyUserService.deleteCompanyUserByIds(userIds));
-    }
-
-    /**
-     * 重置密码
-     */
-    @PreAuthorize("@ss.hasPermi('company:user:edit')")
-    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
-    @PutMapping("/resetPwd")
-    public AjaxResult resetPwd(@RequestBody CompanyUser user)
-    {
-        if (!PatternUtils.checkPassword(user.getPassword())) {
-            return AjaxResult.error("密码格式不正确,需包含字母、数字和特殊字符,长度为 8-20 位");
-        }
-
-        String newPassword = SecurityUtils.encryptPassword(user.getPassword());
-        int i = companyUserService.resetUserPwdByUserId(user.getUserId(), newPassword);
-
-        if (i > 0) {
-            // 更新缓存用户密码
-            redisCache.deleteObject("newCompanyUser:" + user.getCompanyId() + ":" + user.getUserName());
-        }
-
-        return toAjax(i);
-    }
-
-    /**
-     * 状态修改
-     */
-    @PreAuthorize("@ss.hasPermi('company:user:edit')")
-    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
-    @PutMapping("/changeStatus")
-    public AjaxResult changeStatus(@RequestBody CompanyUser user)
-    {
-        //管理员的状态不能修改
-        CompanyUser companyUser=companyUserService.selectCompanyUserById(user.getUserId());
-        if(companyUser.isAdmin()){
-            return AjaxResult.error("不能修改管理员状态");
-        }
-        user.setUpdateBy(SecurityUtils.getUsername());
-        return toAjax(companyUserService.updateCompanyUser(user));
-    }
-
-
-
-
-    /**
-     * 获取区域
-     */
-    @GetMapping("/getCitysAreaList")
-    public R getCitysAreaList(){
-        return R.ok().put("data",companyUserService.getCitysAreaList());
-    }
-
-    /**
-     * 批量修改 销售的所属区域(临时的)
-     */
-    @PreAuthorize("@ss.hasPermi('company:user:updateCompanyUserAreaList')")
-    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
-    @PostMapping("/updateCompanyUserAreaList")
-    public R updateCompanyUserAreaList(@RequestBody CompanyUserAreaParam param)
-    {
-        return companyUserService.updateCompanyUserAreaList(param);
-    }
-
-
-    @GetMapping("/generateSubDomain")
-    public R generateSubDomain(CompanyUser user){
-        //获取后台配置
-        String json= configService.selectConfigByKey("course.config");
-        CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
-        // 生成二级域名
-        String subDomain = "http://" + DomainUtil.generateSubDomain(config.getCourseDomainName(), 6, String.valueOf(SecurityUtils.getLoginUser().getUser().getUserId()));
-        return  R.ok().put("data",subDomain);
-    }
-
-    @PreAuthorize("@ss.hasPermi('company:user:setRegister')")
-    @Log(title = "设置是否需要单独注册会员", businessType = BusinessType.UPDATE)
-    @PutMapping("/setRegister")
-    public AjaxResult setIsRegisterMember(@RequestParam Boolean status, @RequestBody List<Long> userIds) {
-        Boolean r = companyUserService.setIsRegisterMember(status, userIds);
-        if (r) {
-            return AjaxResult.success();
-        } else {
-            return AjaxResult.error("操作失败");
-        }
-    }
-
-    @PreAuthorize("@ss.hasPermi('company:user:allowedAllRegister')")
-    @Log(title = "是否允许所有方式注册会员", businessType = BusinessType.UPDATE)
-    @PutMapping("/allowedAllRegister")
-    public AjaxResult isAllowedAllRegister(@RequestParam Boolean status, @RequestBody List<Long> userIds) {
-        Boolean r = companyUserService.isAllowedAllRegister(status, userIds);
-        if (r) {
-            return AjaxResult.success();
-        } else {
-            return AjaxResult.error("操作失败");
-        }
-    }
-    @PostMapping("/common/uploadOSS")
-    public R uploadOSS(@RequestParam("file") MultipartFile file,
-                       @RequestParam("userId") String userId) throws Exception {
-        String url = companyUserService.uploadQrCode(file, userId);
-        return R.ok().put("url", url);
-    }
-
-
-    /**
-     * 销售解除绑定医生
-     */
-    @PreAuthorize("@ss.hasPermi('qw:companyUser:unBindDoctorId')")
-    @Log(title = "销售解除绑定医生", businessType = BusinessType.UPDATE)
-    @GetMapping("/unBindDoctorId/{userId}")
-    public R bindDoctorId(@PathVariable("userId") Long userId){
-        return companyUserService.unBindDoctor(userId);
-    }
-
-    /**
-     * 销售绑定医生
-     */
-    @PreAuthorize("@ss.hasPermi('qw:companyUser:bindDoctorId')")
-    @Log(title = "销售绑定医生", businessType = BusinessType.UPDATE)
-    @PostMapping("/bindDoctorId")
-    public R unBindDoctorId(@RequestBody CompanyUser companyUser){
-        return companyUserService.bindDoctor(companyUser);
-    }
-
-    /**
-     * 批量修改角色
-     * @param batchUserRolesVO
-     */
-    @PreAuthorize("@ss.hasPermi('company:user:edit')")
-    @Log(title = "批量修改角色", businessType = BusinessType.UPDATE)
-    @PostMapping("/updateBatchUserRoles")
-    public R updateBatchUserRoles(@RequestBody BatchUserRolesVO batchUserRolesVO){
-        Assert.notEmpty(batchUserRolesVO.getRoleIds(), "角色不能为空");
-        Assert.notEmpty(batchUserRolesVO.getUserIds(), "用户不能为空");
-        return companyUserService.updateBatchUserRoles(batchUserRolesVO);
-    }
-
-
-    @ApiOperation("校验客服是否注册新的im")
-    @PostMapping("/accountCheck")
-    public R accountCheck(@RequestBody Map<String, String> userIdMap){
-
-        ProjectConfig projectConfig = ProjectConfig.getFromDB(sysConfigMapper);
-        ProjectConfig.OpenIM im = projectConfig != null ? projectConfig.getOpenIM() : null;
-
-        //获取管理员token
-        String userId = userIdMap.get("userId");
-        String adminToken = openIMService.getAdminToken();
-        JSONObject requestBody = new JSONObject();
-        // 解析响应
-        if (StringUtils.isNotEmpty(adminToken)) {
-            //查询用户是否注册
-            ArrayList<String> userIds = new ArrayList<>();
-            requestBody = new JSONObject();
-            userIds.add(userId);
-            requestBody.put("checkUserIDs", userIds);
-
-            String body = HttpRequest.post(im.getUrl()+"/user/account_check")
-                    .header("operationID", String.valueOf(System.currentTimeMillis()))
-                    .header("token", adminToken)
-                    .body(requestBody.toString())
-                    .execute()
-                    .body();
-            JSONObject jsonObject = new JSONObject(body);
-            JSONArray results = jsonObject.getJSONObject("data").getJSONArray("results");
-            if (results != null && results.length() > 0) {
-                JSONObject resultObj = results.getJSONObject(0);
-                int accountStatus = resultObj.getInt("accountStatus");
-                //未注册自动注册
-                if (accountStatus==0){
-                    String s = userId.replaceFirst("^C", "");
-                    CompanyUser companyUser = companyUserService.selectCompanyUserById(Long.parseLong(s));
-                    if (null==companyUser){
-                        return R.error("用户不存在");
-                    }
-                    ArrayList<Object> users = new ArrayList<>();
-                    HashMap<String, String> map = new HashMap<>();
-                    map.put("userID",userId);
-                    map.put("nickname",companyUser.getNickName());
-                    map.put("faceURL",companyUser.getAvatar());
-                    users.add(map);
-                    requestBody = new JSONObject();
-                    //userIds.add(userId);
-                    requestBody.put("users", users);
-                    String registerBody = HttpRequest.post(im.getUrl()+"/user/user_register")
-                            .header("operationID", String.valueOf(System.currentTimeMillis()))
-                            .header("token", adminToken).body(requestBody.toString()).execute().body();
-                }
-            } else {
-                return R.error("返回结果为空");
-            }
-           /* HashMap<String, String> tokenMap = new HashMap<>();
-            tokenMap.put("platformID","1");
-            tokenMap.put("userID",userId);*/
-            requestBody = new JSONObject();
-            requestBody.put("platformID",5);
-            requestBody.put("userID",userId);
-            String body1 = HttpRequest.post(im.getUrl()+"/auth/get_user_token")
-                    .header("operationID", String.valueOf(System.currentTimeMillis()))
-                    .header("token", adminToken)
-                    .body(requestBody.toString()).execute().body();
-            JSONObject userJson = new JSONObject(body1);
-            JSONObject userData = userJson.getJSONObject("data");
-            String userToken = userData.getString("token");
-            return R.ok().put("token", userToken);
-        } else {
-            return R.error("获取管理员token失败");
-        }
-    }
-    @ApiOperation("添加好友")
-    @PostMapping("/importFriend")
-    public R importFriend(@RequestBody HashMap<String,Object> map){
-        String ownerUserID = (String) map.get("ownerUserID");
-        List<String> friendUserIDs = (List<String>)map.get("friendUserIDs");
-        OpenImResponseDTO openImResponseDTO = openIMService.importFriend(ownerUserID, friendUserIDs);
-        return R.ok().put("data",openImResponseDTO);
-    }
-}

+ 0 - 201
fs-admin/src/main/java/com/fs/company/controller/CompanyUserController.java

@@ -1,201 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.constant.UserConstants;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.ServletUtils;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyUser;
-import com.fs.company.service.ICompanyUserService;
-import com.fs.his.vo.OptionsVO;
-import com.fs.qw.dto.UserProjectDTO;
-import com.github.pagehelper.PageHelper;
-import com.github.pagehelper.PageInfo;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 企业员工信息Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/companyUser")
-public class CompanyUserController extends BaseController
-{
-    @Autowired
-    private ICompanyUserService companyUserService;
-
-    /**
-     * 查询企业员工信息列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUser:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyUser companyUser)
-    {
-        startPage();
-        List<CompanyUser> list = companyUserService.selectCompanyUserList(companyUser);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出企业员工信息列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUser:export')")
-    @Log(title = "企业员工信息", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyUser companyUser)
-    {
-        List<CompanyUser> list = companyUserService.selectCompanyUserList(companyUser);
-        ExcelUtil<CompanyUser> util = new ExcelUtil<CompanyUser>(CompanyUser.class);
-        return util.exportExcel(list, "companyUser");
-    }
-
-    /**
-     * 获取企业员工信息详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUser:query')")
-    @GetMapping(value = "/{userId}")
-    public AjaxResult getInfo(@PathVariable("userId") Long userId)
-    {
-        return AjaxResult.success(companyUserService.selectCompanyUserById(userId));
-    }
-
-    /**
-     * 新增企业员工信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUser:add')")
-    @Log(title = "企业员工信息", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyUser companyUser)
-    {
-        if (UserConstants.NOT_UNIQUE.equals(companyUserService.checkUserNameUnique(companyUser.getUserName())))
-        {
-            return AjaxResult.error("新增用户'" + companyUser.getUserName() + "'失败,登录账号已存在");
-        }
-        return toAjax(companyUserService.insertCompanyUser(companyUser));
-    }
-
-    /**
-     * 修改企业员工信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUser:edit')")
-    @Log(title = "企业员工信息", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyUser companyUser)
-    {
-        return toAjax(companyUserService.updateCompanyUser(companyUser));
-    }
-
-    /**
-     * 删除企业员工信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUser:remove')")
-    @Log(title = "企业员工信息", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{userIds}")
-    public AjaxResult remove(@PathVariable Long[] userIds)
-    {
-        return toAjax(companyUserService.deleteCompanyUserByIds(userIds));
-    }
-
-    @GetMapping("/getAllUserlist")
-    public R getAllUserlist(@RequestParam Long companyId)
-    {
-        CompanyUser map=new CompanyUser();
-        map.setCompanyId(companyId);
-        List<CompanyUser> list = companyUserService.selectCompanyUserList(map);
-        return R.ok().put("data",list);
-    }
-    @GetMapping("/getAllUserListLimit")
-    public R getAllUserListLimit(@RequestParam(required = false) Long companyId,
-                                 @RequestParam(required = false) String keywords){
-        List<CompanyUser> list = companyUserService.getAllUserListLimit(companyId,keywords);
-        return R.ok().put("data", list);
-    }
-    @GetMapping("/getUserListByDeptId")
-    public R getUserListByDeptId(CompanyUser user)
-    {
-
-        List<CompanyUser> list = companyUserService.getUserListByDeptId(user);
-        return R.ok().put("data",list);
-    }
-
-    /**
-     * 获取所有的销售列表
-     * @param companyId
-     * @return
-     */
-    @GetMapping("/getUserList")
-    public R getUserList(@RequestParam("companyId") Long companyId)
-    {
-        CompanyUser map=new CompanyUser();
-        map.setCompanyId(companyId);
-        List<CompanyUser> list = companyUserService.selectCompanyUserList(map);
-        return  R.ok().put("data",list);
-    }
-
-    /**
-     * 更换会员归属销售
-     * @return
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUser:change')")
-    @Log(title = "更换会员归属", businessType = BusinessType.OTHER)
-    @PostMapping("/changeCompanyUser")
-    public AjaxResult changeCompanyUser(@RequestBody List<UserProjectDTO> users, @RequestParam Long companyUserId, @RequestParam Long companyId)
-    {
-        return toAjax(companyUserService.changeCompanyUser(users, companyUserId, companyId));
-    }
-    /**
-     * 根据登录的用户公司获取所有的销售
-     * @return
-     */
-    @GetMapping("/getCompanyUserList")
-    public R getCompanyUserList(@RequestParam Long companyId)
-    {
-        CompanyUser cu = new CompanyUser();
-        cu.setCompanyId(companyId);
-        List<CompanyUser> list = companyUserService.selectCompanyUserList(cu);
-        return  R.ok().put("data",list);
-    }
-
-    /**
-     * 获取用户列表
-     */
-    @GetMapping("/getCompanyUserListPage")
-    public TableDataInfo getCompanyUserListPage(CompanyUser user)
-    {
-        startPage();
-        List<CompanyUser> list = companyUserService.getCompanyUserList(user);
-        return getDataTable(list);
-    }
-    /**
-     * 根据销售名称模糊查询
-     * @param name  名称
-     * @return  list
-     */
-    @GetMapping("/getCompanyUserListLikeName")
-    public R getCompanyUserListLikeName(@RequestParam(required = false) String name,
-                                        @RequestParam(required = false, defaultValue = "1") Integer pageNum,
-                                        @RequestParam(required = false, defaultValue = "10") Integer pageSize,
-                                        @RequestParam(required = false) Long companyId) {
-        Map<String,Object> params = new HashMap<>();
-        params.put("nickName", name);
-        //查询多条数据传入公司
-//        if (pageSize>=200){
-        params.put("companyId", companyId);
-//        }
-        PageHelper.startPage(pageNum, pageSize);
-        List<OptionsVO> companyUserList = companyUserService.selectCompanyUserListByMap(params);
-        return R.ok().put("data", new PageInfo<>(companyUserList));
-    }
-}

+ 0 - 97
fs-admin/src/main/java/com/fs/company/controller/CompanyUserPostController.java

@@ -1,97 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyUserPost;
-import com.fs.company.service.ICompanyUserPostService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 用户与岗位关联Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/companyUserPost")
-public class CompanyUserPostController extends BaseController
-{
-    @Autowired
-    private ICompanyUserPostService companyUserPostService;
-
-    /**
-     * 查询用户与岗位关联列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUserPost:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyUserPost companyUserPost)
-    {
-        startPage();
-        List<CompanyUserPost> list = companyUserPostService.selectCompanyUserPostList(companyUserPost);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出用户与岗位关联列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUserPost:export')")
-    @Log(title = "用户与岗位关联", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyUserPost companyUserPost)
-    {
-        List<CompanyUserPost> list = companyUserPostService.selectCompanyUserPostList(companyUserPost);
-        ExcelUtil<CompanyUserPost> util = new ExcelUtil<CompanyUserPost>(CompanyUserPost.class);
-        return util.exportExcel(list, "companyUserPost");
-    }
-
-    /**
-     * 获取用户与岗位关联详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUserPost:query')")
-    @GetMapping(value = "/{userId}")
-    public AjaxResult getInfo(@PathVariable("userId") Long userId)
-    {
-        return AjaxResult.success(companyUserPostService.selectCompanyUserPostById(userId));
-    }
-
-    /**
-     * 新增用户与岗位关联
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUserPost:add')")
-    @Log(title = "用户与岗位关联", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyUserPost companyUserPost)
-    {
-        return toAjax(companyUserPostService.insertCompanyUserPost(companyUserPost));
-    }
-
-    /**
-     * 修改用户与岗位关联
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUserPost:edit')")
-    @Log(title = "用户与岗位关联", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyUserPost companyUserPost)
-    {
-        return toAjax(companyUserPostService.updateCompanyUserPost(companyUserPost));
-    }
-
-    /**
-     * 删除用户与岗位关联
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUserPost:remove')")
-    @Log(title = "用户与岗位关联", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{userIds}")
-    public AjaxResult remove(@PathVariable Long[] userIds)
-    {
-        return toAjax(companyUserPostService.deleteCompanyUserPostByIds(userIds));
-    }
-}

+ 0 - 97
fs-admin/src/main/java/com/fs/company/controller/CompanyUserRoleController.java

@@ -1,97 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyUserRole;
-import com.fs.company.service.ICompanyUserRoleService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 用户和角色关联Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/companyUserRole")
-public class CompanyUserRoleController extends BaseController
-{
-    @Autowired
-    private ICompanyUserRoleService companyUserRoleService;
-
-    /**
-     * 查询用户和角色关联列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUserRole:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyUserRole companyUserRole)
-    {
-        startPage();
-        List<CompanyUserRole> list = companyUserRoleService.selectCompanyUserRoleList(companyUserRole);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出用户和角色关联列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUserRole:export')")
-    @Log(title = "用户和角色关联", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyUserRole companyUserRole)
-    {
-        List<CompanyUserRole> list = companyUserRoleService.selectCompanyUserRoleList(companyUserRole);
-        ExcelUtil<CompanyUserRole> util = new ExcelUtil<CompanyUserRole>(CompanyUserRole.class);
-        return util.exportExcel(list, "companyUserRole");
-    }
-
-    /**
-     * 获取用户和角色关联详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUserRole:query')")
-    @GetMapping(value = "/{userId}")
-    public AjaxResult getInfo(@PathVariable("userId") Long userId)
-    {
-        return AjaxResult.success(companyUserRoleService.selectCompanyUserRoleById(userId));
-    }
-
-    /**
-     * 新增用户和角色关联
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUserRole:add')")
-    @Log(title = "用户和角色关联", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyUserRole companyUserRole)
-    {
-        return toAjax(companyUserRoleService.insertCompanyUserRole(companyUserRole));
-    }
-
-    /**
-     * 修改用户和角色关联
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUserRole:edit')")
-    @Log(title = "用户和角色关联", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyUserRole companyUserRole)
-    {
-        return toAjax(companyUserRoleService.updateCompanyUserRole(companyUserRole));
-    }
-
-    /**
-     * 删除用户和角色关联
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyUserRole:remove')")
-    @Log(title = "用户和角色关联", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{userIds}")
-    public AjaxResult remove(@PathVariable Long[] userIds)
-    {
-        return toAjax(companyUserRoleService.deleteCompanyUserRoleByIds(userIds));
-    }
-}

+ 0 - 104
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceApiController.java

@@ -1,104 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyVoiceApi;
-import com.fs.company.service.ICompanyVoiceApiService;
-import com.fs.voice.service.IVoiceService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 呼叫接口Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/companyVoiceApi")
-public class CompanyVoiceApiController extends BaseController {
-    @Autowired
-    private ICompanyVoiceApiService companyVoiceApiService;
-    @Autowired
-    private IVoiceService voiceService;
-
-    /**
-     * 查询呼叫接口列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceApi:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyVoiceApi companyVoiceApi) {
-        startPage();
-        List<CompanyVoiceApi> list = companyVoiceApiService.selectCompanyVoiceApiList(companyVoiceApi);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出呼叫接口列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceApi:export')")
-    @Log(title = "呼叫接口", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyVoiceApi companyVoiceApi) {
-        List<CompanyVoiceApi> list = companyVoiceApiService.selectCompanyVoiceApiList(companyVoiceApi);
-        ExcelUtil<CompanyVoiceApi> util = new ExcelUtil<CompanyVoiceApi>(CompanyVoiceApi.class);
-        return util.exportExcel(list, "companyVoiceApi");
-    }
-
-    /**
-     * 获取呼叫接口详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceApi:query')")
-    @GetMapping(value = "/{apiId}")
-    public AjaxResult getInfo(@PathVariable("apiId") Long apiId) {
-        return AjaxResult.success(companyVoiceApiService.selectCompanyVoiceApiById(apiId));
-    }
-
-    /**
-     * 新增呼叫接口
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceApi:add')")
-    @Log(title = "呼叫接口", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyVoiceApi companyVoiceApi) {
-        return toAjax(companyVoiceApiService.insertCompanyVoiceApi(companyVoiceApi));
-    }
-
-    /**
-     * 修改呼叫接口
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceApi:edit')")
-    @Log(title = "呼叫接口", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyVoiceApi companyVoiceApi) {
-        return toAjax(companyVoiceApiService.updateCompanyVoiceApi(companyVoiceApi));
-    }
-
-    /**
-     * 删除呼叫接口
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceApi:remove')")
-    @Log(title = "呼叫接口", businessType = BusinessType.DELETE)
-    @DeleteMapping("/{apiIds}")
-    public AjaxResult remove(@PathVariable Long[] apiIds) {
-        return toAjax(companyVoiceApiService.deleteCompanyVoiceApiByIds(apiIds));
-    }
-
-    @GetMapping("/getVoiceApiList")
-    public R getVoiceApiList() {
-        CompanyVoiceApi map = new CompanyVoiceApi();
-        map.setStatus(1);
-        List<CompanyVoiceApi> list = companyVoiceApiService.selectCompanyVoiceApiList(map);
-        return R.ok().put("data", list);
-    }
-
-
-}

+ 0 - 97
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceBlacklistController.java

@@ -1,97 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyVoiceBlacklist;
-import com.fs.company.service.ICompanyVoiceBlacklistService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 黑名单Controller
- *
- * @author fs
- * @date 2023-02-23
- */
-@RestController
-@RequestMapping("/company/companyVoiceBlacklist")
-public class CompanyVoiceBlacklistController extends BaseController
-{
-    @Autowired
-    private ICompanyVoiceBlacklistService companyVoiceBlacklistService;
-
-    /**
-     * 查询黑名单列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceBlacklist:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyVoiceBlacklist companyVoiceBlacklist)
-    {
-        startPage();
-        List<CompanyVoiceBlacklist> list = companyVoiceBlacklistService.selectCompanyVoiceBlacklistList(companyVoiceBlacklist);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出黑名单列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceBlacklist:export')")
-    @Log(title = "黑名单", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyVoiceBlacklist companyVoiceBlacklist)
-    {
-        List<CompanyVoiceBlacklist> list = companyVoiceBlacklistService.selectCompanyVoiceBlacklistList(companyVoiceBlacklist);
-        ExcelUtil<CompanyVoiceBlacklist> util = new ExcelUtil<CompanyVoiceBlacklist>(CompanyVoiceBlacklist.class);
-        return util.exportExcel(list, "companyVoiceBlacklist");
-    }
-
-    /**
-     * 获取黑名单详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceBlacklist:query')")
-    @GetMapping(value = "/{blacklistId}")
-    public AjaxResult getInfo(@PathVariable("blacklistId") Long blacklistId)
-    {
-        return AjaxResult.success(companyVoiceBlacklistService.selectCompanyVoiceBlacklistById(blacklistId));
-    }
-
-    /**
-     * 新增黑名单
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceBlacklist:add')")
-    @Log(title = "黑名单", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyVoiceBlacklist companyVoiceBlacklist)
-    {
-        return toAjax(companyVoiceBlacklistService.insertCompanyVoiceBlacklist(companyVoiceBlacklist));
-    }
-
-    /**
-     * 修改黑名单
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceBlacklist:edit')")
-    @Log(title = "黑名单", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyVoiceBlacklist companyVoiceBlacklist)
-    {
-        return toAjax(companyVoiceBlacklistService.updateCompanyVoiceBlacklist(companyVoiceBlacklist));
-    }
-
-    /**
-     * 删除黑名单
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceBlacklist:remove')")
-    @Log(title = "黑名单", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{blacklistIds}")
-    public AjaxResult remove(@PathVariable Long[] blacklistIds)
-    {
-        return toAjax(companyVoiceBlacklistService.deleteCompanyVoiceBlacklistByIds(blacklistIds));
-    }
-}

+ 0 - 137
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceCallerController.java

@@ -1,137 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyVoiceCaller;
-import com.fs.company.param.CompanyVoiceCallerImportParam;
-import com.fs.company.param.CompanyVoiceCallerParam;
-import com.fs.company.param.CompanyVoiceCallerRecoverParam;
-import com.fs.company.service.ICompanyVoiceCallerService;
-import com.fs.company.vo.CompanyVoiceCallerListVO;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.util.List;
-
-/**
- * 企业用户坐席Controller
- *
- * @author fs
- * @date 2023-02-23
- */
-@RestController
-@RequestMapping("/company/companyVoiceCaller")
-public class CompanyVoiceCallerController extends BaseController
-{
-    @Autowired
-    private ICompanyVoiceCallerService companyVoiceCallerService;
-
-    /**
-     * 查询企业用户坐席列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceCaller:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyVoiceCallerParam param)
-    {
-        startPage();
-        List<CompanyVoiceCallerListVO> list = companyVoiceCallerService.selectCompanyVoiceCallerListVO(param);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出企业用户坐席列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceCaller:export')")
-    @Log(title = "企业用户坐席", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyVoiceCallerParam param)
-    {
-        List<CompanyVoiceCallerListVO> list = companyVoiceCallerService.selectCompanyVoiceCallerListVO(param);
-        ExcelUtil<CompanyVoiceCallerListVO> util = new ExcelUtil<CompanyVoiceCallerListVO>(CompanyVoiceCallerListVO.class);
-        return util.exportExcel(list, "companyVoiceCaller");
-    }
-
-    /**
-     * 获取企业用户坐席详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceCaller:query')")
-    @GetMapping(value = "/{callingId}")
-    public AjaxResult getInfo(@PathVariable("callingId") Long callingId)
-    {
-        return AjaxResult.success(companyVoiceCallerService.selectCompanyVoiceCallerById(callingId));
-    }
-
-    /**
-     * 新增企业用户坐席
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceCaller:add')")
-    @Log(title = "企业用户坐席", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyVoiceCaller companyVoiceCaller)
-    {
-        return toAjax(companyVoiceCallerService.insertCompanyVoiceCaller(companyVoiceCaller));
-    }
-
-    /**
-     * 修改企业用户坐席
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceCaller:edit')")
-    @Log(title = "企业用户坐席", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyVoiceCaller companyVoiceCaller)
-    {
-        return toAjax(companyVoiceCallerService.updateCompanyVoiceCaller(companyVoiceCaller));
-    }
-
-    /**
-     * 删除企业用户坐席
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceCaller:remove')")
-    @Log(title = "企业用户坐席", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{callingIds}")
-    public AjaxResult remove(@PathVariable Long[] callingIds)
-    {
-        return toAjax(companyVoiceCallerService.deleteCompanyVoiceCallerByIds(callingIds));
-    }
-
-
-    @Log(title = "导入线索客户", businessType = BusinessType.IMPORT)
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceCaller:import')")
-    @PostMapping("/importData")
-    public AjaxResult importLineData(MultipartFile file) throws Exception
-    {
-        ExcelUtil<CompanyVoiceCallerImportParam> util = new ExcelUtil<CompanyVoiceCallerImportParam>(CompanyVoiceCallerImportParam.class);
-        List<CompanyVoiceCallerImportParam> list = util.importExcel(file.getInputStream());
-        String message = companyVoiceCallerService.importCompanyVoiceCaller(list);
-        return AjaxResult.success(message);
-    }
-    //下载模板
-    @GetMapping("/importTemplate")
-    public AjaxResult importLineTemplate()
-    {
-        ExcelUtil<CompanyVoiceCallerImportParam> util = new ExcelUtil<CompanyVoiceCallerImportParam>(CompanyVoiceCallerImportParam.class);
-        return util.importTemplateExcel("分机号数据");
-    }
-
-    //回收
-    @PostMapping("/recover")
-    public R recover(@RequestBody CompanyVoiceCallerRecoverParam param)
-    {
-        CompanyVoiceCaller caller=companyVoiceCallerService.selectCompanyVoiceCallerById(param.getCallerId());
-        caller.setCompanyId(0l);
-        caller.setCompanyUserId(0l);
-        caller.setMobile("");
-        caller.setStatus(1);
-        caller.setBindTime(null);
-        companyVoiceCallerService.updateCompanyVoiceCaller(caller);
-        return R.ok();
-
-    }
-}

+ 0 - 169
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceConfigController.java

@@ -1,169 +0,0 @@
-package com.fs.company.controller;
-
-import cn.hutool.json.JSONUtil;
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.config.CompanyVoiceCalleeConfig;
-import com.fs.company.config.CompanyVoiceCallerConfig;
-import com.fs.company.domain.CompanyVoiceConfig;
-import com.fs.company.param.CompanyVoiceConfigParam;
-import com.fs.company.service.ICompanyService;
-import com.fs.company.service.ICompanyVoiceConfigService;
-import com.fs.company.vo.CompanyVoiceConfigListVO;
-import com.fs.company.vo.CompanyVoiceConfigVO;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 呼叫频率配置Controller
- *
- * @author fs
- * @date 2021-11-13
- */
-@RestController
-@RequestMapping("/company/companyVoiceConfig")
-public class CompanyVoiceConfigController extends BaseController
-{
-    @Autowired
-    private ICompanyVoiceConfigService companyVoiceConfigService;
-    @Autowired
-    private ICompanyService companyService;
-    /**
-     * 查询呼叫频率配置列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceConfig:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyVoiceConfig companyVoiceConfig)
-    {
-        startPage();
-        List<CompanyVoiceConfigListVO> list = companyVoiceConfigService.selectCompanyVoiceConfigListVO(companyVoiceConfig);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出呼叫频率配置列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceConfig:export')")
-    @Log(title = "呼叫频率配置", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyVoiceConfig companyVoiceConfig)
-    {
-        List<CompanyVoiceConfig> list = companyVoiceConfigService.selectCompanyVoiceConfigList(companyVoiceConfig);
-        ExcelUtil<CompanyVoiceConfig> util = new ExcelUtil<CompanyVoiceConfig>(CompanyVoiceConfig.class);
-        return util.exportExcel(list, "companyVoiceConfig");
-    }
-
-    /**
-     * 获取呼叫频率配置详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceConfig:query')")
-    @GetMapping(value = "/{configId}")
-    public AjaxResult getInfo(@PathVariable("configId") Long configId)
-    {
-        CompanyVoiceConfig config=companyVoiceConfigService.selectCompanyVoiceConfigById(configId);
-        CompanyVoiceCalleeConfig voiceCalleeConfigBO=JSONUtil.toBean(config.getCalleeJson(), CompanyVoiceCalleeConfig.class);
-        CompanyVoiceCallerConfig voiceCallerConfigBO=JSONUtil.toBean(config.getCallerJson(), CompanyVoiceCallerConfig.class);
-
-
-        CompanyVoiceConfigVO vo=new CompanyVoiceConfigVO();
-        vo.setCompanyId(config.getCompanyId());
-        vo.setConfigId(config.getConfigId());
-        vo.setCalleeDay(voiceCalleeConfigBO.getCalleeDay());
-        vo.setCalleeHour(voiceCalleeConfigBO.getCalleeHour());
-        vo.setCalleeWeek(voiceCalleeConfigBO.getCalleeWeek());
-        vo.setCalleeMinute(voiceCalleeConfigBO.getCalleeMinute());
-        vo.setCalleeMonth(voiceCalleeConfigBO.getCalleeMonth());
-
-        vo.setCallerDay(voiceCallerConfigBO.getCallerDay());
-        vo.setCallerHour(voiceCallerConfigBO.getCallerHour());
-        vo.setCallerWeek(voiceCallerConfigBO.getCallerWeek());
-        vo.setCallerMonth(voiceCallerConfigBO.getCallerMonth());
-        vo.setCallerMinute(voiceCallerConfigBO.getCallerMinute());
-
-        return AjaxResult.success(vo);
-    }
-
-    /**
-     * 新增呼叫频率配置
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceConfig:add')")
-    @Log(title = "呼叫频率配置", businessType = BusinessType.INSERT)
-    @PostMapping
-    public R add(@RequestBody CompanyVoiceConfigParam companyVoiceConfig)
-    {
-        //查询企业是否存在
-        CompanyVoiceConfig config=companyVoiceConfigService.selectCompanyVoiceConfigByCompanyId(companyVoiceConfig.getCompanyId());
-        if(config!=null){
-            return R.error("企业已存在");
-        }
-        CompanyVoiceCalleeConfig voiceCalleeConfigBO=new CompanyVoiceCalleeConfig();
-        voiceCalleeConfigBO.setCalleeDay(companyVoiceConfig.getCalleeDay());
-        voiceCalleeConfigBO.setCalleeHour(companyVoiceConfig.getCalleeHour());
-        voiceCalleeConfigBO.setCalleeMinute(companyVoiceConfig.getCalleeMinute());
-        voiceCalleeConfigBO.setCalleeMonth(companyVoiceConfig.getCalleeMonth());
-        voiceCalleeConfigBO.setCalleeWeek(companyVoiceConfig.getCalleeWeek());
-
-        CompanyVoiceCallerConfig voiceCallerConfigBO=new CompanyVoiceCallerConfig();
-        voiceCallerConfigBO.setCallerDay(companyVoiceConfig.getCallerDay());
-        voiceCallerConfigBO.setCallerHour(companyVoiceConfig.getCallerHour());
-        voiceCallerConfigBO.setCallerMinute(companyVoiceConfig.getCallerMinute());
-        voiceCallerConfigBO.setCallerWeek(companyVoiceConfig.getCallerWeek());
-        voiceCallerConfigBO.setCallerMonth(companyVoiceConfig.getCallerMonth());
-        config=new CompanyVoiceConfig();
-        config.setCompanyId(companyVoiceConfig.getCompanyId());
-        config.setCalleeJson(JSONUtil.toJsonStr(voiceCalleeConfigBO));
-        config.setCallerJson(JSONUtil.toJsonStr(voiceCallerConfigBO));
-        companyVoiceConfigService.insertCompanyVoiceConfig(config);
-        return R.ok("操作成功");
-    }
-
-    /**
-     * 修改呼叫频率配置
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceConfig:edit')")
-    @Log(title = "呼叫频率配置", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public R edit(@RequestBody CompanyVoiceConfigParam companyVoiceConfig)
-    {
-
-        CompanyVoiceCalleeConfig voiceCalleeConfigBO=new CompanyVoiceCalleeConfig();
-        voiceCalleeConfigBO.setCalleeDay(companyVoiceConfig.getCalleeDay());
-        voiceCalleeConfigBO.setCalleeHour(companyVoiceConfig.getCalleeHour());
-        voiceCalleeConfigBO.setCalleeMinute(companyVoiceConfig.getCalleeMinute());
-        voiceCalleeConfigBO.setCalleeMonth(companyVoiceConfig.getCalleeMonth());
-        voiceCalleeConfigBO.setCalleeWeek(companyVoiceConfig.getCalleeWeek());
-
-        CompanyVoiceCallerConfig voiceCallerConfigBO=new CompanyVoiceCallerConfig();
-        voiceCallerConfigBO.setCallerDay(companyVoiceConfig.getCallerDay());
-        voiceCallerConfigBO.setCallerHour(companyVoiceConfig.getCallerHour());
-        voiceCallerConfigBO.setCallerMinute(companyVoiceConfig.getCallerMinute());
-        voiceCallerConfigBO.setCallerWeek(companyVoiceConfig.getCallerWeek());
-        voiceCallerConfigBO.setCallerMonth(companyVoiceConfig.getCallerMonth());
-        CompanyVoiceConfig config=new CompanyVoiceConfig();
-        config.setConfigId(companyVoiceConfig.getConfigId());
-        config.setCalleeJson(JSONUtil.toJsonStr(voiceCalleeConfigBO));
-        config.setCallerJson(JSONUtil.toJsonStr(voiceCallerConfigBO));
-
-        companyVoiceConfigService.updateCompanyVoiceConfig(config);
-        return R.ok("修改成功");
-    }
-
-    /**
-     * 删除呼叫频率配置
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceConfig:remove')")
-    @Log(title = "呼叫频率配置", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{configIds}")
-    public AjaxResult remove(@PathVariable Long[] configIds)
-    {
-        return toAjax(companyVoiceConfigService.deleteCompanyVoiceConfigByIds(configIds));
-    }
-}

+ 0 - 102
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceController.java

@@ -1,102 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyVoice;
-import com.fs.company.service.ICompanyVoiceService;
-import com.fs.company.vo.CompanyVoiceListVO;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 企业通话Controller
- *
- * @author fs
- * @date 2023-02-23
- */
-@RestController
-@RequestMapping("/company/companyVoice")
-public class CompanyVoiceController extends BaseController
-{
-    @Autowired
-    private ICompanyVoiceService companyVoiceService;
-
-    /**
-     * 查询企业通话列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoice:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyVoice companyVoice)
-    {
-
-        startPage();
-        List<CompanyVoiceListVO> list = companyVoiceService.selectCompanyVoiceListVO(companyVoice);
-        for (CompanyVoiceListVO vo : list){
-            vo.setUseTimes(vo.getTotalTimes()-vo.getTimes());
-        }
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出企业通话列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoice:export')")
-    @Log(title = "企业通话", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyVoice companyVoice)
-    {
-        List<CompanyVoice> list = companyVoiceService.selectCompanyVoiceList(companyVoice);
-        ExcelUtil<CompanyVoice> util = new ExcelUtil<CompanyVoice>(CompanyVoice.class);
-        return util.exportExcel(list, "companyVoice");
-    }
-
-    /**
-     * 获取企业通话详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoice:query')")
-    @GetMapping(value = "/{voiceId}")
-    public AjaxResult getInfo(@PathVariable("voiceId") Long voiceId)
-    {
-        return AjaxResult.success(companyVoiceService.selectCompanyVoiceById(voiceId));
-    }
-
-    /**
-     * 新增企业通话
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoice:add')")
-    @Log(title = "企业通话", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyVoice companyVoice)
-    {
-        return toAjax(companyVoiceService.insertCompanyVoice(companyVoice));
-    }
-
-    /**
-     * 修改企业通话
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoice:edit')")
-    @Log(title = "企业通话", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyVoice companyVoice)
-    {
-        return toAjax(companyVoiceService.updateCompanyVoice(companyVoice));
-    }
-
-    /**
-     * 删除企业通话
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoice:remove')")
-    @Log(title = "企业通话", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{voiceIds}")
-    public AjaxResult remove(@PathVariable Long[] voiceIds)
-    {
-        return toAjax(companyVoiceService.deleteCompanyVoiceByIds(voiceIds));
-    }
-}

+ 0 - 106
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceDialogController.java

@@ -1,106 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyVoiceDialog;
-import com.fs.company.service.ICompanyVoiceDialogService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * AI外呼话术Controller
- * 
- * @author fs
- * @date 2024-12-04
- */
-@RestController
-@RequestMapping("/company/companyVoiceDialog")
-public class CompanyVoiceDialogController extends BaseController
-{
-    @Autowired
-    private ICompanyVoiceDialogService companyVoiceDialogService;
-
-    /**
-     * 查询AI外呼话术列表
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceDialog:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyVoiceDialog companyVoiceDialog)
-    {
-        startPage();
-        List<CompanyVoiceDialog> list = companyVoiceDialogService.selectCompanyVoiceDialogList(companyVoiceDialog);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出AI外呼话术列表
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceDialog:export')")
-    @Log(title = "AI外呼话术", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyVoiceDialog companyVoiceDialog)
-    {
-        List<CompanyVoiceDialog> list = companyVoiceDialogService.selectCompanyVoiceDialogList(companyVoiceDialog);
-        ExcelUtil<CompanyVoiceDialog> util = new ExcelUtil<CompanyVoiceDialog>(CompanyVoiceDialog.class);
-        return util.exportExcel(list, "dialog");
-    }
-
-    /**
-     * 获取AI外呼话术详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceDialog:query')")
-    @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") Long id)
-    {
-        return AjaxResult.success(companyVoiceDialogService.selectCompanyVoiceDialogById(id));
-    }
-
-    /**
-     * 新增AI外呼话术
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceDialog:add')")
-    @Log(title = "AI外呼话术", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyVoiceDialog companyVoiceDialog)
-    {
-        return toAjax(companyVoiceDialogService.insertCompanyVoiceDialog(companyVoiceDialog));
-    }
-
-    /**
-     * 修改AI外呼话术
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceDialog:edit')")
-    @Log(title = "AI外呼话术", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyVoiceDialog companyVoiceDialog)
-    {
-        return toAjax(companyVoiceDialogService.updateCompanyVoiceDialog(companyVoiceDialog));
-    }
-
-    /**
-     * 删除AI外呼话术
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceDialog:remove')")
-    @Log(title = "AI外呼话术", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{ids}")
-    public AjaxResult remove(@PathVariable Long[] ids)
-    {
-        return toAjax(companyVoiceDialogService.deleteCompanyVoiceDialogByIds(ids));
-    }
-    /**
-     * 获取话术配置链接
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceDialog:list')")
-    @Log(title = "话术配置链接", businessType = BusinessType.DELETE)
-	@GetMapping("/getConfigUrl")
-    public AjaxResult getConfigUrl(Long id){
-        return AjaxResult.success("", companyVoiceDialogService.getConfigUrl(id));
-    }
-}

+ 0 - 133
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceLogsController.java

@@ -1,133 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.ParseUtils;
-import com.fs.common.utils.StringUtils;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyVoiceLogs;
-import com.fs.company.param.CompanyVoiceLogsParam;
-import com.fs.company.service.ICompanyVoiceLogsService;
-import com.fs.company.vo.CompanyVoiceLogsExportVO;
-import com.fs.company.vo.CompanyVoiceLogsVO;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 通话记录Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/companyVoiceLogs")
-public class CompanyVoiceLogsController extends BaseController
-{
-    @Autowired
-    private ICompanyVoiceLogsService companyVoiceLogsService;
-
-    /**
-     * 查询通话记录列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceLogs:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyVoiceLogsParam param)
-    {
-        startPage();
-        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
-            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
-        }
-        if(!StringUtils.isEmpty(param.getDateRange())){
-            param.setStartTimeList(param.getDateRange().split("--"));
-        }
-        List<CompanyVoiceLogsVO> list = companyVoiceLogsService.selectCompanyVoiceLogsVOList(param);
-        for(CompanyVoiceLogsVO vo : list){
-            vo.setCalleePhone(ParseUtils.parsePhone(vo.getCalleePhone()));
-            vo.setCallerPhone(ParseUtils.parsePhone(vo.getCallerPhone()));
-            vo.setDisplayCalleeNumber(ParseUtils.parsePhone(vo.getDisplayCalleeNumber()));
-            vo.setDisplayCallerNumber(ParseUtils.parsePhone(vo.getDisplayCallerNumber()));
-
-
-            if (vo.getRemark()!=null&&vo.getRemark().length()>11){
-                StringBuilder replace = new StringBuilder(vo.getRemark()).replace(vo.getRemark().length() - 9, vo.getRemark().length() - 4, "*****");
-                vo.setRemark(replace.toString());
-
-            }
-        }
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出通话记录列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceLogs:export')")
-    @Log(title = "通话记录", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyVoiceLogsParam param)
-    {
-        if(!StringUtils.isEmpty(param.getCreateTimeRange())){
-            param.setCreateTimeList(param.getCreateTimeRange().split("--"));
-        }
-        if(!StringUtils.isEmpty(param.getDateRange())){
-            param.setStartTimeList(param.getDateRange().split("--"));
-        }
-        List<CompanyVoiceLogsExportVO> list = companyVoiceLogsService.selectCompanyVoiceLogsExportVOList(param);
-        for(CompanyVoiceLogsExportVO vo : list){
-            vo.setCalleePhone(ParseUtils.parsePhone(vo.getCalleePhone()));
-            vo.setCallerPhone(ParseUtils.parsePhone(vo.getCallerPhone()));
-            vo.setDisplayCalleeNumber(ParseUtils.parsePhone(vo.getDisplayCalleeNumber()));
-            vo.setDisplayCallerNumber(ParseUtils.parsePhone(vo.getDisplayCallerNumber()));
-        }
-        ExcelUtil<CompanyVoiceLogsExportVO> util = new ExcelUtil<CompanyVoiceLogsExportVO>(CompanyVoiceLogsExportVO.class);
-        return util.exportExcel(list, "通话记录");
-    }
-
-    /**
-     * 获取通话记录详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceLogs:query')")
-    @GetMapping(value = "/{voiceId}")
-    public AjaxResult getInfo(@PathVariable("voiceId") Long voiceId)
-    {
-        return AjaxResult.success(companyVoiceLogsService.selectCompanyVoiceLogsById(voiceId));
-    }
-
-    /**
-     * 新增通话记录
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceLogs:add')")
-    @Log(title = "通话记录", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyVoiceLogs companyVoiceLogs)
-    {
-        return toAjax(companyVoiceLogsService.insertCompanyVoiceLogs(companyVoiceLogs));
-    }
-
-    /**
-     * 修改通话记录
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceLogs:edit')")
-    @Log(title = "通话记录", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyVoiceLogs companyVoiceLogs)
-    {
-        return toAjax(companyVoiceLogsService.updateCompanyVoiceLogs(companyVoiceLogs));
-    }
-
-    /**
-     * 删除通话记录
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceLogs:remove')")
-    @Log(title = "通话记录", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{voiceIds}")
-    public AjaxResult remove(@PathVariable Long[] voiceIds)
-    {
-        return toAjax(companyVoiceLogsService.deleteCompanyVoiceLogsByIds(voiceIds));
-    }
-}

+ 0 - 124
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceMobileController.java

@@ -1,124 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyVoiceMobile;
-import com.fs.company.service.ICompanyVoiceMobileService;
-import com.fs.company.vo.CompanyVoiceMobileVO;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-import java.util.List;
-
-/**
- * 中间号Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/companyVoiceMobile")
-public class CompanyVoiceMobileController extends BaseController
-{
-    @Autowired
-    private ICompanyVoiceMobileService companyVoiceMobileService;
-
-    /**
-     * 查询中间号列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceMobile:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyVoiceMobile companyVoiceMobile)
-    {
-        startPage();
-        List<CompanyVoiceMobileVO> list = companyVoiceMobileService.selectCompanyVoiceMobileVOList(companyVoiceMobile);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出中间号列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceMobile:export')")
-    @Log(title = "中间号", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyVoiceMobile companyVoiceMobile)
-    {
-        List<CompanyVoiceMobile> list = companyVoiceMobileService.selectCompanyVoiceMobileList(companyVoiceMobile);
-        ExcelUtil<CompanyVoiceMobile> util = new ExcelUtil<CompanyVoiceMobile>(CompanyVoiceMobile.class);
-        return util.exportExcel(list, "companyVoiceMobile");
-    }
-
-    /**
-     * 获取中间号详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceMobile:query')")
-    @GetMapping(value = "/{mobileId}")
-    public AjaxResult getInfo(@PathVariable("mobileId") Long mobileId)
-    {
-        return AjaxResult.success(companyVoiceMobileService.selectCompanyVoiceMobileById(mobileId));
-    }
-
-    /**
-     * 新增中间号
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceMobile:add')")
-    @Log(title = "中间号", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyVoiceMobile companyVoiceMobile)
-    {
-        if(companyVoiceMobile.getMobileType().equals(1)){
-            companyVoiceMobile.setCompanyId(0l);
-        }
-        return toAjax(companyVoiceMobileService.insertCompanyVoiceMobile(companyVoiceMobile));
-    }
-
-    /**
-     * 修改中间号
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceMobile:edit')")
-    @Log(title = "中间号", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyVoiceMobile companyVoiceMobile)
-    {
-        if(companyVoiceMobile.getMobileType().equals(1)){
-            companyVoiceMobile.setCompanyId(0l);
-        }
-
-        return toAjax(companyVoiceMobileService.updateCompanyVoiceMobile(companyVoiceMobile));
-    }
-
-    /**
-     * 删除中间号
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceMobile:remove')")
-    @Log(title = "中间号", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{mobileIds}")
-    public AjaxResult remove(@PathVariable Long[] mobileIds)
-    {
-        return toAjax(companyVoiceMobileService.deleteCompanyVoiceMobileByIds(mobileIds));
-    }
-
-    @Log(title = "导入线索客户", businessType = BusinessType.IMPORT)
-    @PreAuthorize("@ss.hasPermi('company:companyVoiceMobile:import')")
-    @PostMapping("/importData")
-    public AjaxResult importLineData(MultipartFile file) throws Exception
-    {
-        ExcelUtil<CompanyVoiceMobile> util = new ExcelUtil<CompanyVoiceMobile>(CompanyVoiceMobile.class);
-        List<CompanyVoiceMobile> list = util.importExcel(file.getInputStream());
-        String message = companyVoiceMobileService.importMobile(list);
-        return AjaxResult.success(message);
-    }
-    //下载模板
-    @GetMapping("/importTemplate")
-    public AjaxResult importLineTemplate()
-    {
-        ExcelUtil<CompanyVoiceMobile> util = new ExcelUtil<CompanyVoiceMobile>(CompanyVoiceMobile.class);
-        return util.importTemplateExcel("号码数据");
-    }
-}

+ 0 - 97
fs-admin/src/main/java/com/fs/company/controller/CompanyVoicePackageController.java

@@ -1,97 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyVoicePackage;
-import com.fs.company.service.ICompanyVoicePackageService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 套餐Controller
- *
- * @author fs
- * @date 2023-02-23
- */
-@RestController
-@RequestMapping("/company/companyVoicePackage")
-public class CompanyVoicePackageController extends BaseController
-{
-    @Autowired
-    private ICompanyVoicePackageService companyVoicePackageService;
-
-    /**
-     * 查询套餐列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoicePackage:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyVoicePackage companyVoicePackage)
-    {
-        startPage();
-        List<CompanyVoicePackage> list = companyVoicePackageService.selectCompanyVoicePackageList(companyVoicePackage);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出套餐列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoicePackage:export')")
-    @Log(title = "套餐", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyVoicePackage companyVoicePackage)
-    {
-        List<CompanyVoicePackage> list = companyVoicePackageService.selectCompanyVoicePackageList(companyVoicePackage);
-        ExcelUtil<CompanyVoicePackage> util = new ExcelUtil<CompanyVoicePackage>(CompanyVoicePackage.class);
-        return util.exportExcel(list, "companyVoicePackage");
-    }
-
-    /**
-     * 获取套餐详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoicePackage:query')")
-    @GetMapping(value = "/{packageId}")
-    public AjaxResult getInfo(@PathVariable("packageId") Long packageId)
-    {
-        return AjaxResult.success(companyVoicePackageService.selectCompanyVoicePackageById(packageId));
-    }
-
-    /**
-     * 新增套餐
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoicePackage:add')")
-    @Log(title = "套餐", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyVoicePackage companyVoicePackage)
-    {
-        return toAjax(companyVoicePackageService.insertCompanyVoicePackage(companyVoicePackage));
-    }
-
-    /**
-     * 修改套餐
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoicePackage:edit')")
-    @Log(title = "套餐", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyVoicePackage companyVoicePackage)
-    {
-        return toAjax(companyVoicePackageService.updateCompanyVoicePackage(companyVoicePackage));
-    }
-
-    /**
-     * 删除套餐
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoicePackage:remove')")
-    @Log(title = "套餐", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{packageIds}")
-    public AjaxResult remove(@PathVariable Long[] packageIds)
-    {
-        return toAjax(companyVoicePackageService.deleteCompanyVoicePackageByIds(packageIds));
-    }
-}

+ 0 - 99
fs-admin/src/main/java/com/fs/company/controller/CompanyVoicePackageOrderController.java

@@ -1,99 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyVoicePackageOrder;
-import com.fs.company.param.CompanyVoicePackageOrderListParam;
-import com.fs.company.service.ICompanyVoicePackageOrderService;
-import com.fs.company.vo.CompanyVoicePackageOrderListVO;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 套餐订单Controller
- *
- * @author fs
- * @date 2023-02-23
- */
-@RestController
-@RequestMapping("/company/companyVoicePackageOrder")
-public class CompanyVoicePackageOrderController extends BaseController
-{
-    @Autowired
-    private ICompanyVoicePackageOrderService companyVoicePackageOrderService;
-
-    /**
-     * 查询套餐订单列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoicePackageOrder:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyVoicePackageOrderListParam param)
-    {
-        startPage();
-        List<CompanyVoicePackageOrderListVO> list = companyVoicePackageOrderService.selectCompanyVoicePackageOrderListVO(param);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出套餐订单列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoicePackageOrder:export')")
-    @Log(title = "套餐订单", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyVoicePackageOrderListParam param)
-    {
-        List<CompanyVoicePackageOrderListVO> list = companyVoicePackageOrderService.selectCompanyVoicePackageOrderListVO(param);
-        ExcelUtil<CompanyVoicePackageOrderListVO> util = new ExcelUtil<CompanyVoicePackageOrderListVO>(CompanyVoicePackageOrderListVO.class);
-        return util.exportExcel(list, "companyVoicePackageOrder");
-    }
-
-    /**
-     * 获取套餐订单详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoicePackageOrder:query')")
-    @GetMapping(value = "/{orderId}")
-    public AjaxResult getInfo(@PathVariable("orderId") Long orderId)
-    {
-        return AjaxResult.success(companyVoicePackageOrderService.selectCompanyVoicePackageOrderById(orderId));
-    }
-
-    /**
-     * 新增套餐订单
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoicePackageOrder:add')")
-    @Log(title = "套餐订单", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyVoicePackageOrder companyVoicePackageOrder)
-    {
-        return toAjax(companyVoicePackageOrderService.insertCompanyVoicePackageOrder(companyVoicePackageOrder));
-    }
-
-    /**
-     * 修改套餐订单
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoicePackageOrder:edit')")
-    @Log(title = "套餐订单", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyVoicePackageOrder companyVoicePackageOrder)
-    {
-        return toAjax(companyVoicePackageOrderService.updateCompanyVoicePackageOrder(companyVoicePackageOrder));
-    }
-
-    /**
-     * 删除套餐订单
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyVoicePackageOrder:remove')")
-    @Log(title = "套餐订单", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{orderIds}")
-    public AjaxResult remove(@PathVariable Long[] orderIds)
-    {
-        return toAjax(companyVoicePackageOrderService.deleteCompanyVoicePackageOrderByIds(orderIds));
-    }
-}

+ 0 - 97
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceRoboticCalleesController.java

@@ -1,97 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyVoiceRoboticCallees;
-import com.fs.company.service.ICompanyVoiceRoboticCalleesService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 任务外呼电话Controller
- * 
- * @author fs
- * @date 2024-12-04
- */
-@RestController
-@RequestMapping("/company/companyVoiceRoboticCallees")
-public class CompanyVoiceRoboticCalleesController extends BaseController
-{
-    @Autowired
-    private ICompanyVoiceRoboticCalleesService companyVoiceRoboticCalleesService;
-
-    /**
-     * 查询任务外呼电话列表
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceRoboticCallees:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyVoiceRoboticCallees companyVoiceRoboticCallees)
-    {
-        startPage();
-        List<CompanyVoiceRoboticCallees> list = companyVoiceRoboticCalleesService.selectCompanyVoiceRoboticCalleesList(companyVoiceRoboticCallees);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出任务外呼电话列表
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceRoboticCallees:export')")
-    @Log(title = "任务外呼电话", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyVoiceRoboticCallees companyVoiceRoboticCallees)
-    {
-        List<CompanyVoiceRoboticCallees> list = companyVoiceRoboticCalleesService.selectCompanyVoiceRoboticCalleesList(companyVoiceRoboticCallees);
-        ExcelUtil<CompanyVoiceRoboticCallees> util = new ExcelUtil<CompanyVoiceRoboticCallees>(CompanyVoiceRoboticCallees.class);
-        return util.exportExcel(list, "callees");
-    }
-
-    /**
-     * 获取任务外呼电话详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceRoboticCallees:query')")
-    @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") Long id)
-    {
-        return AjaxResult.success(companyVoiceRoboticCalleesService.selectCompanyVoiceRoboticCalleesById(id));
-    }
-
-    /**
-     * 新增任务外呼电话
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceRoboticCallees:add')")
-    @Log(title = "任务外呼电话", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyVoiceRoboticCallees companyVoiceRoboticCallees)
-    {
-        return toAjax(companyVoiceRoboticCalleesService.insertCompanyVoiceRoboticCallees(companyVoiceRoboticCallees));
-    }
-
-    /**
-     * 修改任务外呼电话
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceRoboticCallees:edit')")
-    @Log(title = "任务外呼电话", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyVoiceRoboticCallees companyVoiceRoboticCallees)
-    {
-        return toAjax(companyVoiceRoboticCalleesService.updateCompanyVoiceRoboticCallees(companyVoiceRoboticCallees));
-    }
-
-    /**
-     * 删除任务外呼电话
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceRoboticCallees:remove')")
-    @Log(title = "任务外呼电话", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{ids}")
-    public AjaxResult remove(@PathVariable Long[] ids)
-    {
-        return toAjax(companyVoiceRoboticCalleesService.deleteCompanyVoiceRoboticCalleesByIds(ids));
-    }
-}

+ 0 - 200
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceRoboticController.java

@@ -1,200 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.aicall.domain.TaskInfo;
-import com.fs.aicall.domain.apiresult.PushIIntentionResult;
-import com.fs.aicall.domain.result.EditDialogResult;
-import com.fs.aicall.domain.result.GetairobotResult;
-import com.fs.aicall.domain.result.QueryCallTaskInfoResult;
-import com.fs.aicall.service.AiCallService;
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.StringUtils;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyVoiceRobotic;
-import com.fs.company.domain.CompanyVoiceRoboticCallees;
-import com.fs.company.domain.CompanyVoiceRoboticWx;
-import com.fs.company.service.ICompanyVoiceRoboticCalleesService;
-import com.fs.company.service.ICompanyVoiceRoboticService;
-import com.fs.company.service.ICompanyVoiceRoboticWxService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * 机器人外呼任务Controller
- * 
- * @author fs
- * @date 2024-12-04
- */
-@RestController
-@RequestMapping("/company/companyVoiceRobotic")
-public class CompanyVoiceRoboticController extends BaseController
-{
-    @Autowired
-    private ICompanyVoiceRoboticService companyVoiceRoboticService;
-    @Autowired
-    private ICompanyVoiceRoboticCalleesService companyVoiceRoboticCalleesService;
-    @Autowired
-    private AiCallService aiCallService;
-    @Autowired
-    private ICompanyVoiceRoboticWxService companyVoiceRoboticWxService;
-
-    /**
-     * 查询机器人外呼任务列表
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceRobotic:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyVoiceRobotic companyVoiceRobotic){
-        startPage();
-        List<CompanyVoiceRobotic> list = companyVoiceRoboticService.selectCompanyVoiceRoboticList(companyVoiceRobotic);
-        return getDataTable(list);
-    }
-    /**
-     * 查询机器人外呼任务列表
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceRobotic:list')")
-    @GetMapping("/listAll")
-    public R listAll(CompanyVoiceRobotic companyVoiceRobotic){
-        return R.ok().put("data", companyVoiceRoboticService.selectCompanyVoiceRoboticList(companyVoiceRobotic));
-    }
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceRobotic:list')")
-    @GetMapping("/calleesList")
-    public TableDataInfo calleesList(Long id){
-        startPage();
-        List<CompanyVoiceRoboticCallees> list = companyVoiceRoboticCalleesService.selectCompanyVoiceRoboticCalleesListByRoboticId(id);
-        return getDataTable(list);
-    }
-
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceRobotic:list')")
-    @GetMapping("/wxList")
-    public TableDataInfo wxList(Long id){
-        startPage();
-        List<CompanyVoiceRoboticWx> list = companyVoiceRoboticWxService.selectWxList(id);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出机器人外呼任务列表
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceRobotic:export')")
-    @Log(title = "机器人外呼任务", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyVoiceRobotic companyVoiceRobotic)
-    {
-        List<CompanyVoiceRobotic> list = companyVoiceRoboticService.selectCompanyVoiceRoboticList(companyVoiceRobotic);
-        ExcelUtil<CompanyVoiceRobotic> util = new ExcelUtil<CompanyVoiceRobotic>(CompanyVoiceRobotic.class);
-        return util.exportExcel(list, "robotic");
-    }
-
-    /**
-     * 获取机器人外呼任务详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceRobotic:query')")
-    @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") Long id)
-    {
-        return AjaxResult.success(companyVoiceRoboticService.selectCompanyVoiceRoboticById(id));
-    }
-
-    /**
-     * 新增机器人外呼任务
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceRobotic:add')")
-    @Log(title = "机器人外呼任务", businessType = BusinessType.INSERT)
-    @PostMapping
-    @Transactional
-    public AjaxResult add(@RequestBody CompanyVoiceRobotic companyVoiceRobotic)
-    {
-        return toAjax(companyVoiceRoboticService.insertCompanyVoiceRobotic(companyVoiceRobotic));
-    }
-
-    /**
-     * 修改机器人外呼任务
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceRobotic:edit')")
-    @Log(title = "机器人外呼任务", businessType = BusinessType.UPDATE)
-    @PutMapping
-    @Transactional
-    public AjaxResult edit(@RequestBody CompanyVoiceRobotic companyVoiceRobotic)
-    {
-        return toAjax(companyVoiceRoboticService.updateCompanyVoiceRobotic(companyVoiceRobotic));
-    }
-
-    /**
-     * 删除机器人外呼任务
-     */
-    @PreAuthorize("@ss.hasPermi('system:companyVoiceRobotic:remove')")
-    @Log(title = "机器人外呼任务", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{ids}")
-    public AjaxResult remove(@PathVariable Long[] ids)
-    {
-        return toAjax(companyVoiceRoboticService.deleteCompanyVoiceRoboticByIds(ids));
-    }
-    /**
-     * 删除机器人外呼任务
-     */
-	@GetMapping("/getTypes")
-    public R getTypes(Long companyId){
-        List<GetairobotResult> getairobotlist = aiCallService.getairobotlist(companyId);
-        List<EditDialogResult> editDialogResults = aiCallService.queryDialog(companyId);
-        return R.ok().put("robot", getairobotlist).put("dialog", editDialogResults);
-    }
-    /**
-     * 查询状态
-     */
-    @GetMapping("/statusList")
-    public R statusList(String ids,Long companyId){
-        List<String> list = Arrays.stream(ids.split(",")).filter(StringUtils::isNotEmpty).collect(Collectors.toList());
-        return R.ok().put("data", list.stream().map(e -> aiCallService.queryCallTaskInfo(TaskInfo.builder().taskID(e).build(),companyId)).collect(Collectors.toMap(QueryCallTaskInfoResult::getTaskID, e -> e)));
-    }
-    /**
-     * 启动任务
-     */
-	@GetMapping("/startRobotic")
-    public R startRobotic(String taskId, Long companyId){
-        aiCallService.startCallTask(TaskInfo.builder().taskID(taskId).build(),companyId);
-        return R.ok();
-    }
-    /**
-     * 停止任务
-     */
-	@GetMapping("/stopRobotic")
-    public R stopRobotic(String taskId, Long companyId){
-        aiCallService.stopCallTask(TaskInfo.builder().taskID(taskId).build(),companyId);
-        return R.ok();
-    }
-    /**
-     * 员工列表
-     */
-	@GetMapping("/companyUserList")
-    public R qwUserList(){
-        return R.ok().put("data", companyVoiceRoboticService.qwUserList());
-    }
-
-    /**
-     * 外呼回调
-     */
-	@PostMapping("/callerResult")
-    public R callerResult(@RequestBody PushIIntentionResult result){
-        companyVoiceRoboticService.callerResult(result);
-        return R.ok();
-    }
-    /**
-     * 外呼回调
-     */
-	@GetMapping("/test")
-    public R test(Long id){
-//        companyVoiceRoboticService.test(id);
-        companyVoiceRoboticService.dispenseWx(id);
-        return R.ok();
-    }
-}

+ 0 - 97
fs-admin/src/main/java/com/fs/company/controller/CompanyVoiceRoboticWxController.java

@@ -1,97 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyVoiceRoboticWx;
-import com.fs.company.service.ICompanyVoiceRoboticWxService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * AI外呼任务加微方式Controller
- * 
- * @author fs
- * @date 2024-12-06
- */
-@RestController
-@RequestMapping("/company/VoiceRoboticWx")
-public class CompanyVoiceRoboticWxController extends BaseController
-{
-    @Autowired
-    private ICompanyVoiceRoboticWxService companyVoiceRoboticWxService;
-
-    /**
-     * 查询AI外呼任务加微方式列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:VoiceRoboticWx:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyVoiceRoboticWx companyVoiceRoboticWx)
-    {
-        startPage();
-        List<CompanyVoiceRoboticWx> list = companyVoiceRoboticWxService.selectCompanyVoiceRoboticWxList(companyVoiceRoboticWx);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出AI外呼任务加微方式列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:VoiceRoboticWx:export')")
-    @Log(title = "AI外呼任务加微方式", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyVoiceRoboticWx companyVoiceRoboticWx)
-    {
-        List<CompanyVoiceRoboticWx> list = companyVoiceRoboticWxService.selectCompanyVoiceRoboticWxList(companyVoiceRoboticWx);
-        ExcelUtil<CompanyVoiceRoboticWx> util = new ExcelUtil<CompanyVoiceRoboticWx>(CompanyVoiceRoboticWx.class);
-        return util.exportExcel(list, "VoiceRoboticWx");
-    }
-
-    /**
-     * 获取AI外呼任务加微方式详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:VoiceRoboticWx:query')")
-    @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") Long id)
-    {
-        return AjaxResult.success(companyVoiceRoboticWxService.selectCompanyVoiceRoboticWxById(id));
-    }
-
-    /**
-     * 新增AI外呼任务加微方式
-     */
-    @PreAuthorize("@ss.hasPermi('company:VoiceRoboticWx:add')")
-    @Log(title = "AI外呼任务加微方式", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyVoiceRoboticWx companyVoiceRoboticWx)
-    {
-        return toAjax(companyVoiceRoboticWxService.insertCompanyVoiceRoboticWx(companyVoiceRoboticWx));
-    }
-
-    /**
-     * 修改AI外呼任务加微方式
-     */
-    @PreAuthorize("@ss.hasPermi('company:VoiceRoboticWx:edit')")
-    @Log(title = "AI外呼任务加微方式", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyVoiceRoboticWx companyVoiceRoboticWx)
-    {
-        return toAjax(companyVoiceRoboticWxService.updateCompanyVoiceRoboticWx(companyVoiceRoboticWx));
-    }
-
-    /**
-     * 删除AI外呼任务加微方式
-     */
-    @PreAuthorize("@ss.hasPermi('company:VoiceRoboticWx:remove')")
-    @Log(title = "AI外呼任务加微方式", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{ids}")
-    public AjaxResult remove(@PathVariable Long[] ids)
-    {
-        return toAjax(companyVoiceRoboticWxService.deleteCompanyVoiceRoboticWxByIds(ids));
-    }
-}

+ 0 - 115
fs-admin/src/main/java/com/fs/company/controller/CompanyWxAccountController.java

@@ -1,115 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyWxAccount;
-import com.fs.company.service.ICompanyWxAccountService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 企微账号Controller
- * 
- * @author fs
- * @date 2024-12-09
- */
-@RestController
-@RequestMapping("/company/companyWx")
-public class CompanyWxAccountController extends BaseController
-{
-    @Autowired
-    private ICompanyWxAccountService companyWxEnterpriseAccountService;
-
-    /**
-     * 查询企微账号列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyWx:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyWxAccount companyWxAccount)
-    {
-        startPage();
-        List<CompanyWxAccount> list = companyWxEnterpriseAccountService.selectCompanyWxAccountList(companyWxAccount);
-        return getDataTable(list);
-    }
-    /**
-     * 查询企微账号列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyWx:list')")
-    @GetMapping("/listAll")
-    public R listAll(CompanyWxAccount companyWxAccount){
-        List<CompanyWxAccount> list = companyWxEnterpriseAccountService.selectCompanyWxAccountList(companyWxAccount);
-        return R.ok().put("data", list);
-    }
-
-    /**
-     * 导出企微账号列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyWx:export')")
-    @Log(title = "企微账号", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyWxAccount companyWxAccount)
-    {
-        List<CompanyWxAccount> list = companyWxEnterpriseAccountService.selectCompanyWxAccountList(companyWxAccount);
-        ExcelUtil<CompanyWxAccount> util = new ExcelUtil<CompanyWxAccount>(CompanyWxAccount.class);
-        return util.exportExcel(list, "companyWx");
-    }
-
-    /**
-     * 获取企微账号详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyWx:query')")
-    @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") Long id)
-    {
-        return AjaxResult.success(companyWxEnterpriseAccountService.selectCompanyWxAccountById(id));
-    }
-
-    /**
-     * 新增企微账号
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyWx:add')")
-    @Log(title = "企微账号", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyWxAccount companyWxAccount)
-    {
-        return toAjax(companyWxEnterpriseAccountService.insertCompanyWxAccount(companyWxAccount));
-    }
-
-    /**
-     * 修改企微账号
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyWx:edit')")
-    @Log(title = "企微账号", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyWxAccount companyWxAccount)
-    {
-        return toAjax(companyWxEnterpriseAccountService.updateCompanyWxAccount(companyWxAccount));
-    }
-
-    /**
-     * 删除企微账号
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyWx:remove')")
-    @Log(title = "企微账号", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{ids}")
-    public AjaxResult remove(@PathVariable Long[] ids)
-    {
-        return toAjax(companyWxEnterpriseAccountService.deleteCompanyWxAccountByIds(ids));
-    }
-    /**
-     * 删除企微账号
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyWx:list')")
-	@GetMapping("/companyListAll")
-    public R companyListAll(){
-        return R.ok().put("data", companyWxEnterpriseAccountService.companyListAll());
-    }
-}

+ 0 - 125
fs-admin/src/main/java/com/fs/company/controller/CompanyWxClientController.java

@@ -1,125 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyWxClient;
-import com.fs.company.service.ICompanyVoiceRoboticService;
-import com.fs.company.service.ICompanyWxClientService;
-import com.fs.company.vo.AddWxClientVo;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.*;
-
-import java.time.LocalDate;
-import java.util.List;
-
-/**
- * 添加个微信账号Controller
- * 
- * @author fs
- * @date 2024-12-09
- */
-@RestController
-@RequestMapping("/company/companyClient")
-public class CompanyWxClientController extends BaseController
-{
-    @Autowired
-    private ICompanyWxClientService companyWxClientService;
-    @Autowired
-    private ICompanyVoiceRoboticService companyVoiceRoboticService;
-
-    /**
-     * 查询添加个微信账号列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyClient:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyWxClient companyWxClient){
-        startPage();
-        List<CompanyWxClient> list = companyWxClientService.selectCompanyWxClientList(companyWxClient);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出添加个微信账号列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyClient:export')")
-    @Log(title = "添加个微信账号", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyWxClient companyWxClient)
-    {
-        List<CompanyWxClient> list = companyWxClientService.selectCompanyWxClientList(companyWxClient);
-        ExcelUtil<CompanyWxClient> util = new ExcelUtil<CompanyWxClient>(CompanyWxClient.class);
-        return util.exportExcel(list, "companyClient");
-    }
-
-    /**
-     * 获取添加个微信账号详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyClient:query')")
-    @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") Long id)
-    {
-        return AjaxResult.success(companyWxClientService.selectCompanyWxClientById(id));
-    }
-
-    /**
-     * 新增添加个微信账号
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyClient:add')")
-    @Log(title = "添加个微信账号", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyWxClient companyWxClient)
-    {
-        return toAjax(companyWxClientService.insertCompanyWxClient(companyWxClient));
-    }
-
-    /**
-     * 修改添加个微信账号
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyClient:edit')")
-    @Log(title = "添加个微信账号", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyWxClient companyWxClient)
-    {
-        return toAjax(companyWxClientService.updateCompanyWxClient(companyWxClient));
-    }
-
-    /**
-     * 删除添加个微信账号
-     */
-    @PreAuthorize("@ss.hasPermi('company:companyClient:remove')")
-    @Log(title = "添加个微信账号", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{ids}")
-    public AjaxResult remove(@PathVariable Long[] ids){
-        return toAjax(companyWxClientService.deleteCompanyWxClientByIds(ids));
-    }
-
-
-    @PostMapping("/addWxClient")
-    @Transactional
-    public R addWxClient(@RequestBody AddWxClientVo vo){
-        companyVoiceRoboticService.addCompany(vo);
-        return R.ok();
-    }
-    @GetMapping("/addWxStatistics")
-    @Transactional
-    public R addWxStatistics(CompanyWxClient companyWxClient){
-        List<CompanyWxClient> clients = companyWxClientService.selectCompanyWxClientList(companyWxClient);
-        LocalDate now = LocalDate.now();
-        return R.ok()
-                .put("totalNum", clients.size())
-                .put("toDayAddNum", clients.stream().filter(e -> e.getIsAdd() == 1 && e.getAddTime() != null && e.getAddTime().toLocalDate().equals(now)).count());
-    }
-
-    @GetMapping("/toDayAddWxAccountList")
-    @Transactional
-    public R toDayAddWxAccountList(Long companyId, Long accountId){
-        return R.ok().put("data", companyWxClientService.toDayAddWxAccountList(companyId, accountId, 0));
-    }
-}

+ 0 - 104
fs-admin/src/main/java/com/fs/company/controller/CompanyWxDialogController.java

@@ -1,104 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.company.domain.CompanyWxDialog;
-import com.fs.company.service.ICompanyWxDialogService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 添加微信话术Controller
- * 
- * @author fs
- * @date 2024-12-06
- */
-@RestController
-@RequestMapping("/company/wxDialog")
-public class CompanyWxDialogController extends BaseController
-{
-    @Autowired
-    private ICompanyWxDialogService companyWxDialogService;
-
-    /**
-     * 查询添加微信话术列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxDialog:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyWxDialog companyWxDialog)
-    {
-        startPage();
-        List<CompanyWxDialog> list = companyWxDialogService.selectCompanyWxDialogList(companyWxDialog);
-        return getDataTable(list);
-    }
-
-    @PreAuthorize("@ss.hasPermi('company:wxDialog:list')")
-    @GetMapping("/listAll")
-    public R listAll(CompanyWxDialog companyWxDialog){
-        return R.ok().put("data", companyWxDialogService.selectCompanyWxDialogList(companyWxDialog));
-    }
-
-    /**
-     * 导出添加微信话术列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxDialog:export')")
-    @Log(title = "添加微信话术", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyWxDialog companyWxDialog)
-    {
-        List<CompanyWxDialog> list = companyWxDialogService.selectCompanyWxDialogList(companyWxDialog);
-        ExcelUtil<CompanyWxDialog> util = new ExcelUtil<CompanyWxDialog>(CompanyWxDialog.class);
-        return util.exportExcel(list, "wxDialog");
-    }
-
-    /**
-     * 获取添加微信话术详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxDialog:query')")
-    @GetMapping(value = "/{id}")
-    public AjaxResult getInfo(@PathVariable("id") Long id)
-    {
-        return AjaxResult.success(companyWxDialogService.selectCompanyWxDialogById(id));
-    }
-
-    /**
-     * 新增添加微信话术
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxDialog:add')")
-    @Log(title = "添加微信话术", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyWxDialog companyWxDialog)
-    {
-        return toAjax(companyWxDialogService.insertCompanyWxDialog(companyWxDialog));
-    }
-
-    /**
-     * 修改添加微信话术
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxDialog:edit')")
-    @Log(title = "添加微信话术", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyWxDialog companyWxDialog)
-    {
-        return toAjax(companyWxDialogService.updateCompanyWxDialog(companyWxDialog));
-    }
-
-    /**
-     * 删除添加微信话术
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxDialog:remove')")
-    @Log(title = "添加微信话术", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{ids}")
-    public AjaxResult remove(@PathVariable Long[] ids)
-    {
-        return toAjax(companyWxDialogService.deleteCompanyWxDialogByIds(ids));
-    }
-}

+ 0 - 146
fs-admin/src/main/java/com/fs/company/controller/CompanyWxUserController.java

@@ -1,146 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.domain.R;
-import com.fs.common.core.domain.model.LoginUser;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.ServletUtils;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.framework.web.service.TokenService;
-import com.fs.qw.param.CompanyWxUserAddGroupParam;
-import com.fs.wxUser.domain.CompanyWxUser;
-import com.fs.wxUser.param.CompanyWxUserBindFsUserParam;
-import com.fs.wxUser.param.CompanyWxUserParam;
-import com.fs.wxUser.service.ICompanyWxUserService;
-import com.fs.wxUser.vo.CompanyWxUserVO;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 个微用户Controller
- * 
- * @author fs
- * @date 2024-10-22
- */
-@RestController
-@RequestMapping("/company/wxUser")
-public class CompanyWxUserController extends BaseController
-{
-    @Autowired
-    private ICompanyWxUserService companyWxUserService;
-
-    /**
-     * 查询个微用户列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxUser:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyWxUserParam param)
-    {
-        startPage();
-        List<CompanyWxUserVO> list = companyWxUserService.selectCompanyWxUserListVO(param);
-        return getDataTable(list);
-    }
-    @PreAuthorize("@ss.hasPermi('company:wxUser:list')")
-    @GetMapping("/listAll")
-    public R listAll(CompanyWxUserParam param)
-    {
-        return R.ok().put("data", companyWxUserService.selectCompanyWxUserListVO(param));
-    }
-
-    /**
-     * 导出个微用户列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxUser:export')")
-    @Log(title = "个微用户", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyWxUserParam param)
-    {
-        List<CompanyWxUserVO> list = companyWxUserService.selectCompanyWxUserListVO(param);
-        ExcelUtil<CompanyWxUserVO> util = new ExcelUtil<CompanyWxUserVO>(CompanyWxUserVO.class);
-        return util.exportExcel(list, "个微用户数据");
-    }
-
-    /**
-     * 获取个微用户详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxUser:query')")
-    @GetMapping(value = "/{userId}")
-    public AjaxResult getInfo(@PathVariable("userId") Long userId)
-    {
-        return AjaxResult.success(companyWxUserService.selectCompanyWxUserByUserId(userId));
-    }
-
-    /**
-     * 新增个微用户
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxUser:add')")
-    @Log(title = "个微用户", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyWxUser companyWxUser)
-    {
-        return toAjax(companyWxUserService.insertCompanyWxUser(companyWxUser));
-    }
-
-    /**
-     * 修改个微用户
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxUser:edit')")
-    @Log(title = "个微用户", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyWxUser companyWxUser)
-    {
-        return toAjax(companyWxUserService.updateCompanyWxUser(companyWxUser));
-    }
-
-    /**
-     * 删除个微用户
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxUser:remove')")
-    @Log(title = "个微用户", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{userIds}")
-    public AjaxResult remove(@PathVariable Long[] userIds)
-    {
-        return toAjax(companyWxUserService.deleteCompanyWxUserByUserIds(userIds));
-    }
-
-    /**
-    *  绑定小程序id
-    */
-    @PutMapping("/bindMiniUserId")
-    public R bindUserId(@RequestBody CompanyWxUserBindFsUserParam param)
-    {
-        return companyWxUserService.updateCompanyWxUserBindFsUser(param);
-    }
-
-    /**
-    * 批量添加分组
-    */
-
-    @PreAuthorize("@ss.hasPermi('company:wxUser:addGroup')")
-    @Log(title = "批量添加分组", businessType = BusinessType.INSERT)
-    @PostMapping("/addGroup")
-    public R addGroup(@RequestBody CompanyWxUserAddGroupParam param)
-    {
-
-        return companyWxUserService.addGroup(param);
-    }
-
-    /**
-    * 批量移除分组
-    */
-    @PreAuthorize("@ss.hasPermi('company:wxUser:delGroup')")
-    @Log(title = "批量移除分组", businessType = BusinessType.INSERT)
-    @PostMapping("/delGroup")
-    public R delGroup(@RequestBody CompanyWxUserAddGroupParam param)
-    {
-
-        return companyWxUserService.delGroup(param);
-    }
-
-}

+ 0 - 107
fs-admin/src/main/java/com/fs/company/controller/CompanyWxUserGroupController.java

@@ -1,107 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.core.page.TableDataInfo;
-import com.fs.common.enums.BusinessType;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.wxUser.domain.CompanyWxUserGroup;
-import com.fs.wxUser.service.ICompanyWxUserGroupService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 个微 分组Controller
- *
- * @author fs
- * @date 2024-10-25
- */
-@RestController
-@RequestMapping("/company/wxUserGroup")
-public class CompanyWxUserGroupController extends BaseController
-{
-    @Autowired
-    private ICompanyWxUserGroupService companyWxUserGroupService;
-    /**
-     * 查询个微 分组列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxUserGroup:list')")
-    @GetMapping("/list")
-    public TableDataInfo list(CompanyWxUserGroup companyWxUserGroup)
-    {
-        startPage();
-        List<CompanyWxUserGroup> list = companyWxUserGroupService.selectCompanyWxUserGroupList(companyWxUserGroup);
-        return getDataTable(list);
-    }
-
-    //查询个微分组-添加sop任务-个微-选择的分组(不要权限版)
-    @GetMapping("/sopList")
-    public TableDataInfo sopList(CompanyWxUserGroup companyWxUserGroup)
-    {
-        startPage();
-        List<CompanyWxUserGroup> list = companyWxUserGroupService.selectCompanyWxUserGroupList(companyWxUserGroup);
-        return getDataTable(list);
-    }
-
-    /**
-     * 导出个微 分组列表
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxUserGroup:export')")
-    @Log(title = "个微 分组", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(CompanyWxUserGroup companyWxUserGroup)
-    {
-        List<CompanyWxUserGroup> list = companyWxUserGroupService.selectCompanyWxUserGroupList(companyWxUserGroup);
-        ExcelUtil<CompanyWxUserGroup> util = new ExcelUtil<CompanyWxUserGroup>(CompanyWxUserGroup.class);
-        return util.exportExcel(list, "个微 分组数据");
-    }
-
-    /**
-     * 获取个微 分组详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxUserGroup:query')")
-    @GetMapping(value = "/{groupId}")
-    public AjaxResult getInfo(@PathVariable("groupId") Long groupId)
-    {
-        return AjaxResult.success(companyWxUserGroupService.selectCompanyWxUserGroupByGroupId(groupId));
-    }
-
-    /**
-     * 新增个微 分组
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxUserGroup:add')")
-    @Log(title = "个微 分组", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody CompanyWxUserGroup companyWxUserGroup)
-    {
-        return toAjax(companyWxUserGroupService.insertCompanyWxUserGroup(companyWxUserGroup));
-    }
-
-    /**
-     * 修改个微 分组
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxUserGroup:edit')")
-    @Log(title = "个微 分组", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody CompanyWxUserGroup companyWxUserGroup)
-    {
-        return toAjax(companyWxUserGroupService.updateCompanyWxUserGroup(companyWxUserGroup));
-    }
-
-    /**
-     * 删除个微 分组
-     */
-    @PreAuthorize("@ss.hasPermi('company:wxUserGroup:remove')")
-    @Log(title = "个微 分组", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{groupIds}")
-    public AjaxResult remove(@PathVariable Long[] groupIds)
-    {
-        return toAjax(companyWxUserGroupService.deleteCompanyWxUserGroupByGroupIds(groupIds));
-    }
-
-
-}

+ 0 - 145
fs-admin/src/main/java/com/fs/company/controller/ExternalApiConfigController.java

@@ -1,145 +0,0 @@
-package com.fs.company.controller;
-
-import cn.hutool.core.util.StrUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.model.LoginUser;
-import com.fs.common.result.Result;
-import com.fs.companyWorkflow.service.dto.ExternalApiCallLogPageReq;
-import com.fs.companyWorkflow.service.dto.ExternalApiConfigPageReq;
-import com.fs.companyWorkflow.service.dto.ExternalApiConfigSaveReq;
-import com.fs.companyWorkflow.service.dto.ExternalApiTestReq;
-import com.fs.companyWorkflow.domain.ExternalApiCallLog;
-import com.fs.companyWorkflow.domain.ExternalApiConfig;
-import com.fs.companyWorkflow.service.IExternalApiCallLogService;
-import com.fs.companyWorkflow.service.IExternalApiConfigService;
-import com.fs.companyWorkflow.service.dto.ExternalApiTestRequest;
-import com.fs.companyWorkflow.service.dto.ExternalApiTestResult;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.Date;
-
-/**
- * 外部接口管理配置
- */
-@RestController
-@RequestMapping("/companyWorkflow/externalApi")
-public class ExternalApiConfigController extends BaseController {
-
-    private final IExternalApiConfigService configService;
-    private final IExternalApiCallLogService logService;
-
-    public ExternalApiConfigController(IExternalApiConfigService configService, IExternalApiCallLogService logService) {
-        this.configService = configService;
-        this.logService = logService;
-    }
-
-    /**
-     * 列表分页
-     */
-    @GetMapping("/page")
-    public Result<IPage<ExternalApiConfig>> page(ExternalApiConfigPageReq req) {
-        Page<ExternalApiConfig> page = new Page<>(req.getPageNum(), req.getPageSize());
-        LambdaQueryWrapper<ExternalApiConfig> qw = new LambdaQueryWrapper<>();
-        qw.eq(req.getStatus() != null, ExternalApiConfig::getStatus, req.getStatus());
-        qw.like(StrUtil.isNotBlank(req.getApiType()), ExternalApiConfig::getApiType, req.getApiType());
-        qw.like(StrUtil.isNotBlank(req.getApiName()), ExternalApiConfig::getApiName, req.getApiName());
-        qw.like(StrUtil.isNotBlank(req.getApiCode()), ExternalApiConfig::getApiCode, req.getApiCode());
-        qw.orderByDesc(ExternalApiConfig::getPriority).orderByDesc(ExternalApiConfig::getCreateTime);
-        return Result.success(configService.page(page, qw));
-    }
-
-    /**
-     * 新增/编辑
-     */
-    @PostMapping("/saveOrUpdate")
-    public Result<Void> saveOrUpdate(@RequestBody ExternalApiConfigSaveReq req) {
-        LoginUser loginUser = getLoginUser();
-        ExternalApiConfig entity = new ExternalApiConfig();
-        entity.setId(req.getId());
-        entity.setApiType(req.getApiType());
-        entity.setApiName(req.getApiName());
-        entity.setApiCode(req.getApiCode());
-        entity.setApiUrl(req.getApiUrl());
-        entity.setHttpMethod(req.getHttpMethod());
-        entity.setRateWindowSeconds(req.getRateWindowSeconds());
-        entity.setRateMaxCount(req.getRateMaxCount());
-        entity.setPriority(req.getPriority());
-        entity.setStatus(req.getStatus());
-        entity.setDefaultHeadersJson(req.getDefaultHeadersJson());
-        entity.setDefaultBodyJson(req.getDefaultBodyJson());
-        entity.setTimeoutMs(req.getTimeoutMs());
-        boolean ok;
-        if (req.getId() != null){
-            entity.setUpdateTime(new Date());
-            entity.setUpdateBy(loginUser.getUserId().toString());
-            ok = configService.updateById(entity);
-        }else {
-            entity.setCreateTime(new Date());
-            entity.setCreateBy(loginUser.getUserId().toString());
-            ok = configService.save(entity);
-        }
-        return ok ? Result.success() : Result.error("保存失败");
-    }
-
-    @GetMapping("/{id}")
-    public Result<ExternalApiConfig> detail(@PathVariable Long id) {
-        return Result.success(configService.getById(id));
-    }
-
-    /**
-     * 启停
-     */
-    @PostMapping("/{id}/status")
-    public Result<Void> changeStatus(@PathVariable Long id, @RequestParam Integer status) {
-        ExternalApiConfig entity = new ExternalApiConfig();
-        entity.setId(id);
-        entity.setStatus(status);
-        boolean ok = configService.updateById(entity);
-        return ok ? Result.success() : Result.error("更新状态失败");
-    }
-
-    /**
-     * 删除(逻辑删)
-     */
-    @DeleteMapping("/{id}")
-    public Result<Void> delete(@PathVariable Long id) {
-        ExternalApiConfig entity = new ExternalApiConfig();
-        entity.setId(id);
-        entity.setIsDel(Integer.valueOf(1));
-        boolean ok = configService.updateById(entity);
-        return ok ? Result.success() : Result.error("删除失败");
-    }
-
-    /**
-     * 测试接口
-     */
-    @PostMapping("/{id}/test")
-    public Result<ExternalApiTestResult> test(@PathVariable Long id, @RequestBody(required = false) ExternalApiTestReq req) {
-        ExternalApiTestRequest r = new ExternalApiTestRequest();
-        if (req != null) {
-            r.setHeadersJson(req.getHeadersJson());
-            r.setBodyJson(req.getBodyJson());
-            r.setTimeoutMs(req.getTimeoutMs());
-        }
-        return Result.success(configService.testCall(id, r));
-    }
-
-    /**
-     * 调用日志分页
-     */
-    @GetMapping("/logs/page")
-    public Result<IPage<ExternalApiCallLog>> logs(ExternalApiCallLogPageReq req) {
-        if (req.getConfigId() == null) {
-            return Result.error("configId不能为空");
-        }
-        Page<ExternalApiCallLog> page = new Page<>(req.getPageNum(), req.getPageSize());
-        LambdaQueryWrapper<ExternalApiCallLog> qw = new LambdaQueryWrapper<>();
-        qw.eq(ExternalApiCallLog::getConfigId, req.getConfigId());
-        qw.orderByDesc(ExternalApiCallLog::getCreateTime);
-        return Result.success(logService.page(page, qw));
-    }
-}
-

+ 0 - 57
fs-admin/src/main/java/com/fs/company/controller/IndexController.java

@@ -1,57 +0,0 @@
-package com.fs.company.controller;
-
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.R;
-import com.fs.company.service.*;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * 企业Controller
- *
- * @author fs
- * @date 2021-10-04
- */
-@RestController
-@RequestMapping("/company/index")
-public class IndexController extends BaseController
-{
-    @Autowired
-    private ICompanyService companyService;
-//    @Autowired
-//    private ICompanyPackageOrderService packageOrderService;
-    @Autowired
-    private ICompanyRechargeService rechargeService;
-    @Autowired
-    private ICompanyVoiceLogsService voiceLogsService;
-    @Autowired
-    private ICompanyVoiceApiService voiceApiService;
-    @Autowired
-    private ICompanyVoiceMobileService mobileService;
-    /**
-     * 查询企业列表
-     */
-    @GetMapping("/getCount")
-    public R getCount()
-    {
-//        Integer companyCount=companyService.selectCompanyCount();
-//        BigDecimal rechargeMoney=rechargeService.selectCompanyRechargeMoney();
-//        BigDecimal packageOrderMoney=packageOrderService.selectCompanyPackageOrderMoney();
-//        Integer voiceLogsCount=voiceLogsService.selectCompanyVoiceLogsCount();
-//        Integer voiceApiCount=voiceApiService.selectCompanyVoiceApiCount();
-//        Integer mobileCount=mobileService.selectCompanyVoiceMobileCount();
-//        Map<String,Object> map=new HashMap<>();
-//        map.put("companyCount",companyCount);
-//        map.put("rechargeMoney",rechargeMoney);
-//        map.put("packageOrderMoney",packageOrderMoney);
-//        map.put("voiceLogsCount",voiceLogsCount);
-//        map.put("voiceApiCount",voiceApiCount);
-//        map.put("mobileCount",mobileCount);
-
-
-//        return R.ok().put("data",map);
-        return R.ok();
-    }
-}

+ 0 - 148
fs-admin/src/main/java/com/fs/course/controller/FsCourseWatchCommentController.java

@@ -1,148 +0,0 @@
-package com.fs.course.controller;
-
-import java.util.List;
-
-import com.fs.common.core.domain.R;
-import com.fs.course.param.FsCourseWatchCommentPageParam;
-import com.fs.course.vo.FsCourseWatchCommentListVO;
-import com.fs.qw.service.IQwExternalContactService;
-import com.github.pagehelper.PageHelper;
-import com.github.pagehelper.PageInfo;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import com.fs.common.annotation.Log;
-import com.fs.common.core.controller.BaseController;
-import com.fs.common.core.domain.AjaxResult;
-import com.fs.common.enums.BusinessType;
-import com.fs.course.domain.FsCourseWatchComment;
-import com.fs.course.service.IFsCourseWatchCommentService;
-import com.fs.common.utils.poi.ExcelUtil;
-import com.fs.common.core.page.TableDataInfo;
-
-/**
- * 看课评论Controller
- *
- * @author fs
- * @date 2025-05-26
- */
-@RestController
-@RequestMapping("/course/courseWatchComment")
-public class FsCourseWatchCommentController extends BaseController
-{
-    @Autowired
-    private IFsCourseWatchCommentService fsCourseWatchCommentService;
-
-    @Autowired
-    private IQwExternalContactService qwExternalContactService;
-
-    /**
-     * 查询看课评论列表
-     */
-    @PreAuthorize("@ss.hasPermi('course:courseWatchComment:list')")
-    @GetMapping("/list")
-    public R list(FsCourseWatchCommentPageParam fsCourseWatchCommentPageParam)
-    {
-//        startPage();
-        PageHelper.startPage(fsCourseWatchCommentPageParam.getPageNum(), fsCourseWatchCommentPageParam.getPageSize());
-        List<FsCourseWatchCommentListVO> list = fsCourseWatchCommentService.selectFsCourseWatchCommentList(fsCourseWatchCommentPageParam);
-        PageInfo<FsCourseWatchCommentListVO> pageInfo = new PageInfo<>(list);
-        return R.ok().put("rows", pageInfo);
-    }
-
-    /**
-     * 导出看课评论列表
-     */
-    @PreAuthorize("@ss.hasPermi('course:courseWatchComment:export')")
-    @Log(title = "看课评论", businessType = BusinessType.EXPORT)
-    @GetMapping("/export")
-    public AjaxResult export(FsCourseWatchCommentPageParam fsCourseWatchCommentPageParam)
-    {
-        List<FsCourseWatchCommentListVO> list = fsCourseWatchCommentService.selectFsCourseWatchCommentList(fsCourseWatchCommentPageParam);
-        ExcelUtil<FsCourseWatchCommentListVO> util = new ExcelUtil<FsCourseWatchCommentListVO>(FsCourseWatchCommentListVO.class);
-        return util.exportExcel(list, "看课评论数据");
-    }
-
-    @PreAuthorize("@ss.hasPermi('course:courseWatchComment:edit')")
-    @Log(title = "看课评论", businessType = BusinessType.UPDATE)
-    @PutMapping("/updateBarrageStatus")
-    public AjaxResult updateBarrageStatus(@RequestBody FsCourseWatchComment fsCourseWatchComment)
-    {
-        return toAjax(fsCourseWatchCommentService.updateFsCourseWatchComment(fsCourseWatchComment));
-    }
-
-    /**
-     * 获取看课评论详细信息
-     */
-    @PreAuthorize("@ss.hasPermi('course:courseWatchComment:query')")
-    @GetMapping(value = "/{commentId}")
-    public AjaxResult getInfo(@PathVariable("commentId") Long commentId)
-    {
-        return AjaxResult.success(fsCourseWatchCommentService.selectFsCourseWatchCommentByCommentId(commentId));
-    }
-
-    /**
-     * 新增看课评论
-     */
-    @PreAuthorize("@ss.hasPermi('course:courseWatchComment:add')")
-    @Log(title = "看课评论", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody FsCourseWatchComment fsCourseWatchComment)
-    {
-        return toAjax(fsCourseWatchCommentService.insertFsCourseWatchComment(fsCourseWatchComment));
-    }
-
-    /**
-     * 修改看课评论
-     */
-    @PreAuthorize("@ss.hasPermi('course:courseWatchComment:edit')")
-    @Log(title = "看课评论", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody FsCourseWatchComment fsCourseWatchComment)
-    {
-        return toAjax(fsCourseWatchCommentService.updateFsCourseWatchComment(fsCourseWatchComment));
-    }
-
-    /**
-     * 删除看课评论
-     */
-    @PreAuthorize("@ss.hasPermi('course:courseWatchComment:remove')")
-    @Log(title = "看课评论", businessType = BusinessType.DELETE)
-	@DeleteMapping("/{commentIds}")
-    public AjaxResult remove(@PathVariable Long[] commentIds)
-    {
-        return toAjax(fsCourseWatchCommentService.deleteFsCourseWatchCommentByCommentIds(commentIds));
-    }
-
-    @Log(title = "手动拉黑外部联系人用户", businessType = BusinessType.UPDATE)
-    @PutMapping("/addBlack")
-    public R addBlack(Integer commentStatus, Long fsUserId)
-    {
-        int i = qwExternalContactService.updateQwExternalContactByFsUserId(commentStatus, fsUserId);
-        if (i > 0){
-            return R.ok();
-        } else {
-            return R.error();
-        }
-    }
-
-    @Log(title = "手动解除外部联系人拉黑用户", businessType = BusinessType.UPDATE)
-    @PutMapping("/clearBlack")
-    public R clearBlack(Integer commentStatus, Long fsUserId)
-    {
-        int i = qwExternalContactService.updateQwExternalContactByFsUserId(commentStatus, fsUserId);
-        if (i > 0){
-            return R.ok();
-        } else {
-            return R.error();
-        }
-    }
-
-}

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini