This commit is contained in:
Lx 2025-08-04 10:22:56 +08:00
parent 716536e260
commit 4a62d0fc52
8 changed files with 180 additions and 144 deletions

View File

@ -93,12 +93,14 @@ public class WorkReportServiceImpl extends ServiceImpl<WorkReportMapper, WorkRep
String message = "向您进行了工作汇报,请在内部管理中查阅!";
String text = userName + message;
// 发送消息给汇报对象
this.sendMessage(createReqVO.getReportTos(), text, createReqVO.getServicePackageId());
// 根据服务套餐id进行发送
if("jiaxiao".equals(createReqVO.getServicePackageId())){
/*if("jiaxiao".equals(createReqVO.getServicePackageId())){
this.sendMessage(createReqVO.getReportTos(), text, createReqVO.getServicePackageId());
}else if("jiance".equals(createReqVO.getServicePackageId())){
this.sendMessage(createReqVO.getReportTos(), text, createReqVO.getServicePackageId());
}
}*/
// 返回
return report.getId();
}

View File

@ -18,6 +18,7 @@ import cn.iocoder.yudao.module.rescue.service.IRescueOrderInfoService;
import cn.iocoder.yudao.module.rescue.utils.ExcelUtil;
import cn.iocoder.yudao.module.rescue.utils.StringUtils;
import cn.iocoder.yudao.module.rescue.vo.BuckleVO;
import cn.iocoder.yudao.module.rescue.vo.DriverInfoExportVO;
import cn.iocoder.yudao.module.rescue.vo.MoneyManagement;
import cn.iocoder.yudao.module.rescue.vo.ReturnCarVO;
import cn.iocoder.yudao.module.staff.entity.CompanyStaff;
@ -542,7 +543,7 @@ public class RescueInfoSystem extends BaseController {
*/
@GetMapping("/get-import-template")
public void importTemplate(HttpServletResponse response) throws IOException {
String[] head = {"员工姓名", "岗位", "年龄", "电话号码", "性别"};
String[] head = {"员工姓名", "年龄", "电话号码", "性别"};
// 下拉框列及选项列索引 -> 下拉框选项
Map<Integer, String[]> dropdownColumns = new HashMap<>();
@ -562,7 +563,7 @@ public class RescueInfoSystem extends BaseController {
dropdownColumns.put(5, genders);
List<List<String>> exampleDataList = Arrays.asList(
Arrays.asList("测试员工", "岗位是下拉框选择", "年龄", "电话号码", "性别")
Arrays.asList("测试员工", "年龄", "电话号码", "性别")
);
List<Integer> textColumns = Collections.singletonList(3);
@ -577,9 +578,9 @@ public class RescueInfoSystem extends BaseController {
@GetMapping("/drviceExport")
public void exportUserList(DriverInfoDto query,
HttpServletResponse response) throws IOException {
List<DriverInfoDto> list = rescueInfoService.getAll(query);
List<DriverInfoExportVO> list = rescueInfoService.getAll(query);
// 输出 Excel
ExcelUtils.write(response, "员工数据.xls", "数据", DriverInfoDto.class,
ExcelUtils.write(response, "员工数据.xls", "数据", DriverInfoExportVO.class,
list);
}
}

View File

@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.rescue.domain.RescueInfo;
import cn.iocoder.yudao.module.rescue.dto.DriverInfo2Dto;
import cn.iocoder.yudao.module.rescue.dto.DriverInfoDto;
import cn.iocoder.yudao.module.rescue.vo.BuckleVO;
import cn.iocoder.yudao.module.rescue.vo.DriverInfoExportVO;
import cn.iocoder.yudao.module.rescue.vo.DriverStaffSaveVO;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@ -91,5 +92,5 @@ public interface RescueInfoMapper extends BaseMapper<RescueInfo>
DriverStaffSaveVO getOnInternal(Long id);
List<DriverInfoDto> getAll(@Param("entity") DriverInfoDto query);
List<DriverInfoExportVO> getAll(@Param("entity") DriverInfoDto query);
}

View File

@ -6,10 +6,7 @@ import cn.iocoder.yudao.module.rescue.domain.DriverInfo;
import cn.iocoder.yudao.module.rescue.domain.RescueInfo;
import cn.iocoder.yudao.module.rescue.dto.DriverInfo2Dto;
import cn.iocoder.yudao.module.rescue.dto.DriverInfoDto;
import cn.iocoder.yudao.module.rescue.vo.BuckleVO;
import cn.iocoder.yudao.module.rescue.vo.DriverStaffSaveVO;
import cn.iocoder.yudao.module.rescue.vo.MoneyManagement;
import cn.iocoder.yudao.module.rescue.vo.ReturnCarVO;
import cn.iocoder.yudao.module.rescue.vo.*;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -176,5 +173,5 @@ public interface IRescueInfoService extends IService<RescueInfo>
DriverStaffSaveVO getOnInternal(Long id);
List<DriverInfoDto> getAll(DriverInfoDto query);
List<DriverInfoExportVO> getAll(DriverInfoDto query);
}

View File

@ -25,10 +25,7 @@ import cn.iocoder.yudao.module.rescue.utils.DateUtils;
import cn.iocoder.yudao.module.rescue.utils.RedisUtil;
import cn.iocoder.yudao.module.rescue.utils.RedissonDelayQueue;
import cn.iocoder.yudao.module.rescue.utils.StringUtils;
import cn.iocoder.yudao.module.rescue.vo.BuckleVO;
import cn.iocoder.yudao.module.rescue.vo.DriverStaffSaveVO;
import cn.iocoder.yudao.module.rescue.vo.MoneyManagement;
import cn.iocoder.yudao.module.rescue.vo.ReturnCarVO;
import cn.iocoder.yudao.module.rescue.vo.*;
import cn.iocoder.yudao.module.staff.service.CompanyStaffService;
import cn.iocoder.yudao.module.staff.vo.CompanyStaffRespVO;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
@ -1548,7 +1545,7 @@ public class RescueInfoServiceImpl extends ServiceImpl<RescueInfoMapper, RescueI
}
@Override
public List<DriverInfoDto> getAll(DriverInfoDto query) {
public List<DriverInfoExportVO> getAll(DriverInfoDto query) {
return baseMapper.getAll(query);
}
public List<RescueInfo> filterRescueInfoByDate(List<RescueInfo> rescueInfos, Date startTime, Date endTime) {

View File

@ -0,0 +1,41 @@
package cn.iocoder.yudao.module.rescue.vo;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
@Data
public class DriverInfoExportVO {
@ExcelProperty("员工账号")
private String username;
@ExcelProperty("员工姓名")
private String nickname;
@ExcelProperty("手机号")
private String mobile;
@ExcelIgnore
private String sex;
@ExcelProperty("性别")
private String sexStr;
@ExcelProperty("岗位")
private String roleNames;
public void setSex(String sex) {
this.sex = sex;
// 设置转换后的性别字符串
if ("0".equals(sex)) {
this.sexStr = "";
} else if ("1".equals(sex)) {
this.sexStr = "";
} else {
this.sexStr = "未知";
}
}
}

View File

@ -6,13 +6,13 @@
<select id="selectRescueInfoList" parameterType="cn.iocoder.yudao.module.rescue.domain.RescueInfo"
resultType="cn.iocoder.yudao.module.rescue.domain.RescueInfo">
SELECT ri.*,
roi.order_status,
roi.set_money
roi.order_status,
roi.set_money
FROM rescue_info ri
left join rescue_order_info roi on roi.rescue_info_id = ri.id
left join rescue_order_info roi on roi.rescue_info_id = ri.id
<where>
1 = 1
and ri.deleted = '0'
and ri.deleted = '0'
<if test="map.rescueStatus != null">
<choose>
<when test="map.rescueStatus == '1'.toString()">
@ -49,9 +49,10 @@
and ri.license_num like concat('%', #{map.licenseNum}, '%')
</if>
<if test="map.deptList != null and map.deptList.size()>0">
and ri.dept_id in <foreach collection="map.deptList" separator="," item="item" open="(" close=")">
#{item}
</foreach>
and ri.dept_id in
<foreach collection="map.deptList" separator="," item="item" open="(" close=")">
#{item}
</foreach>
</if>
</where>
order by ri.create_time desc
@ -59,13 +60,13 @@
<select id="selectRescueListSystem2" resultType="cn.iocoder.yudao.module.rescue.domain.RescueInfo">
SELECT ri.*,
roi.order_status,
roi.set_money,
roi.id as rescueOrderId,
roi.pay_money,
roi.pay_time
roi.order_status,
roi.set_money,
roi.id as rescueOrderId,
roi.pay_money,
roi.pay_time
FROM rescue_info ri
left join rescue_order_info roi on roi.rescue_info_id = ri.id
left join rescue_order_info roi on roi.rescue_info_id = ri.id
where ri.deleted = '0'
<if test="map.orderStatus != null and map.orderStatus != ''">
and roi.order_status = #{map.orderStatus}
@ -96,7 +97,7 @@
</if>
<if test="map.rescueStart != null and map.rescueEnd != null">
and rescue_time between
concat(#{map.rescueStart}, ' 00:00:00') and concat(#{map.rescueEnd}, ' 23:59:59')
concat(#{map.rescueStart}, ' 00:00:00') and concat(#{map.rescueEnd}, ' 23:59:59')
</if>
<if test="map.deptId != null">
and if(#{map.deptId} = 0, ri.dept_id is null, ri.dept_id = #{map.deptId})
@ -107,15 +108,15 @@
<select id="listData" resultType="com.alibaba.fastjson.JSONObject">
SELECT sum(set_money / 100) as allMoney,
count(1) as allNum,
sum(case
when ri.car_type = '1' then (set_money / 100) *
${rescueTcBig}
when ri.car_type = '2' then (set_money / 100) * ${rescueTcMid}
when ri.car_type = '3' then (set_money / 100) * ${rescueTcSmall}
else 0 end) as tcAll
count(1) as allNum,
sum(case
when ri.car_type = '1' then (set_money / 100) *
${rescueTcBig}
when ri.car_type = '2' then (set_money / 100) * ${rescueTcMid}
when ri.car_type = '3' then (set_money / 100) * ${rescueTcSmall}
else 0 end) as tcAll
FROM rescue_info ri
left join rescue_order_info roi on roi.rescue_info_id = ri.id
left join rescue_order_info roi on roi.rescue_info_id = ri.id
<where>
<if test="driverName != null">
and ri.driver_name like concat('%', #{driverName}, '%')
@ -135,10 +136,10 @@
<select id="selectRescueInfoListApp" parameterType="cn.iocoder.yudao.module.rescue.domain.RescueInfo"
resultType="cn.iocoder.yudao.module.rescue.domain.RescueInfo">
SELECT ri.*,
roi.order_status,
roi.set_money
roi.order_status,
roi.set_money
FROM rescue_info ri
left join rescue_order_info roi on roi.rescue_info_id = ri.id
left join rescue_order_info roi on roi.rescue_info_id = ri.id
<where>
(ri.user_id = #{map.userId} or connection_phone = #{map.connectionPhone})
<if test="map.rescueStatus != null">
@ -223,12 +224,12 @@
from rescue_info ri
<where>
dept_id = #{map.deptId}
and rescue_type = '5'
and rescue_type = '5'
<if test="map.connectionName != null and map.connectionName != ''">
and (connection_name like concat('%', #{map.connectionName}, '%') or connection_phone like concat('%',
#{map.connectionPhone},
'%') or
license_num like concat('%', #{map.licenseNum}, '%'))
#{map.connectionPhone},
'%') or
license_num like concat('%', #{map.licenseNum}, '%'))
</if>
<if test="map.rescueStatus != null">
<choose>
@ -247,15 +248,15 @@
</select>
<select id="driverList" resultType="cn.iocoder.yudao.module.rescue.domain.DriverInfo">
SELECT su.id AS userId,
su.nickname AS nickName,
su.mobile AS phonenumber,
su.sex as sex,
su.avatar as avatar,
di.*
SELECT su.id AS userId,
su.nickname AS nickName,
su.mobile AS phonenumber,
su.sex as sex,
su.avatar as avatar,
di.*
FROM driver_info di
INNER JOIN system_users su ON di.user_id = su.id
AND su.deleted = '0'
INNER JOIN system_users su ON di.user_id = su.id
AND su.deleted = '0'
WHERE 1 = 1
<if test="map.nickName != null and map.nickName != ''">
and su.nickname like concat('%', #{map.nickName}, '%')
@ -280,17 +281,17 @@
<select id="driverListApp" resultType="cn.iocoder.yudao.module.rescue.dto.DriverInfo2Dto">
SELECT di.*,
su.nickname as real_name,
rci.rescue_car_num
su.nickname as real_name,
rci.rescue_car_num
FROM driver_info di
INNER JOIN system_users su ON di.user_id = su.id AND su.deleted = '0'
left join system_dept sd on sd.id = di.dept_id
inner join rescue_car_info rci on rci.possessor_id = di.id
INNER JOIN system_users su ON di.user_id = su.id AND su.deleted = '0'
left join system_dept sd on sd.id = di.dept_id
inner join rescue_car_info rci on rci.possessor_id = di.id
WHERE di.auth_status = '2'
<if test="searchValue != null and searchValue != ''">
and (su.nickname like concat('%', #{searchValue}, '%') or
di.phonenumber like concat('%', #{searchValue}, '%')
or rci.rescue_car_num like concat('%', #{searchValue}, '%'))
di.phonenumber like concat('%', #{searchValue}, '%')
or rci.rescue_car_num like concat('%', #{searchValue}, '%'))
</if>
order by di.create_time desc
</select>
@ -312,8 +313,8 @@
WHERE need_system = '0'
AND driver_id IS NULL
AND TIMESTAMPDIFF(
MINUTE, rescue_time,
NOW()) > 5
MINUTE, rescue_time,
NOW()) > 5
AND rescue_status = '2'
</update>
<select id="getOverTimeRescue" resultType="cn.iocoder.yudao.module.rescue.domain.RescueInfo">
@ -325,15 +326,15 @@
AND ri.rescue_status = '2'
GROUP BY ri.id
HAVING TIMESTAMPDIFF(
MINUTE, MAX(rdi.create_time),
NOW()) <![CDATA[>]]> 3
MINUTE, MAX(rdi.create_time),
NOW()) <![CDATA[>]]> 3
</select>
<select id="getRescueStatistics" resultType="java.util.Map">
SELECT IFNULL(sum(ri.rescue_status = '2' or ri.rescue_status = '3'), 0) as jyzNum,
IFNULL(sum(roi.order_status = '1'), 0) as dzfNum,
IFNULL(sum(ri.rescue_status = '6'), 0) as dqcNum,
IFNULL(sum(ri.rescue_status <![CDATA[>=]]> '5'), 0) as ywcNum,
IFNULL(sum(ri.is_wei_xiu = '1'), 0) as zwxNum
IFNULL(sum(ri.is_wei_xiu = '1'), 0) as zwxNum
FROM rescue_info ri
left join rescue_order_info roi on roi.rescue_info_id = ri.id
where ri.user_id = #{userId}
@ -341,17 +342,18 @@
</select>
<select id="getRescueStatisticsByAdmin" resultType="java.util.Map">
SELECT IFNULL(sum(ri.rescue_status = '2' or ri.rescue_status = '3'), 0) as jyzNum,
IFNULL(sum(roi.order_status = '1'), 0) as dzfNum,
IFNULL(sum(ri.rescue_status = '6'), 0) as dqcNum,
IFNULL(sum(ri.rescue_status <![CDATA[>=]]> '5'), 0) as ywcNum,
IFNULL(sum(ri.is_wei_xiu = '1'), 0) as zwxNum
IFNULL(sum(roi.order_status = '1'), 0) as dzfNum,
IFNULL(sum(ri.rescue_status = '6'), 0) as dqcNum,
IFNULL(sum(ri.rescue_status <![CDATA[>=]]> '5'), 0) as ywcNum,
IFNULL(sum(ri.is_wei_xiu = '1'), 0) as zwxNum
FROM rescue_info ri
left join rescue_order_info roi on roi.rescue_info_id = ri.id
left join rescue_order_info roi on roi.rescue_info_id = ri.id
where 1 = 1
<if test="map.deptList != null and map.deptList.size()>0">
and ri.dept_id in <foreach collection="map.deptList" separator="," item="item" open="(" close=")">
#{item}
</foreach>
and ri.dept_id in
<foreach collection="map.deptList" separator="," item="item" open="(" close=")">
#{item}
</foreach>
</if>
</select>
<delete id="deleteOtherInfo1">
@ -378,17 +380,17 @@
</select>
<select id="getRescueInfoByDriver" resultType="cn.iocoder.yudao.module.rescue.domain.RescueInfo">
SELECT ri.*,
roi.order_status,
roi.set_money,
roi.id as rescueOrderId,
roi.pay_money,
roi.pay_time
roi.order_status,
roi.set_money,
roi.id as rescueOrderId,
roi.pay_money,
roi.pay_time
FROM rescue_info ri
left join rescue_order_info roi on roi.rescue_info_id = ri.id
left join rescue_order_info roi on roi.rescue_info_id = ri.id
where driver_id is not null
<if test="map.rescueStart != null and map.rescueEnd != null">
and rescue_time between concat(#{map.rescueStart}, ' 00:00:00')
and concat(#{map.rescueEnd}, ' 23:59:59')
and concat(#{map.rescueEnd}, ' 23:59:59')
</if>
<if test="map.licenseNum != null">
and ri.license_num like concat('%', #{map.licenseNum}, '%')
@ -401,7 +403,7 @@
</if>
<if test="map.rescueStart != null and map.rescueEnd != null">
and rescue_time between concat(#{map.rescueStart}, ' 00:00:00')
and concat(#{map.rescueEnd}, ' 23:59:59')
and concat(#{map.rescueEnd}, ' 23:59:59')
</if>
<if test="map.driverName != null">
@ -442,53 +444,55 @@
ORDER BY sd.id desc
</select>
<select id="selectManageAnalyze" resultType="java.util.Map">
WITH rescue_types AS (
SELECT '1' AS rescue_type, '拖车' AS rescue_type_desc
UNION ALL SELECT '2', '送油'
UNION ALL SELECT '3', '搭电'
UNION ALL SELECT '4', '换台'
UNION ALL SELECT '5', '扣车'
)
SELECT
rt.rescue_type_desc AS rescueType,
COUNT(ri.rescue_type) AS typeCount,
ROUND((COUNT(ri.rescue_type) * 100.0 / NULLIF((SELECT COUNT(*) FROM rescue_info WHERE deleted = b'0' AND rescue_time BETWEEN #{startTime} AND #{endTime} AND tenant_id = #{tenantId}), 0)), 2) AS percentage
FROM
rescue_types rt
LEFT JOIN
rescue_info ri ON rt.rescue_type = ri.rescue_type
AND ri.rescue_time BETWEEN #{startTime} AND #{endTime}
AND ri.tenant_id = #{tenantId}
GROUP BY
rt.rescue_type_desc
ORDER BY
rt.rescue_type;
WITH rescue_types AS (SELECT '1' AS rescue_type, '拖车' AS rescue_type_desc
UNION ALL
SELECT '2', '送油'
UNION ALL
SELECT '3', '搭电'
UNION ALL
SELECT '4', '换台'
UNION ALL
SELECT '5', '扣车')
SELECT rt.rescue_type_desc AS rescueType,
COUNT(ri.rescue_type) AS typeCount,
ROUND((COUNT(ri.rescue_type) * 100.0 / NULLIF((SELECT COUNT(*)
FROM rescue_info
WHERE deleted = b'0'
AND rescue_time BETWEEN #{startTime} AND #{endTime}
AND tenant_id = #{tenantId}), 0)), 2) AS percentage
FROM rescue_types rt
LEFT JOIN
rescue_info ri ON rt.rescue_type = ri.rescue_type
AND ri.rescue_time BETWEEN #{startTime} AND #{endTime}
AND ri.tenant_id = #{tenantId}
GROUP BY rt.rescue_type_desc
ORDER BY rt.rescue_type;
</select>
<select id="selectDriverSort" resultType="java.util.Map">
SELECT
ROW_NUMBER() OVER (ORDER BY COALESCE(SUM(roi.pay_money), 0) DESC) AS sort,
su.nickname,
COALESCE(SUM(roi.set_money), 0) AS money,
COALESCE(COUNT(roi.id), 0) AS count
SELECT ROW_NUMBER() OVER (ORDER BY COALESCE(SUM(roi.pay_money), 0) DESC) AS sort, su.nickname,
COALESCE(SUM(roi.set_money), 0) AS money,
COALESCE(COUNT(roi.id), 0) AS count
FROM
driver_info di
LEFT JOIN
system_users su ON di.user_id = su.id
LEFT JOIN
LEFT JOIN
system_users su
ON di.user_id = su.id
LEFT JOIN
rescue_info ri ON di.id = ri.driver_id
LEFT JOIN
LEFT JOIN
rescue_order_info roi ON ri.id = roi.rescue_info_id
WHERE roi.pay_time BETWEEN #{startTime} AND #{endTime}
WHERE roi.pay_time BETWEEN #{startTime}
AND #{endTime}
GROUP BY
su.nickname,
di.id
ORDER BY
COALESCE(SUM(roi.set_money), 0) DESC;
COALESCE (SUM (roi.set_money), 0) DESC;
</select>
<select id="selectRescueOrderByRoad" resultType="java.util.Map">
select
COALESCE((select value from system_dict_data where dict_type = #{dictType} and id = ri.section_road),'其他') name,
count(1) as count
select COALESCE((select value from system_dict_data where dict_type = #{dictType} and id = ri.section_road),
'其他') name,
count(1) as count
from rescue_info ri
group by name;
</select>
@ -520,36 +524,26 @@
</where>
</select>
<select id="getAll" resultType="cn.iocoder.yudao.module.rescue.dto.DriverInfoDto">
SELECT su.id AS userId,
su.nickname AS nickName,
su.mobile AS phonenumber,
su.sex as sex,
su.avatar as avatar,
di.*
<select id="getAll" resultType="cn.iocoder.yudao.module.rescue.vo.DriverInfoExportVO">
SELECT su.username,
su.nickname,
su.mobile,
su.sex,
GROUP_CONCAT(DISTINCT sr2.name SEPARATOR ',') AS roleNames
FROM driver_info di
INNER JOIN system_users su ON di.user_id = su.id
AND su.deleted = '0'
WHERE 1 = 1
<if test="entity.nickName != null and entity.nickName != ''">
and su.nickname like concat('%', #{entity.nickName}, '%')
INNER JOIN system_users su ON di.user_id = su.id AND su.deleted = 0
LEFT JOIN system_user_role sr ON su.id = sr.user_id AND sr.deleted = 0
INNER JOIN system_role role ON role.id = sr.role_id AND role.deleted = 0 AND role.code = 'jysj'
LEFT JOIN system_role sr2 ON sr.role_id = sr2.id AND sr2.service_package_id = 'jiuyuan'
<if test="entity.status != null">
AND su.status = #{entity.status}
</if>
<if test="entity.phonenumber != null and entity.phonenumber != ''">
and su.mobile like concat('%', #{entity.phonenumber}, '%')
<if test="entity.nickname != null">
AND (su.nickname like CONCAT('%',#{entity.nickname},'%') OR su.username like
CONCAT('%',#{entity.nickname},'%'))
</if>
<if test="entity.driveStatus != null and entity.driveStatus != ''">
and di.driver_status = #{entity.driveStatus}
</if>
<if test="entity.authStatus != null and entity.authStatus != ''">
and di.auth_status = #{entity.authStatus}
</if>
<if test="entity.carType != null and entity.carType != ''">
and di.car_type = #{entity.carType}
</if>
<if test="entity.carLicenseNum != null and entity.carLicenseNum != ''">
and di.car_license_num like concat('%', #{entity.carLicenseNum}, '%')
</if>
order by di.create_time desc
GROUP BY su.username, su.nickname, su.mobile, su.sex
ORDER BY su.nickname
</select>

View File

@ -104,6 +104,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="role.nickname != null">
AND (su.nickname like CONCAT('%',#{role.nickname},'%') OR su.username like CONCAT('%',#{role.nickname},'%'))
</if>
<if test="role.status != null">
AND su.status = #{role.status}
</if>
</where>
GROUP BY
su.id, su.username, su.nickname, su.user_type, su.remark,