Procházet zdrojové kódy

对话前端登录实现

Zhangbw před 2 měsíci
rodič
revize
b44ea37494

+ 0 - 8
ruoyi-modules/yp-talk/src/main/java/org/dromara/talk/controller/admin/TalkAgentController.java

@@ -136,12 +136,4 @@ public class TalkAgentController extends BaseController {
         return R.ok(dictService.getDictData("tts_vcn"));
     }
 
-    /**
-     * 获取语言字典
-     */
-    @SaCheckPermission("talk:agent:list")
-    @GetMapping("/dict/language")
-    public R<List<DictDataDTO>> getLanguageDict() {
-        return R.ok(dictService.getDictData("agent_language"));
-    }
 }

+ 105 - 0
ruoyi-modules/yp-talk/src/main/java/org/dromara/talk/controller/admin/TalkUserController.java

@@ -0,0 +1,105 @@
+package org.dromara.talk.controller.admin;
+
+import java.util.List;
+
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.constraints.*;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.dromara.common.idempotent.annotation.RepeatSubmit;
+import org.dromara.common.log.annotation.Log;
+import org.dromara.common.web.core.BaseController;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.core.domain.R;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import org.dromara.common.log.enums.BusinessType;
+import org.dromara.common.excel.utils.ExcelUtil;
+import org.dromara.talk.domain.vo.TalkUserVo;
+import org.dromara.talk.domain.bo.TalkUserBo;
+import org.dromara.talk.service.ITalkUserService;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+
+/**
+ * 对话用户
+ *
+ * @author Lion Li
+ * @date 2026-01-28
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/talk/admin/user")
+public class TalkUserController extends BaseController {
+
+    private final ITalkUserService talkUserService;
+
+    /**
+     * 查询对话用户列表
+     */
+    @SaCheckPermission("system:user:list")
+    @GetMapping("/list")
+    public TableDataInfo<TalkUserVo> list(TalkUserBo bo, PageQuery pageQuery) {
+        return talkUserService.queryPageList(bo, pageQuery);
+    }
+
+    /**
+     * 导出对话用户列表
+     */
+    @SaCheckPermission("system:user:export")
+    @Log(title = "对话用户", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(TalkUserBo bo, HttpServletResponse response) {
+        List<TalkUserVo> list = talkUserService.queryList(bo);
+        ExcelUtil.exportExcel(list, "对话用户", TalkUserVo.class, response);
+    }
+
+    /**
+     * 获取对话用户详细信息
+     *
+     * @param id 主键
+     */
+    @SaCheckPermission("system:user:query")
+    @GetMapping("/{id}")
+    public R<TalkUserVo> getInfo(@NotNull(message = "主键不能为空")
+                                     @PathVariable Long id) {
+        return R.ok(talkUserService.queryById(id));
+    }
+
+    /**
+     * 新增对话用户
+     */
+    @SaCheckPermission("system:user:add")
+    @Log(title = "对话用户", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping()
+    public R<Void> add(@Validated(AddGroup.class) @RequestBody TalkUserBo bo) {
+        return toAjax(talkUserService.insertByBo(bo));
+    }
+
+    /**
+     * 修改对话用户
+     */
+    @SaCheckPermission("system:user:edit")
+    @Log(title = "对话用户", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping()
+    public R<Void> edit(@Validated(EditGroup.class) @RequestBody TalkUserBo bo) {
+        return toAjax(talkUserService.updateByBo(bo));
+    }
+
+    /**
+     * 删除对话用户
+     *
+     * @param ids 主键串
+     */
+    @SaCheckPermission("system:user:remove")
+    @Log(title = "对话用户", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public R<Void> remove(@NotEmpty(message = "主键不能为空")
+                          @PathVariable Long[] ids) {
+        return toAjax(talkUserService.deleteWithValidByIds(List.of(ids), true));
+    }
+}

+ 0 - 16
ruoyi-modules/yp-talk/src/main/java/org/dromara/talk/controller/api/ChatController.java

@@ -46,7 +46,6 @@ public class ChatController {
      *         - audio: 语音音频(base64编码)
      *         - timestamp: 时间戳
      */
-    @SaIgnore
     @PostMapping("/message")
     public Map<String, Object> handleMessage(@RequestBody Map<String, Object> request) {
         String userMessage = (String) request.get("message");
@@ -61,25 +60,12 @@ public class ChatController {
         return chatService.processMessage(userMessage, agentId, agentGender, ttsVcnList);
     }
 
-    /**
-     * 获取语言字典
-     * 返回系统支持的语言列表
-     *
-     * @return 语言字典列表
-     */
-    @SaIgnore
-    @GetMapping("/dict/language")
-    public List<DictDataDTO> getLanguageDict() {
-        return dictService.getDictData("agent_language");
-    }
-
     /**
      * 获取TTS发言人字典
      * 返回系统支持的TTS发言人列表,用于AI动态选择合适的发言人
      *
      * @return TTS发言人字典列表
      */
-    @SaIgnore
     @GetMapping("/dict/ttsVcn")
     public List<DictDataDTO> getTtsVcnDict() {
         return dictService.getDictData("tts_vcn");
@@ -92,7 +78,6 @@ public class ChatController {
      * @param bo 查询条件(可选)
      * @return 客服列表(分页数据)
      */
-    @SaIgnore
     @GetMapping("/agent/list")
     public TableDataInfo<TalkAgentVo> getAgentList(TalkAgentBo bo) {
         List<TalkAgentVo> list = talkAgentService.queryList(bo);
@@ -112,7 +97,6 @@ public class ChatController {
      *           - status: 客服状态(2=对话中)
      * @return 更新结果
      */
-    @SaIgnore
     @PutMapping("/agent/{id}")
     public Map<String, Object> updateAgentConfig(@PathVariable Long id, @RequestBody TalkAgentBo bo) {
         bo.setId(id);

+ 93 - 0
ruoyi-modules/yp-talk/src/main/java/org/dromara/talk/controller/api/TalkAuthController.java

@@ -0,0 +1,93 @@
+package org.dromara.talk.controller.api;
+
+import cn.dev33.satoken.annotation.SaIgnore;
+import cn.dev33.satoken.stp.StpUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.domain.R;
+import org.dromara.talk.domain.TalkUser;
+import org.dromara.talk.domain.vo.TalkUserVo;
+import org.dromara.talk.service.ITalkUserService;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import cn.dev33.satoken.stp.parameter.SaLoginParameter;
+
+/**
+ * 对话前端认证接口
+ *
+ * @author Lion Li
+ * @date 2026-01-28
+ */
+@Slf4j
+@SaIgnore
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/talk/auth")
+@CrossOrigin(origins = "*", maxAge = 3600)
+public class TalkAuthController {
+
+    private final ITalkUserService talkUserService;
+
+    /**
+     * 登录
+     */
+    @PostMapping("/login")
+    public R<Map<String, Object>> login(@RequestBody Map<String, String> request) {
+        String username = request.get("username");
+        String password = request.get("password");
+
+        // 查询用户(包含密码)
+        TalkUser user = talkUserService.queryByUsernameWithPassword(username);
+        if (user == null) {
+            return R.fail("用户名或密码错误");
+        }
+
+        // 验证密码
+        if (!password.equals(user.getPassword())) {
+            return R.fail("用户名或密码错误");
+        }
+
+        // 检查用户状态
+        if ("1".equals(user.getStatus())) {
+            return R.fail("用户已被停用");
+        }
+
+        // 登录并设置会话信息
+        StpUtil.login(user.getId(),
+            new SaLoginParameter()
+                .setExtra("userId", user.getId())
+                .setExtra("userName", user.getUsername())
+                .setExtra("clientid", "talk-web"));
+
+        // 返回token和用户信息(不包含密码)
+        TalkUserVo userVo = talkUserService.queryByUsername(username);
+        Map<String, Object> result = new HashMap<>();
+        result.put("token", StpUtil.getTokenValue());
+        result.put("user", userVo);
+
+        return R.ok(result);
+    }
+
+    /**
+     * 退出登录
+     */
+    @PostMapping("/logout")
+    public R<Void> logout() {
+        StpUtil.logout();
+        return R.ok();
+    }
+
+    /**
+     * 获取当前用户信息
+     */
+    @GetMapping("/userInfo")
+    public R<TalkUserVo> getUserInfo() {
+        long userId = StpUtil.getLoginIdAsLong();
+        TalkUserVo user = talkUserService.queryByUsername(String.valueOf(userId));
+        return R.ok(user);
+    }
+
+}

+ 57 - 0
ruoyi-modules/yp-talk/src/main/java/org/dromara/talk/domain/TalkUser.java

@@ -0,0 +1,57 @@
+package org.dromara.talk.domain;
+
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+
+/**
+ * 对话用户对象 talk_user
+ *
+ * @author Lion Li
+ * @date 2026-01-28
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("talk_user")
+public class TalkUser extends BaseEntity {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 用户ID
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 用户名
+     */
+    private String username;
+
+    /**
+     * 密码
+     */
+    private String password;
+
+    /**
+     * 昵称
+     */
+    private String nickname;
+
+    /**
+     * 状态(0=正常 1=停用)
+     */
+    private String status;
+
+    /**
+     * 删除标志(0=存在 1=删除)
+     */
+    @TableLogic
+    private String delFlag;
+
+
+}

+ 52 - 0
ruoyi-modules/yp-talk/src/main/java/org/dromara/talk/domain/bo/TalkUserBo.java

@@ -0,0 +1,52 @@
+package org.dromara.talk.domain.bo;
+
+import org.dromara.talk.domain.TalkUser;
+import org.dromara.common.mybatis.core.domain.BaseEntity;
+import org.dromara.common.core.validate.AddGroup;
+import org.dromara.common.core.validate.EditGroup;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+
+/**
+ * 对话用户业务对象 talk_user
+ *
+ * @author Lion Li
+ * @date 2026-01-28
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = TalkUser.class, reverseConvertGenerate = false)
+public class TalkUserBo extends BaseEntity {
+
+    /**
+     * 用户ID
+     */
+    @NotNull(message = "用户ID不能为空", groups = { EditGroup.class })
+    private Long id;
+
+    /**
+     * 用户名
+     */
+    @NotBlank(message = "用户名不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String username;
+
+    /**
+     * 密码
+     */
+    @NotBlank(message = "密码不能为空", groups = { AddGroup.class, EditGroup.class })
+    private String password;
+
+    /**
+     * 昵称
+     */
+    private String nickname;
+
+    /**
+     * 状态(0=正常 1=停用)
+     */
+    private String status;
+
+
+}

+ 63 - 0
ruoyi-modules/yp-talk/src/main/java/org/dromara/talk/domain/vo/TalkUserVo.java

@@ -0,0 +1,63 @@
+package org.dromara.talk.domain.vo;
+
+import org.dromara.talk.domain.TalkUser;
+import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
+import cn.idev.excel.annotation.ExcelProperty;
+import org.dromara.common.excel.annotation.ExcelDictFormat;
+import org.dromara.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+
+
+/**
+ * 对话用户视图对象 talk_user
+ *
+ * @author Lion Li
+ * @date 2026-01-28
+ */
+@Data
+@ExcelIgnoreUnannotated
+@AutoMapper(target = TalkUser.class)
+public class TalkUserVo implements Serializable {
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 用户ID
+     */
+    @ExcelProperty(value = "用户ID")
+    private Long id;
+
+    /**
+     * 用户名
+     */
+    @ExcelProperty(value = "用户名")
+    private String username;
+
+    /**
+     * 密码
+     */
+    @ExcelProperty(value = "密码")
+    private String password;
+
+    /**
+     * 昵称
+     */
+    @ExcelProperty(value = "昵称")
+    private String nickname;
+
+    /**
+     * 状态(0=正常 1=停用)
+     */
+    @ExcelProperty(value = "状态", converter = ExcelDictConvert.class)
+    @ExcelDictFormat(readConverterExp = "0==正常,1==停用")
+    private String status;
+
+
+}

+ 15 - 0
ruoyi-modules/yp-talk/src/main/java/org/dromara/talk/mapper/TalkUserMapper.java

@@ -0,0 +1,15 @@
+package org.dromara.talk.mapper;
+
+import org.dromara.talk.domain.TalkUser;
+import org.dromara.talk.domain.vo.TalkUserVo;
+import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
+
+/**
+ * 对话用户Mapper接口
+ *
+ * @author Lion Li
+ * @date 2026-01-28
+ */
+public interface TalkUserMapper extends BaseMapperPlus<TalkUser, TalkUserVo> {
+
+}

+ 80 - 0
ruoyi-modules/yp-talk/src/main/java/org/dromara/talk/service/ITalkUserService.java

@@ -0,0 +1,80 @@
+package org.dromara.talk.service;
+
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.talk.domain.TalkUser;
+import org.dromara.talk.domain.bo.TalkUserBo;
+import org.dromara.talk.domain.vo.TalkUserVo;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * 对话用户Service接口
+ *
+ * @author Lion Li
+ * @date 2026-01-28
+ */
+public interface ITalkUserService {
+
+    /**
+     * 查询对话用户
+     *
+     * @param id 主键
+     * @return 对话用户
+     */
+    TalkUserVo queryById(Long id);
+
+    /**
+     * 分页查询对话用户列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 对话用户分页列表
+     */
+    TableDataInfo<TalkUserVo> queryPageList(TalkUserBo bo, PageQuery pageQuery);
+
+    /**
+     * 查询符合条件的对话用户列表
+     *
+     * @param bo 查询条件
+     * @return 对话用户列表
+     */
+    List<TalkUserVo> queryList(TalkUserBo bo);
+
+    /**
+     * 新增对话用户
+     *
+     * @param bo 对话用户
+     * @return 是否新增成功
+     */
+    Boolean insertByBo(TalkUserBo bo);
+
+    /**
+     * 修改对话用户
+     *
+     * @param bo 对话用户
+     * @return 是否修改成功
+     */
+    Boolean updateByBo(TalkUserBo bo);
+
+    /**
+     * 校验并批量删除对话用户信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
+
+    /**
+     * 根据用户名查询用户(包含密码,用于登录验证)
+     */
+    TalkUser queryByUsernameWithPassword(String username);
+
+    /**
+     * 根据用户名查询用户VO
+     */
+    TalkUserVo queryByUsername(String username);
+
+}

+ 147 - 0
ruoyi-modules/yp-talk/src/main/java/org/dromara/talk/service/impl/TalkUserServiceImpl.java

@@ -0,0 +1,147 @@
+package org.dromara.talk.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.common.core.utils.MapstructUtils;
+import org.dromara.common.core.utils.StringUtils;
+import org.dromara.common.mybatis.core.page.PageQuery;
+import org.dromara.common.mybatis.core.page.TableDataInfo;
+import org.dromara.talk.domain.TalkUser;
+import org.dromara.talk.domain.bo.TalkUserBo;
+import org.dromara.talk.domain.vo.TalkUserVo;
+import org.dromara.talk.mapper.TalkUserMapper;
+import org.dromara.talk.service.ITalkUserService;
+import org.springframework.stereotype.Service;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 对话用户Service业务层处理
+ *
+ * @author Lion Li
+ * @date 2026-01-28
+ */
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class TalkUserServiceImpl implements ITalkUserService {
+
+    private final TalkUserMapper baseMapper;
+
+    /**
+     * 查询对话用户
+     *
+     * @param id 主键
+     * @return 对话用户
+     */
+    @Override
+    public TalkUserVo queryById(Long id){
+        return baseMapper.selectVoById(id);
+    }
+
+    /**
+     * 分页查询对话用户列表
+     *
+     * @param bo        查询条件
+     * @param pageQuery 分页参数
+     * @return 对话用户分页列表
+     */
+    @Override
+    public TableDataInfo<TalkUserVo> queryPageList(TalkUserBo bo, PageQuery pageQuery) {
+        LambdaQueryWrapper<TalkUser> lqw = buildQueryWrapper(bo);
+        Page<TalkUserVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
+        return TableDataInfo.build(result);
+    }
+
+    /**
+     * 查询符合条件的对话用户列表
+     *
+     * @param bo 查询条件
+     * @return 对话用户列表
+     */
+    @Override
+    public List<TalkUserVo> queryList(TalkUserBo bo) {
+        LambdaQueryWrapper<TalkUser> lqw = buildQueryWrapper(bo);
+        return baseMapper.selectVoList(lqw);
+    }
+
+    private LambdaQueryWrapper<TalkUser> buildQueryWrapper(TalkUserBo bo) {
+        Map<String, Object> params = bo.getParams();
+        LambdaQueryWrapper<TalkUser> lqw = Wrappers.lambdaQuery();
+        lqw.orderByDesc(TalkUser::getId);
+        lqw.like(StringUtils.isNotBlank(bo.getUsername()), TalkUser::getUsername, bo.getUsername());
+        lqw.eq(StringUtils.isNotBlank(bo.getPassword()), TalkUser::getPassword, bo.getPassword());
+        lqw.like(StringUtils.isNotBlank(bo.getNickname()), TalkUser::getNickname, bo.getNickname());
+        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), TalkUser::getStatus, bo.getStatus());
+        return lqw;
+    }
+
+    /**
+     * 新增对话用户
+     *
+     * @param bo 对话用户
+     * @return 是否新增成功
+     */
+    @Override
+    public Boolean insertByBo(TalkUserBo bo) {
+        TalkUser add = MapstructUtils.convert(bo, TalkUser.class);
+        validEntityBeforeSave(add);
+        boolean flag = baseMapper.insert(add) > 0;
+        if (flag) {
+            bo.setId(add.getId());
+        }
+        return flag;
+    }
+
+    /**
+     * 修改对话用户
+     *
+     * @param bo 对话用户
+     * @return 是否修改成功
+     */
+    @Override
+    public Boolean updateByBo(TalkUserBo bo) {
+        TalkUser update = MapstructUtils.convert(bo, TalkUser.class);
+        validEntityBeforeSave(update);
+        return baseMapper.updateById(update) > 0;
+    }
+
+    /**
+     * 保存前的数据校验
+     */
+    private void validEntityBeforeSave(TalkUser entity){
+        //TODO 做一些数据校验,如唯一约束
+    }
+
+    /**
+     * 校验并批量删除对话用户信息
+     *
+     * @param ids     待删除的主键集合
+     * @param isValid 是否进行有效性校验
+     * @return 是否删除成功
+     */
+    @Override
+    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
+        if(isValid){
+            //TODO 做一些业务上的校验,判断是否需要校验
+        }
+        return baseMapper.deleteByIds(ids) > 0;
+    }
+    @Override
+    public TalkUser queryByUsernameWithPassword(String username) {
+        return baseMapper.selectOne(new LambdaQueryWrapper<TalkUser>()
+            .eq(TalkUser::getUsername, username));
+    }
+
+    @Override
+    public TalkUserVo queryByUsername(String username) {
+        return baseMapper.selectVoOne(new LambdaQueryWrapper<TalkUser>()
+            .eq(TalkUser::getUsername, username));
+    }
+
+}