zx 2 недель назад
Родитель
Сommit
5ead074ee2

+ 2 - 1
fs-admin/src/main/java/com/fs/FSApplication.java

@@ -22,7 +22,8 @@ import org.springframework.transaction.annotation.Transactional;
             "com\\.fs\\.framework\\.service\\.PermissionService",
             "com\\.fs\\.framework\\.service\\.UserDetailsServiceImpl",
             "com\\.fs\\.company\\.controller\\..*",
-            "com\\.fs\\.hisStore\\.controller\\..*"
+            "com\\.fs\\.hisStore\\.controller\\..*",
+            "com\\.fs\\.his\\.controller\\.FsAiWorkflowController"
         })
     }
 )

+ 273 - 0
fs-admin/src/main/java/com/fs/admin/controller/AdminAiWorkflowBridgeController.java

@@ -0,0 +1,273 @@
+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.common.enums.DataSourceType;
+import com.fs.framework.datasource.DynamicDataSourceContextHolder;
+import com.fs.framework.datasource.TenantDataSourceManager;
+import com.fs.his.domain.FsAiWorkflow;
+import com.fs.his.domain.FsAiWorkflowNodeType;
+import com.fs.his.param.FsAiWorkflowSaveParam;
+import com.fs.his.param.FsAiWorkflowUpdateBindWCParam;
+import com.fs.his.service.IFsAiWorkflowService;
+import com.fs.tenant.domain.TenantInfo;
+import com.fs.tenant.mapper.TenantInfoMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * AI工作流桥接Controller - adminui端(fs-admin 8004)
+ * 替代 com.fs.his.controller.FsAiWorkflowController(已从admin扫描中排除)
+ * <p>
+ * AI工作流数据存储在租户库中,admin端需根据请求中的租户上下文切换数据源后查询。
+ * 请求头需携带 tenant-code 或 tenant-id 来指定目标租户。
+ *
+ * @author fs
+ * @date 2026-05-12
+ */
+@RestController
+@RequestMapping("/his/aiWorkflow")
+public class AdminAiWorkflowBridgeController extends BaseController {
+
+    private static final Logger log = LoggerFactory.getLogger(AdminAiWorkflowBridgeController.class);
+
+    @Autowired(required = false)
+    private IFsAiWorkflowService fsAiWorkflowService;
+
+    @Autowired(required = false)
+    private TenantDataSourceManager tenantDataSourceManager;
+
+    @Autowired(required = false)
+    private TenantInfoMapper tenantInfoMapper;
+
+    @Autowired
+    private HttpServletRequest request;
+
+    /**
+     * 尝试切换到租户数据源
+     * @return true=切换成功,false=无租户上下文或切换失败
+     */
+    private boolean trySwitchToTenant() {
+        if (tenantDataSourceManager == null || tenantInfoMapper == null) {
+            log.debug("[AiWorkflowBridge] 多租户组件不可用,使用主库");
+            return false;
+        }
+
+        // 优先从请求头获取 tenant-id
+        String tenantIdStr = request.getHeader("tenant-id");
+        if (tenantIdStr == null || tenantIdStr.isEmpty()) {
+            // 尝试 tenant-code
+            String tenantCode = request.getHeader("tenant-code");
+            if (tenantCode != null && !tenantCode.isEmpty()) {
+                DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
+                try {
+                    TenantInfo info = tenantInfoMapper.getTenByCode(tenantCode);
+                    if (info != null) {
+                        tenantDataSourceManager.switchTenant(info);
+                        log.debug("[AiWorkflowBridge] 通过 tenant-code={} 切换到租户: {}", tenantCode, info.getId());
+                        return true;
+                    }
+                } finally {
+                    // 如果没找到,已经切到MASTER,需要回切?
+                }
+            }
+            // 尝试查询参数 tenantId
+            tenantIdStr = request.getParameter("tenantId");
+        }
+
+        if (tenantIdStr != null && !tenantIdStr.isEmpty()) {
+            try {
+                Long tenantId = Long.parseLong(tenantIdStr);
+                tenantDataSourceManager.ensureSwitchByTenantId(tenantId);
+                log.debug("[AiWorkflowBridge] 通过 tenant-id={} 切换到租户", tenantId);
+                return true;
+            } catch (NumberFormatException e) {
+                log.warn("[AiWorkflowBridge] tenantId格式错误: {}", tenantIdStr);
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * 清理数据源上下文
+     */
+    private void clearDataSource() {
+        if (tenantDataSourceManager != null) {
+            tenantDataSourceManager.clear();
+        }
+    }
+
+    /**
+     * 查询AI工作流列表
+     */
+    @GetMapping("/list")
+    public TableDataInfo list(FsAiWorkflow fsAiWorkflow) {
+        if (fsAiWorkflowService == null || !trySwitchToTenant()) {
+            return getDataTable(new ArrayList<>());
+        }
+        try {
+            startPage();
+            List<FsAiWorkflow> list = fsAiWorkflowService.selectFsAiWorkflowList(fsAiWorkflow);
+            return getDataTable(list);
+        } finally {
+            clearDataSource();
+        }
+    }
+
+    /**
+     * 导出AI工作流列表
+     */
+    @GetMapping("/export")
+    public AjaxResult export(FsAiWorkflow fsAiWorkflow) {
+        if (fsAiWorkflowService == null || !trySwitchToTenant()) {
+            return AjaxResult.error("请先选择租户");
+        }
+        try {
+            List<FsAiWorkflow> list = fsAiWorkflowService.selectFsAiWorkflowList(fsAiWorkflow);
+            // 导出功能在admin端简化为返回数据
+            return AjaxResult.success(list);
+        } finally {
+            clearDataSource();
+        }
+    }
+
+    /**
+     * 获取AI工作流详细信息(包含节点和连线)
+     */
+    @GetMapping(value = "/{workflowId}")
+    public AjaxResult getInfo(@PathVariable("workflowId") Long workflowId) {
+        if (fsAiWorkflowService == null || !trySwitchToTenant()) {
+            return AjaxResult.error("请先选择租户");
+        }
+        try {
+            return AjaxResult.success(fsAiWorkflowService.selectFsAiWorkflowById(workflowId));
+        } finally {
+            clearDataSource();
+        }
+    }
+
+    /**
+     * 保存AI工作流(新增或更新) - admin端不支持直接写入
+     */
+    @PostMapping("/save")
+    public AjaxResult save(@RequestBody FsAiWorkflowSaveParam param) {
+        return AjaxResult.error("总后台不支持直接操作租户工作流,请在租户端操作");
+    }
+
+    /**
+     * 修改AI工作流状态 - admin端不支持直接写入
+     */
+    @PutMapping("/status/{workflowId}/{status}")
+    public AjaxResult updateStatus(@PathVariable("workflowId") Long workflowId,
+                                   @PathVariable("status") Integer status) {
+        return AjaxResult.error("总后台不支持直接操作租户工作流,请在租户端操作");
+    }
+
+    /**
+     * 删除AI工作流 - admin端不支持直接写入
+     */
+    @DeleteMapping("/{workflowIds}")
+    public AjaxResult remove(@PathVariable Long[] workflowIds) {
+        return AjaxResult.error("总后台不支持直接操作租户工作流,请在租户端操作");
+    }
+
+    /**
+     * 复制AI工作流 - admin端不支持直接写入
+     */
+    @PostMapping("/copy/{workflowId}")
+    public AjaxResult copy(@PathVariable("workflowId") Long workflowId) {
+        return AjaxResult.error("总后台不支持直接操作租户工作流,请在租户端操作");
+    }
+
+    /**
+     * 获取所有启用的节点类型
+     */
+    @GetMapping("/nodeTypes")
+    public AjaxResult getNodeTypes() {
+        if (fsAiWorkflowService == null || !trySwitchToTenant()) {
+            return AjaxResult.success(new ArrayList<>());
+        }
+        try {
+            List<FsAiWorkflowNodeType> list = fsAiWorkflowService.selectAllEnabledNodeTypes();
+            return AjaxResult.success(list);
+        } finally {
+            clearDataSource();
+        }
+    }
+
+    /**
+     * 导出工作流流程图JSON
+     */
+    @GetMapping("/exportJson/{workflowId}")
+    public AjaxResult exportJson(@PathVariable("workflowId") Long workflowId) {
+        if (fsAiWorkflowService == null || !trySwitchToTenant()) {
+            return AjaxResult.error("请先选择租户");
+        }
+        try {
+            return AjaxResult.success(fsAiWorkflowService.exportWorkflowJson(workflowId));
+        } finally {
+            clearDataSource();
+        }
+    }
+
+    /**
+     * 分页销售
+     */
+    @GetMapping("/listCompanyUser")
+    public AjaxResult listCompanyUser() {
+        if (fsAiWorkflowService == null || !trySwitchToTenant()) {
+            return AjaxResult.success(new ArrayList<>());
+        }
+        try {
+            return AjaxResult.success(fsAiWorkflowService.listCompanyUser());
+        } finally {
+            clearDataSource();
+        }
+    }
+
+    /**
+     * 查销售
+     */
+    @GetMapping("/getCompanyUserById/{companyUserId}")
+    public AjaxResult getCompanyUserById(@PathVariable("companyUserId") Long companyUserId) {
+        if (fsAiWorkflowService == null || !trySwitchToTenant()) {
+            return AjaxResult.error("请先选择租户");
+        }
+        try {
+            return AjaxResult.success(fsAiWorkflowService.getCompanyUserById(companyUserId));
+        } finally {
+            clearDataSource();
+        }
+    }
+
+    /**
+     * 查工作流已绑定的销售
+     */
+    @GetMapping("/getBindCompanyUserByWorkflowId/{workflowId}")
+    public AjaxResult getBindCompanyUserByWorkflowId(@PathVariable("workflowId") Long workflowId) {
+        if (fsAiWorkflowService == null || !trySwitchToTenant()) {
+            return AjaxResult.error("请先选择租户");
+        }
+        try {
+            return AjaxResult.success(fsAiWorkflowService.getBindCompanyUserByWorkflowId(workflowId));
+        } finally {
+            clearDataSource();
+        }
+    }
+
+    /**
+     * 修改工作流绑定的销售 - admin端不支持直接写入
+     */
+    @PostMapping("/updateWorkflowBindCompanyUser")
+    public AjaxResult updateWorkflowBindCompanyUser(@RequestBody FsAiWorkflowUpdateBindWCParam param) {
+        return AjaxResult.error("总后台不支持直接操作租户工作流,请在租户端操作");
+    }
+}

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

@@ -38,6 +38,17 @@ public class AdminModuleUsageController extends BaseController {
         return getDataTable(list);
     }
 
+    /**
+     * 查询租户模块使用统计汇总列表(每个租户一行,不按天展示)
+     */
+    @PreAuthorize("@ss.hasPermi('admin:moduleUsage:list')")
+    @GetMapping("/summary")
+    public TableDataInfo summary(TenantModuleUsage query) {
+        startPage();
+        List<TenantModuleUsage> list = tenantModuleUsageService.selectTenantModuleUsageSummary(query);
+        return getDataTable(list);
+    }
+
     /**
      * 按代理维度查看模块使用详情
      * 返回:指定代理下所有租户的模块使用情况

+ 32 - 22
fs-service/src/main/java/com/fs/company/service/impl/CompanyWorkflowLobsterServiceImpl.java

@@ -89,32 +89,42 @@ public class CompanyWorkflowLobsterServiceImpl implements ICompanyWorkflowLobste
         record.setUpdateBy(userName);
         record.setUpdateTime(DateUtils.getNowDate());
         record.setDelFlag(0);
-        String requestStr = "{ \"userContent\": \""+param.getRequirement()+"\", \"aiContent\": null }";
-        R r = callAiService(requestStr, l, LOBSTER_KEY);
-        log.info("流程图生成成功: {}", param.getRequirement());
-//        System.out.println(r);
-        record.setResultJson(buildResultJsonFromAi(r, param.getRequirement()));
+        // 安全构建JSON,避免requirement中的特殊字符破坏JSON格式
+        JSONObject requestJson = new JSONObject();
+        requestJson.set("userContent", param.getRequirement());
+        requestJson.set("aiContent", (Object) null);
+        String requestStr = requestJson.toString();
+        try {
+            R r = callAiService(requestStr, l, LOBSTER_KEY);
+            log.info("流程图生成成功: {}", param.getRequirement());
+            record.setResultJson(buildResultJsonFromAi(r, param.getRequirement()));
+        } catch (Exception e) {
+            log.error("AI服务调用失败,使用默认模板: {}", e.getMessage(), e);
+            record.setStatus(2); // 标记为失败状态
+            record.setErrorMsg("AI服务调用失败: " + e.getMessage());
+            record.setResultJson(buildDefaultResultJson(param.getRequirement()));
+        }
         recordMapper.insertRecord(record);
         return recordNo;
     }
-    public static R callAiService(String requestParam, Long logId, String appKey) {
-        try {
-            ChatParam param = new ChatParam();
-            param.setChatId(logId.toString());
-            param.setStream(false);
-            param.setDetail(true);
-            ChatParam.Message message = new ChatParam.Message();
-            List<ChatParam.Message> messageList = new ArrayList<ChatParam.Message>();
-            message.setContent(requestParam);
-            message.setRole("user");
-            messageList.add(message);
-            param.setMessages(messageList);
-            ChatService chatService = SpringUtils.getBean(ChatService.class);
-
-            return chatService.initiatingTakeChat(param, AI_API, appKey);
-        } catch (Exception e) {
-            throw new RuntimeException("AI服务调用失败", e);
+    public R callAiService(String requestParam, Long logId, String appKey) {
+        ChatParam param = new ChatParam();
+        param.setChatId(logId.toString());
+        param.setStream(false);
+        param.setDetail(true);
+        ChatParam.Message message = new ChatParam.Message();
+        List<ChatParam.Message> messageList = new ArrayList<ChatParam.Message>();
+        message.setContent(requestParam);
+        message.setRole("user");
+        messageList.add(message);
+        param.setMessages(messageList);
+        ChatService chatService = SpringUtils.getBean(ChatService.class);
+
+        R result = chatService.initiatingTakeChat(param, AI_API, appKey);
+        if (result == null) {
+            throw new RuntimeException("AI服务返回为空");
         }
+        return result;
     }
 
     @Override

+ 9 - 0
fs-service/src/main/java/com/fs/fastgptApi/service/Impl/ChatServiceImpl.java

@@ -12,6 +12,8 @@ import com.fs.fastgptApi.result.ChatDetailTStreamFResult;
 import com.fs.fastgptApi.result.KnowledgeBaseResult;
 import com.fs.fastgptApi.service.ChatService;
 import com.fs.fastgptApi.util.HttpUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
 
@@ -24,6 +26,8 @@ import java.util.stream.Collectors;
 @Service
 public class ChatServiceImpl implements ChatService {
 
+    private static final Logger log = LoggerFactory.getLogger(ChatServiceImpl.class);
+
 
     /**
      * 发起对话
@@ -33,6 +37,11 @@ public class ChatServiceImpl implements ChatService {
 
         String json = HttpUtil.sendPost(param, url+FastGptApiConfig.completionsUrl, appKey);
 
+        if (json == null || json.trim().isEmpty()) {
+            log.error("AI服务响应为空,url={}", url);
+            return R.error("AI服务响应异常,请稍后重试");
+        }
+
         JSONObject jsonObject = JSON.parseObject(json);
 
         // 判断是否有回应消息

+ 16 - 4
fs-service/src/main/java/com/fs/fastgptApi/util/HttpUtil.java

@@ -13,6 +13,7 @@ import org.apache.hc.core5.net.URIBuilder;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
 import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.RequestConfig;
 import org.apache.http.client.methods.*;
 import org.apache.http.entity.ContentType;
 import org.apache.http.entity.StringEntity;
@@ -20,6 +21,8 @@ import org.apache.http.entity.mime.MultipartEntityBuilder;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.File;
 import java.io.IOException;
@@ -32,6 +35,8 @@ import java.util.Objects;
 
 public class HttpUtil {
 
+    private static final Logger log = LoggerFactory.getLogger(HttpUtil.class);
+
 
     public static String sendAuthPost(Object param, String url) {
         // 使用 CloseableHttpClient
@@ -60,8 +65,15 @@ public class HttpUtil {
     }
 
     public static String sendPost(Object param, String url, String key) {
-        // 使用 CloseableHttpClient
-        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+        // 使用 CloseableHttpClient,设置超时
+        RequestConfig requestConfig = RequestConfig.custom()
+                .setConnectTimeout(30000)       // 连接超时30秒
+                .setSocketTimeout(120000)       // 读取超时120秒(AI响应可能较慢)
+                .setConnectionRequestTimeout(30000)
+                .build();
+        try (CloseableHttpClient httpClient = HttpClients.custom()
+                .setDefaultRequestConfig(requestConfig)
+                .build()) {
             URIBuilder builder = new URIBuilder(url);
             URI uri = builder.build();
 
@@ -76,12 +88,12 @@ public class HttpUtil {
 
             // 执行请求
             try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
-                    // 请求成功,返回响应内容
+                // 请求成功,返回响应内容
                 String string = EntityUtils.toString(response.getEntity());
                 return string;
             }
         } catch (Exception e) {
-            e.printStackTrace();
+            log.error("AI服务HTTP请求失败, url={}: {}", url, e.getMessage(), e);
         }
         return null;
     }

+ 5 - 0
fs-service/src/main/java/com/fs/proxy/mapper/TenantModuleUsageMapper.java

@@ -57,4 +57,9 @@ public interface TenantModuleUsageMapper {
      * 活跃租户定义:company表中status=0且is_del=0
      */
     List<Long> selectActiveTenantIds();
+
+    /**
+     * 按租户汇总查询:每个租户取最新一条统计记录(不按天展示)
+     */
+    List<TenantModuleUsage> selectTenantModuleUsageSummary(TenantModuleUsage query);
 }

+ 5 - 0
fs-service/src/main/java/com/fs/proxy/service/TenantModuleUsageService.java

@@ -50,4 +50,9 @@ public interface TenantModuleUsageService {
      * 返回:按代理分组的各模块使用情况
      */
     Map<String, Object> getModuleUsageDetail(Long proxyId, String statDate);
+
+    /**
+     * 按租户汇总查询:每个租户取最新一条统计记录(不按天展示)
+     */
+    List<TenantModuleUsage> selectTenantModuleUsageSummary(TenantModuleUsage query);
 }

+ 5 - 0
fs-service/src/main/java/com/fs/proxy/service/impl/TenantModuleUsageServiceImpl.java

@@ -42,6 +42,11 @@ public class TenantModuleUsageServiceImpl implements TenantModuleUsageService {
         return usageMapper.selectTenantModuleUsageList(query);
     }
 
+    @Override
+    public List<TenantModuleUsage> selectTenantModuleUsageSummary(TenantModuleUsage query) {
+        return usageMapper.selectTenantModuleUsageSummary(query);
+    }
+
     @Override
     public TenantModuleUsage selectLatestByTenantId(Long tenantId) {
         TenantModuleUsage query = new TenantModuleUsage();

+ 12 - 0
fs-service/src/main/resources/mapper/proxy/TenantModuleUsageMapper.xml

@@ -165,4 +165,16 @@
         select company_id from company where status = 0 and (is_del = 0 or is_del is null)
     </select>
 
+    <!-- 按租户汇总:每个租户取最新一条统计记录(不按天展示) -->
+    <select id="selectTenantModuleUsageSummary" resultMap="TenantModuleUsageResult">
+        <include refid="selectVo"/>
+        WHERE u.stat_date = (
+            SELECT MAX(u2.stat_date) FROM tenant_module_usage u2 WHERE u2.tenant_id = u.tenant_id
+        )
+        <if test="tenantName != null and tenantName != ''">and u.tenant_name like concat('%', #{tenantName}, '%')</if>
+        <if test="proxyId != null">and u.proxy_id = #{proxyId}</if>
+        <if test="queryProxyId != null">and u.proxy_id = #{queryProxyId}</if>
+        ORDER BY u.tenant_id ASC
+    </select>
+
 </mapper>

+ 20 - 20
fs-service/src/main/resources/mapper/system/AdminMenuMapper.xml

@@ -26,47 +26,47 @@
 
     <select id="selectMenuTreeAll" resultMap="AdminMenuResult">
         select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
-        from sys_menu m where m.menu_type in ('M', 'C') and m.status = 0 and m.visible = '0'
+        from fs_menu m where m.menu_type in ('M', 'C') and m.status = '0' and m.visible = '0'
         order by m.parent_id, m.order_num
     </select>
 
     <select id="selectMenuTreeByUserId" resultMap="AdminMenuResult">
         select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
-        from sys_menu m
-             left join sys_role_menu rm on m.menu_id = rm.menu_id
+        from fs_menu m
+             left join fs_role_menu rm on m.menu_id = rm.menu_id
              left join sys_user_role ur on rm.role_id = ur.role_id
              left join sys_role ro on ur.role_id = ro.role_id
-        where m.menu_type in ('M', 'C') and m.status = 0
-              and ro.status = 0
+        where m.menu_type in ('M', 'C') and m.status = '0'
+              and ro.status = '0'
               and ur.user_id = #{userId}
         order by m.parent_id, m.order_num
     </select>
 
     <select id="selectMenuListByUserId" resultMap="AdminMenuResult">
         select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
-        from sys_menu m
-             left join sys_role_menu rm on m.menu_id = rm.menu_id
+        from fs_menu m
+             left join fs_role_menu rm on m.menu_id = rm.menu_id
              left join sys_user_role ur on rm.role_id = ur.role_id
              left join sys_role ro on ur.role_id = ro.role_id
-        where ur.user_id = #{userId} and m.menu_type in ('M', 'C') and m.status = 0
-              and ro.status = 0
+        where ur.user_id = #{userId} and m.menu_type in ('M', 'C') and m.status = '0'
+              and ro.status = '0'
         order by m.parent_id, m.order_num
     </select>
 
     <select id="selectMenuPermsByUserId" resultType="String">
         select distinct m.perms
-        from sys_menu m
-             left join sys_role_menu rm on m.menu_id = rm.menu_id
+        from fs_menu m
+             left join fs_role_menu rm on m.menu_id = rm.menu_id
              left join sys_user_role ur on rm.role_id = ur.role_id
              left join sys_role ro on ur.role_id = ro.role_id
-        where ur.user_id = #{userId} and m.status = 0 and ro.status = 0
+        where ur.user_id = #{userId} and m.status = '0' and ro.status = '0'
     </select>
 
     <sql id="selectMenuVo">
         select m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.query, m.visible, m.status,
                ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num,
                m.create_by, m.create_time, m.update_by, m.update_time, m.remark
-        from sys_menu m
+        from fs_menu m
     </sql>
 
     <select id="selectMenuList" parameterType="com.fs.common.core.domain.entity.AdminMenu" resultMap="AdminMenuResult">
@@ -92,8 +92,8 @@
 
     <select id="selectMenuListByRoleId" resultType="Long">
         select m.menu_id
-        from sys_menu m
-             left join sys_role_menu rm on m.menu_id = rm.menu_id
+        from fs_menu m
+             left join fs_role_menu rm on m.menu_id = rm.menu_id
         where rm.role_id = #{roleId}
         order by m.parent_id, m.order_num
     </select>
@@ -104,7 +104,7 @@
     </select>
 
     <insert id="insertMenu" parameterType="com.fs.common.core.domain.entity.AdminMenu" useGeneratedKeys="true" keyProperty="menuId">
-        insert into sys_menu (
+        insert into fs_menu (
             <if test="menuName != null and menuName != ''">menu_name,</if>
             <if test="parentId != null">parent_id,</if>
             <if test="orderNum != null">order_num,</if>
@@ -142,7 +142,7 @@
     </insert>
 
     <update id="updateMenu" parameterType="com.fs.common.core.domain.entity.AdminMenu">
-        update sys_menu
+        update fs_menu
         <set>
             <if test="menuName != null and menuName != ''">menu_name = #{menuName},</if>
             <if test="parentId != null">parent_id = #{parentId},</if>
@@ -165,15 +165,15 @@
     </update>
 
     <delete id="deleteMenuById" parameterType="Long">
-        delete from sys_menu where menu_id = #{menuId}
+        delete from fs_menu where menu_id = #{menuId}
     </delete>
 
     <select id="hasChildByMenuId" parameterType="Long" resultType="int">
-        select count(1) from sys_menu where parent_id = #{menuId}
+        select count(1) from fs_menu where parent_id = #{menuId}
     </select>
 
     <select id="checkMenuExistRole" parameterType="Long" resultType="int">
-        select count(1) from sys_role_menu where menu_id = #{menuId}
+        select count(1) from fs_role_menu where menu_id = #{menuId}
     </select>
 
 </mapper>