feat(tenant): 添加租户白名单功能并集成系统反馈模块- 新增租户白名单相关接口和服务实现

- 添加系统反馈模块,包括反馈列表、新增反馈、处理反馈等功能
- 在 HeaderCheckAspect 中集成租户白名单检查逻辑
- 优化 SysUser 中登录类型字段的定义
main-p
shi 2025-02-27 17:48:29 +08:00
parent 1323f46128
commit f4be0750f5
16 changed files with 925 additions and 7 deletions

View File

@ -1,8 +1,5 @@
package com.ff.base.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.ff.base.constant.Constants;
import com.ff.base.interceptor.DataSourceSwitchInterceptor;
import com.ff.base.interceptor.RepeatSubmitInterceptor;
@ -10,8 +7,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.CacheControl;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@ -19,7 +14,6 @@ import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
@ -36,6 +30,9 @@ public class ResourcesConfig implements WebMvcConfigurer
@Autowired
private DataSourceSwitchInterceptor dataSourceSwitchInterceptor;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{

View File

@ -0,0 +1,18 @@
package com.ff.base.enums;
import lombok.Getter;
@Getter
public enum Status {
PENDING(1, "待处理"),
PROCESSED(2, "已处理");
private final Integer value;
private final String description;
Status(Integer value, String description) {
this.value = value;
this.description = description;
}
}

View File

@ -143,7 +143,7 @@ public class SysUser extends BaseEntity {
/**
* 0 1 2
* 0 1 2
*/
private Integer loginType;

View File

@ -0,0 +1,39 @@
package com.ff.base.system.domain;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.ff.base.annotation.Excel;
import com.ff.base.core.domain.BaseEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* ff_tenant_white
*
* @author shi
* @date 2025-02-27
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class TenantWhite extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键id */
private Long id;
/** 租户id */
@JsonSerialize(using = ToStringSerializer.class)
@Excel(name = "租户id", width = 30, dateFormat = "yyyy-MM-dd")
private Long tenantId;
/** 白名单ip地址 */
@Excel(name = "白名单ip地址")
private String whiteIp;
}

View File

@ -0,0 +1,61 @@
package com.ff.base.system.mapper;
import java.util.List;
import com.ff.base.system.domain.TenantWhite;
/**
* Mapper
*
* @author shi
* @date 2025-02-27
*/
public interface TenantWhiteMapper
{
/**
*
*
* @param id
* @return
*/
TenantWhite selectTenantWhiteById(Long id);
/**
*
*
* @param tenantWhite
* @return
*/
List<TenantWhite> selectTenantWhiteList(TenantWhite tenantWhite);
/**
*
*
* @param tenantWhite
* @return
*/
int insertTenantWhite(TenantWhite tenantWhite);
/**
*
*
* @param tenantWhite
* @return
*/
int updateTenantWhite(TenantWhite tenantWhite);
/**
*
*
* @param id
* @return
*/
int deleteTenantWhiteById(Long id);
/**
*
*
* @param ids
* @return
*/
int deleteTenantWhiteByIds(Long[] ids);
}

View File

@ -0,0 +1,61 @@
package com.ff.base.system.service;
import java.util.List;
import com.ff.base.system.domain.TenantWhite;
/**
* Service
*
* @author shi
* @date 2025-02-27
*/
public interface ITenantWhiteService
{
/**
*
*
* @param id
* @return
*/
TenantWhite selectTenantWhiteById(Long id);
/**
*
*
* @param tenantWhite
* @return
*/
List<TenantWhite> selectTenantWhiteList(TenantWhite tenantWhite);
/**
*
*
* @param tenantWhite
* @return
*/
int insertTenantWhite(TenantWhite tenantWhite);
/**
*
*
* @param tenantWhite
* @return
*/
int updateTenantWhite(TenantWhite tenantWhite);
/**
*
*
* @param ids
* @return
*/
int deleteTenantWhiteByIds(Long[] ids);
/**
*
*
* @param id
* @return
*/
int deleteTenantWhiteById(Long id);
}

View File

@ -0,0 +1,99 @@
package com.ff.base.system.service.impl;
import java.util.List;
import com.ff.base.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ff.base.system.mapper.TenantWhiteMapper;
import com.ff.base.system.domain.TenantWhite;
import com.ff.base.system.service.ITenantWhiteService;
import cn.hutool.core.util.IdUtil;
/**
* Service
*
* @author shi
* @date 2025-02-27
*/
@Service
public class TenantWhiteServiceImpl implements ITenantWhiteService
{
@Autowired
private TenantWhiteMapper tenantWhiteMapper;
/**
*
*
* @param id
* @return
*/
@Override
public TenantWhite selectTenantWhiteById(Long id)
{
return tenantWhiteMapper.selectTenantWhiteById(id);
}
/**
*
*
* @param tenantWhite
* @return
*/
@Override
public List<TenantWhite> selectTenantWhiteList(TenantWhite tenantWhite)
{
return tenantWhiteMapper.selectTenantWhiteList(tenantWhite);
}
/**
*
*
* @param tenantWhite
* @return
*/
@Override
public int insertTenantWhite(TenantWhite tenantWhite)
{
tenantWhite.setId(IdUtil.getSnowflakeNextId());
tenantWhite.setCreateTime(DateUtils.getNowDate());
return tenantWhiteMapper.insertTenantWhite(tenantWhite);
}
/**
*
*
* @param tenantWhite
* @return
*/
@Override
public int updateTenantWhite(TenantWhite tenantWhite)
{
tenantWhite.setUpdateTime(DateUtils.getNowDate());
return tenantWhiteMapper.updateTenantWhite(tenantWhite);
}
/**
*
*
* @param ids
* @return
*/
@Override
public int deleteTenantWhiteByIds(Long[] ids)
{
return tenantWhiteMapper.deleteTenantWhiteByIds(ids);
}
/**
*
*
* @param id
* @return
*/
@Override
public int deleteTenantWhiteById(Long id)
{
return tenantWhiteMapper.deleteTenantWhiteById(id);
}
}

View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ff.base.system.mapper.TenantWhiteMapper">
<resultMap type="TenantWhite" id="TenantWhiteResult">
<result property="id" column="id" />
<result property="tenantId" column="tenant_id" />
<result property="whiteIp" column="white_ip" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectTenantWhiteVo">
select id, tenant_id, white_ip, create_by, create_time, update_by, update_time from ff_tenant_white
</sql>
<select id="selectTenantWhiteList" parameterType="TenantWhite" resultMap="TenantWhiteResult">
<include refid="selectTenantWhiteVo"/>
<where>
<if test="tenantId != null "> and tenant_id = #{tenantId}</if>
<if test="whiteIp != null and whiteIp != ''"> and white_ip = #{whiteIp}</if>
</where>
</select>
<select id="selectTenantWhiteById" parameterType="Long" resultMap="TenantWhiteResult">
<include refid="selectTenantWhiteVo"/>
where id = #{id}
</select>
<insert id="insertTenantWhite" parameterType="TenantWhite">
insert into ff_tenant_white
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">id,</if>
<if test="tenantId != null">tenant_id,</if>
<if test="whiteIp != null">white_ip,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
<if test="tenantId != null">#{tenantId},</if>
<if test="whiteIp != null">#{whiteIp},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
</insert>
<update id="updateTenantWhite" parameterType="TenantWhite">
update ff_tenant_white
<trim prefix="SET" suffixOverrides=",">
<if test="tenantId != null">tenant_id = #{tenantId},</if>
<if test="whiteIp != null">white_ip = #{whiteIp},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteTenantWhiteById" parameterType="Long">
delete from ff_tenant_white where id = #{id}
</delete>
<delete id="deleteTenantWhiteByIds" parameterType="String">
delete from ff_tenant_white where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>

View File

@ -1,6 +1,11 @@
package com.ff.annotation;
import cn.hutool.core.util.IdUtil;
import com.ff.base.constant.Constants;
import com.ff.base.system.domain.TenantWhite;
import com.ff.base.system.service.ITenantWhiteService;
import com.ff.base.utils.ip.IpUtils;
import com.ff.base.utils.uuid.IdUtils;
import com.ff.config.KeyConfig;
import com.ff.base.utils.sign.Md5Utils;
import com.ff.base.system.domain.TenantSecretKey;
@ -15,6 +20,7 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
*
@ -29,6 +35,9 @@ public class HeaderCheckAspect {
@Resource
private ITenantSecretKeyService tenantSecretKeyService;
@Resource
private ITenantWhiteService tenantWhiteService;
@Resource
private KeyConfig keyUtils;
@ -63,6 +72,12 @@ public class HeaderCheckAspect {
Assert.isTrue(tenantSecretKey.getTenantStatus(), "当前租户已停用");
List<TenantWhite> tenantWhites = tenantWhiteService.selectTenantWhiteList(TenantWhite.builder()
.tenantId(tenantSecretKey.getId())
.whiteIp(IpUtils.getIpAddr())
.build());
Assert.isTrue(!tenantWhites.isEmpty(), "当前租户不在白名单内");
String keyG = Md5Utils.md5New(random + key + tenantSecretKey.getTenantSecret());
Assert.isTrue(keyG.equals(sign), "签名错误");
//保存

View File

@ -0,0 +1,98 @@
package com.ff.sys.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import com.ff.base.enums.Status;
import com.ff.base.utils.SecurityUtils;
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.ff.base.annotation.Log;
import com.ff.base.core.controller.BaseController;
import com.ff.base.core.domain.AjaxResult;
import com.ff.base.enums.BusinessType;
import com.ff.sys.domain.SysFeedback;
import com.ff.sys.service.ISysFeedbackService;
import com.ff.base.utils.poi.ExcelUtil;
import com.ff.base.core.page.TableDataInfo;
/**
* Controller
*
* @author shi
* @date 2025-02-27
*/
@RestController
@RequestMapping("/sys/feedback")
public class SysFeedbackController extends BaseController
{
@Autowired
private ISysFeedbackService sysFeedbackService;
/**
*
*/
@PreAuthorize("@ss.hasPermi('sys:feedback:list')")
@GetMapping("/list")
public TableDataInfo list(SysFeedback sysFeedback)
{
startPage();
List<SysFeedback> list = sysFeedbackService.selectSysFeedbackList(sysFeedback);
return getDataTable(list);
}
/**
*
*/
@PreAuthorize("@ss.hasPermi('sys:feedback:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return success(sysFeedbackService.selectSysFeedbackById(id));
}
/**
*
*/
@PreAuthorize("@ss.hasPermi('sys:feedback:add')")
@Log(title = "系统反馈", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SysFeedback sysFeedback)
{
sysFeedback.setUserId(getUserId());
sysFeedback.setUserType(SecurityUtils.getLoginUser().getUser().getLoginType());
return toAjax(sysFeedbackService.insertSysFeedback(sysFeedback));
}
/**
*
*/
@PreAuthorize("@ss.hasPermi('sys:feedback:edit')")
@Log(title = "系统反馈", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SysFeedback sysFeedback)
{
sysFeedback.setStatus(Status.PROCESSED.getValue());
return toAjax(sysFeedbackService.updateSysFeedback(sysFeedback));
}
/**
*
*/
@PreAuthorize("@ss.hasPermi('sys:feedback:remove')")
@Log(title = "系统反馈", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(sysFeedbackService.deleteSysFeedbackByIds(ids));
}
}

View File

@ -0,0 +1,52 @@
package com.ff.sys.domain;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.ff.base.annotation.Excel;
import com.ff.base.core.domain.BaseEntity;
import lombok.Data;
/**
* ff_sys_feedback
*
* @author shi
* @date 2025-02-27
*/
@Data
public class SysFeedback extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** $column.columnComment */
private Long id;
/** 用户类型 1 租户 2代理 */
@Excel(name = "用户类型 1 租户 2代理 ")
private Integer userType;
/** 用户id */
@JsonSerialize(using = ToStringSerializer.class)
@Excel(name = "用户id", width = 30, dateFormat = "yyyy-MM-dd")
private Long userId;
/** 标题 */
@Excel(name = "标题")
private String title;
/** 手机号 */
@Excel(name = "手机号")
private String phone;
/** 反馈内容 */
@Excel(name = "反馈内容")
private String content;
/** 状态 1待处理 2已处理 */
@Excel(name = "状态 1待处理 2已处理")
private Integer status;
/** 回复内容 */
@Excel(name = "回复内容")
private String replyContent;
}

View File

@ -0,0 +1,61 @@
package com.ff.sys.mapper;
import java.util.List;
import com.ff.sys.domain.SysFeedback;
/**
* Mapper
*
* @author shi
* @date 2025-02-27
*/
public interface SysFeedbackMapper
{
/**
*
*
* @param id
* @return
*/
SysFeedback selectSysFeedbackById(Long id);
/**
*
*
* @param sysFeedback
* @return
*/
List<SysFeedback> selectSysFeedbackList(SysFeedback sysFeedback);
/**
*
*
* @param sysFeedback
* @return
*/
int insertSysFeedback(SysFeedback sysFeedback);
/**
*
*
* @param sysFeedback
* @return
*/
int updateSysFeedback(SysFeedback sysFeedback);
/**
*
*
* @param id
* @return
*/
int deleteSysFeedbackById(Long id);
/**
*
*
* @param ids
* @return
*/
int deleteSysFeedbackByIds(Long[] ids);
}

View File

@ -0,0 +1,61 @@
package com.ff.sys.service;
import java.util.List;
import com.ff.sys.domain.SysFeedback;
/**
* Service
*
* @author shi
* @date 2025-02-27
*/
public interface ISysFeedbackService
{
/**
*
*
* @param id
* @return
*/
SysFeedback selectSysFeedbackById(Long id);
/**
*
*
* @param sysFeedback
* @return
*/
List<SysFeedback> selectSysFeedbackList(SysFeedback sysFeedback);
/**
*
*
* @param sysFeedback
* @return
*/
int insertSysFeedback(SysFeedback sysFeedback);
/**
*
*
* @param sysFeedback
* @return
*/
int updateSysFeedback(SysFeedback sysFeedback);
/**
*
*
* @param ids
* @return
*/
int deleteSysFeedbackByIds(Long[] ids);
/**
*
*
* @param id
* @return
*/
int deleteSysFeedbackById(Long id);
}

View File

@ -0,0 +1,99 @@
package com.ff.sys.service.impl;
import java.util.List;
import com.ff.base.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ff.sys.mapper.SysFeedbackMapper;
import com.ff.sys.domain.SysFeedback;
import com.ff.sys.service.ISysFeedbackService;
import cn.hutool.core.util.IdUtil;
/**
* Service
*
* @author shi
* @date 2025-02-27
*/
@Service
public class SysFeedbackServiceImpl implements ISysFeedbackService
{
@Autowired
private SysFeedbackMapper sysFeedbackMapper;
/**
*
*
* @param id
* @return
*/
@Override
public SysFeedback selectSysFeedbackById(Long id)
{
return sysFeedbackMapper.selectSysFeedbackById(id);
}
/**
*
*
* @param sysFeedback
* @return
*/
@Override
public List<SysFeedback> selectSysFeedbackList(SysFeedback sysFeedback)
{
return sysFeedbackMapper.selectSysFeedbackList(sysFeedback);
}
/**
*
*
* @param sysFeedback
* @return
*/
@Override
public int insertSysFeedback(SysFeedback sysFeedback)
{
sysFeedback.setId(IdUtil.getSnowflakeNextId());
sysFeedback.setCreateTime(DateUtils.getNowDate());
return sysFeedbackMapper.insertSysFeedback(sysFeedback);
}
/**
*
*
* @param sysFeedback
* @return
*/
@Override
public int updateSysFeedback(SysFeedback sysFeedback)
{
sysFeedback.setUpdateTime(DateUtils.getNowDate());
return sysFeedbackMapper.updateSysFeedback(sysFeedback);
}
/**
*
*
* @param ids
* @return
*/
@Override
public int deleteSysFeedbackByIds(Long[] ids)
{
return sysFeedbackMapper.deleteSysFeedbackByIds(ids);
}
/**
*
*
* @param id
* @return
*/
@Override
public int deleteSysFeedbackById(Long id)
{
return sysFeedbackMapper.deleteSysFeedbackById(id);
}
}

View File

@ -0,0 +1,74 @@
package com.ff.tenant.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
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.ff.base.annotation.Log;
import com.ff.base.core.controller.BaseController;
import com.ff.base.core.domain.AjaxResult;
import com.ff.base.enums.BusinessType;
import com.ff.base.system.domain.TenantWhite;
import com.ff.base.system.service.ITenantWhiteService;
import com.ff.base.utils.poi.ExcelUtil;
import com.ff.base.core.page.TableDataInfo;
/**
* Controller
*
* @author shi
* @date 2025-02-27
*/
@RestController
@RequestMapping("/tenant/white")
public class TenantWhiteController extends BaseController
{
@Autowired
private ITenantWhiteService tenantWhiteService;
/**
*
*/
@PreAuthorize("@ss.hasPermi('tenant:white:list')")
@GetMapping("/list")
public TableDataInfo list(TenantWhite tenantWhite)
{
startPage();
tenantWhite.setTenantId(getUserId());
List<TenantWhite> list = tenantWhiteService.selectTenantWhiteList(tenantWhite);
return getDataTable(list);
}
/**
*
*/
@PreAuthorize("@ss.hasPermi('tenant:white:add')")
@Log(title = "租户白名单", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody TenantWhite tenantWhite)
{
tenantWhite.setTenantId(getUserId());
tenantWhite.setCreateBy(getUsername());
return toAjax(tenantWhiteService.insertTenantWhite(tenantWhite));
}
/**
*
*/
@PreAuthorize("@ss.hasPermi('tenant:white:remove')")
@Log(title = "租户白名单", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(tenantWhiteService.deleteTenantWhiteByIds(ids));
}
}

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ff.sys.mapper.SysFeedbackMapper">
<resultMap type="SysFeedback" id="SysFeedbackResult">
<result property="id" column="id" />
<result property="userType" column="user_type" />
<result property="userId" column="user_id" />
<result property="title" column="title" />
<result property="phone" column="phone" />
<result property="content" column="content" />
<result property="status" column="status" />
<result property="replyContent" column="reply_content" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectSysFeedbackVo">
select id, user_type, user_id, title, phone, content, status, reply_content, create_by, create_time, update_by, update_time from ff_sys_feedback
</sql>
<select id="selectSysFeedbackList" parameterType="SysFeedback" resultMap="SysFeedbackResult">
<include refid="selectSysFeedbackVo"/>
<where>
<if test="userType != null "> and user_type = #{userType}</if>
<if test="userId != null "> and user_id = #{userId}</if>
<if test="title != null and title != ''"> and title = #{title}</if>
<if test="phone != null and phone != ''"> and phone = #{phone}</if>
<if test="content != null and content != ''"> and content = #{content}</if>
<if test="status != null "> and status = #{status}</if>
<if test="replyContent != null and replyContent != ''"> and reply_content = #{replyContent}</if>
</where>
</select>
<select id="selectSysFeedbackById" parameterType="Long" resultMap="SysFeedbackResult">
<include refid="selectSysFeedbackVo"/>
where id = #{id}
</select>
<insert id="insertSysFeedback" parameterType="SysFeedback">
insert into ff_sys_feedback
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">id,</if>
<if test="userType != null">user_type,</if>
<if test="userId != null">user_id,</if>
<if test="title != null">title,</if>
<if test="phone != null">phone,</if>
<if test="content != null">content,</if>
<if test="status != null">status,</if>
<if test="replyContent != null">reply_content,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
<if test="userType != null">#{userType},</if>
<if test="userId != null">#{userId},</if>
<if test="title != null">#{title},</if>
<if test="phone != null">#{phone},</if>
<if test="content != null">#{content},</if>
<if test="status != null">#{status},</if>
<if test="replyContent != null">#{replyContent},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
</insert>
<update id="updateSysFeedback" parameterType="SysFeedback">
update ff_sys_feedback
<trim prefix="SET" suffixOverrides=",">
<if test="userType != null">user_type = #{userType},</if>
<if test="userId != null">user_id = #{userId},</if>
<if test="title != null">title = #{title},</if>
<if test="phone != null">phone = #{phone},</if>
<if test="content != null">content = #{content},</if>
<if test="status != null">status = #{status},</if>
<if test="replyContent != null">reply_content = #{replyContent},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where id = #{id}
</update>
<delete id="deleteSysFeedbackById" parameterType="Long">
delete from ff_sys_feedback where id = #{id}
</delete>
<delete id="deleteSysFeedbackByIds" parameterType="String">
delete from ff_sys_feedback where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>