zyp 3 days ago
parent
commit
f2f648730d

+ 604 - 0
fs-user-course/src/main/java/com/fs/course/controller/CommonController.java

@@ -0,0 +1,604 @@
+package com.fs.course.controller;
+
+
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
+import com.baidubce.appbuilder.model.dataset.DocumentListResponse;
+import com.fs.ai.service.IBaiduAIService;
+import com.fs.ai.vo.BaiduAIMsgResultVO;
+import com.fs.bdAdv.domain.FsAdvSem;
+import com.fs.bdAdv.service.IFsAdvSemService;
+import com.fs.chat.config.WxConfig;
+import com.fs.chat.domain.ChatRole;
+import com.fs.chat.service.IChatRoleService;
+import com.fs.common.config.FSConfig;
+import com.fs.common.constant.Constants;
+import com.fs.common.core.domain.AjaxResult;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.redis.RedisCache;
+import com.fs.common.exception.file.OssException;
+import com.fs.common.utils.file.FileUploadUtils;
+import com.fs.common.utils.http.HttpUtils;
+import com.fs.common.utils.sign.Md5Utils;
+import com.fs.core.utils.OrderCodeUtils;
+import com.fs.course.config.CourseConfig;
+import com.fs.course.param.SignParam;
+import com.fs.course.service.IHuaweiVodService;
+import com.fs.course.utils.CityTreeUtil;
+import com.fs.course.utils.JwtUtils;
+import com.fs.course.vo.CityVO;
+import com.fs.event.TemplateBean;
+import com.fs.event.TemplateEvent;
+import com.fs.event.TemplateListenEnum;
+import com.fs.event.WeixinTemplateService;
+import com.fs.framework.config.ServerConfig;
+import com.fs.his.config.FsSysConfig;
+import com.fs.his.domain.*;
+import com.fs.his.param.FsInquiryOrderFinishParam;
+import com.fs.his.service.*;
+import com.fs.his.utils.ConfigUtil;
+import com.fs.im.dto.*;
+import com.fs.im.service.IImService;
+import com.fs.qw.service.IQwAppContactWayService;
+import com.fs.system.oss.CloudStorageService;
+import com.fs.system.oss.OSSFactory;
+import com.fs.system.service.ISysConfigService;
+import com.fs.system.service.ISysDictDataService;
+import com.fs.system.vo.DictVO;
+import com.google.common.collect.Lists;
+import com.huaweicloud.sdk.vod.v1.model.BaseInfo;
+import com.tencentyun.TLSSigAPIv2;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import static com.fs.common.utils.SecurityUtils.getUserId;
+
+
+@Api("公共接口")
+@RestController
+@RequestMapping(value="/app/common")
+public class CommonController {
+	@Autowired
+	private RedisCache redisCache;
+	@Autowired
+	private IFsUserService userService;
+	@Autowired
+	private ApplicationEventPublisher publisher;
+	@Autowired
+	JwtUtils jwtUtils;
+	@Autowired
+	private ISysDictDataService dictDataService;
+	@Autowired
+	ConfigUtil configUtil;
+	@Autowired
+	private ISysConfigService configService;
+	@Autowired
+	private IFsCityService cityService;
+	@Autowired
+	private IFsDepartmentService departmentService;
+
+	@Autowired
+	private IFsHospitalService hospitalService;
+	@Autowired
+	private IImService imService;
+	@Autowired
+	private IFsInquiryOrderReportService reportService;
+	@Autowired
+	private IFsInquiryOrderService inquiryOrderService;
+	@Autowired
+	private IFsDoctorService doctorService;
+	@Autowired
+	private IFsFollowService followService;
+	@Autowired
+	private IBaiduAIService baiduAIService;
+	@Autowired
+	private IChatRoleService chatRoleService;
+	@Autowired
+	private WeixinTemplateService weixinTemplateService;
+	@Autowired
+	private ServerConfig serverConfig;
+	@Autowired
+	private IFsAppVersionService appVersionService;
+	@Autowired
+	private IHuaweiVodService huaweiVodService;
+	@Autowired
+	private IFsAdvSemService advSemService;
+
+	@Autowired
+	private IQwAppContactWayService qwAppContactWayService;
+
+//	@Autowired
+//	private RocketMQTemplate rocketMQTemplate;
+//
+//	@ApiOperation("testMqSend")
+//	@GetMapping(value = "/testMqSend")
+//	public R testMqSend()
+//	{
+//		rocketMQTemplate.syncSend("my-topic", MessageBuilder.withPayload(123).build());
+//		return R.ok();
+//	}
+
+
+	@ApiOperation("excel")
+	@GetMapping(value = "/exportExcel")
+	public void exportExcel() throws Exception {
+		String filePath="c://phone.xlsx";
+		FileInputStream inputStream = new FileInputStream(filePath);
+		Workbook workbook = new XSSFWorkbook(inputStream);
+		Sheet sheet = workbook.getSheetAt(0);
+		List<String> phones=new ArrayList<>();
+		// 遍历行
+		Iterator<Row> rowIterator = sheet.iterator();
+		int index1=0;
+		while (rowIterator.hasNext()) {
+			Row row = rowIterator.next();
+
+			// 遍历列
+			if(index1>0){
+				Iterator<Cell> cellIterator = row.iterator();
+				while (cellIterator.hasNext()) {
+					Cell cell = cellIterator.next();
+					// 读取单元格数据
+					try
+					{
+
+						if(StringUtils.isNotEmpty(cell.toString())){
+							String cellValue =cell.toString();
+							phones.add(cellValue);
+						}
+
+					}
+					catch (Exception e){
+
+
+					}
+
+				}
+
+			}
+			index1++;
+
+		}
+		workbook.close();
+		// 写入Excel数据
+		Workbook workbookOut = new XSSFWorkbook();
+		Sheet sheetOut = workbookOut.createSheet("NewSheet");
+		int index=0;
+		for(String p :phones){
+			Row row = sheetOut.createRow(index);
+			Cell cell1 = row.createCell(0);
+			cell1.setCellValue(p);
+			Cell cell2 = row.createCell(1);
+			cell2.setCellValue(Md5Utils.hash(p));
+			index++;
+		}
+
+		// 写入到文件
+		FileOutputStream outputStream = new FileOutputStream("C://output.xlsx");
+		workbookOut.write(outputStream);
+		workbookOut.close();
+		outputStream.close();
+
+	}
+	@ApiOperation("aiAddDocument")
+	@PostMapping("/aiAddDocument")
+	public R aiAddDocument(@RequestParam("file") MultipartFile file) throws Exception
+	{
+
+		if (file.isEmpty())
+		{
+			throw new OssException("上传文件不能为空");
+		}
+		// 上传文件路径
+		String filePath = FSConfig.getUploadPath();
+		// 上传并返回新文件名称
+		String fileName = FileUploadUtils.upload(filePath, file);
+		String url =filePath + fileName.replaceAll("/profile/upload","");
+
+		// 上传文件
+		String[] documentIds =baiduAIService.addDocument("88c6a6b0-0f75-4f47-ab27-fae27c74746d",url);
+
+		return R.ok().put("data",documentIds);
+	}
+	@ApiOperation("aiGetDocments")
+	@GetMapping(value = "/aiGetDocments")
+	public R aiGetDocments()
+	{
+		DocumentListResponse document =baiduAIService.getDocument("88c6a6b0-0f75-4f47-ab27-fae27c74746d",1,10,"");
+		return R.ok().put("data",document);
+//		BaiduAITokenVO vo=baiduAIService.getToken();
+//		BaiduAIMsgVO info=baiduAIService.callAI(msg);
+//		return R.ok().put("data",info);
+	}
+	@ApiOperation("aiRun")
+	@GetMapping(value = "/aiRun")
+	public R aiRun(@RequestParam(value = "msg", required = false) String msg )
+	{
+		ChatRole chatRole=chatRoleService.selectChatRoleByKfId("wkb56IcAAAY3el_KSzhhjslPAATDmd_g");
+		if(chatRole!=null){
+			//获取配置
+			WxConfig wxConfig=JSONUtil.toBean(chatRole.getModeConfigJson(), WxConfig.class);
+			BaiduAIMsgResultVO vo=baiduAIService.run(wxConfig.getAppId(),null,msg);
+			return R.ok().put("data",vo);
+		}
+		else{
+			//未配置客服
+			return R.error();
+		}
+
+
+//		BaiduAITokenVO vo=baiduAIService.getToken();
+//		BaiduAIMsgVO info=baiduAIService.callAI(msg);
+//		return R.ok().put("data",info);
+	}
+	@ApiOperation("测试")
+	@GetMapping(value = "/getTest")
+	public AjaxResult getTest(@RequestParam(value = "fid", required = false) Long fid)
+	{
+		FsFollow follow=followService.selectFsFollowByFollowId(fid);
+		MsgDTO msgDTO3=new MsgDTO();
+		MsgCustomDTO customDTO3=new MsgCustomDTO();
+		customDTO3.setType("startFollow");
+		customDTO3.setOrderType(2);
+		customDTO3.setFollowId(follow.getFollowId().toString());
+		customDTO3.setOrderId(follow.getInquiryOrderId().toString());
+		customDTO3.setImType(2);
+		msgDTO3.setCloudCustomData(JSONUtil.toJsonStr(customDTO3));
+		msgDTO3.setFrom_Account("U-"+follow.getUserId());
+		msgDTO3.setTo_Account("D-"+follow.getDoctorId()	);
+		List<MsgDataDTO> msgs3=new ArrayList<>();
+		MsgDataDTO msg3=new MsgDataDTO();
+		String ext= JSONUtil.toJsonStr(follow);
+		msg3.setMsgContent(new MsgDataFormatDTO("follow",ext,follow.getFollowId().toString()));
+		msg3.setMsgType("TIMCustomElem");//TIMCustomElem
+		msgs3.add(msg3);
+		msgDTO3.setMsgBody(msgs3);
+		MsgResponseDTO msgResponseDTO3 = imService.sendMsg(msgDTO3);
+		return AjaxResult.success("");
+	}
+
+	@GetMapping(value = "/testPush")
+	@ApiOperation("测试推送")
+	public R testPush(@RequestParam(value = "uid", required = false) Long uid)
+	{
+		TemplateBean templateBean = TemplateBean.builder()
+				.orderId("111")
+				.title("订单已取消")
+				.remark("您的订单已取消")
+				.uid(uid)
+				.templateType(TemplateListenEnum.TYPE_1.getValue())
+				.build();
+		publisher.publishEvent(new TemplateEvent(this, templateBean));
+		return  R.ok();
+
+	}
+
+
+	@ApiOperation("获取数据字典")
+	@GetMapping("/getDictByKey")
+    @Cacheable(value="dicts", key="#key")
+	public R getDictByKey(@RequestParam(value = "key", required = false) String key){
+		List<DictVO> dicts=dictDataService.selectDictDataListByType(key);
+		return R.ok().put("data",dicts);
+	}
+
+	@GetMapping(value = "/getConfigByKey")
+	@ApiOperation("获取配置")
+	public R getConfigByKey(@RequestParam(value = "key", required = false) String key)
+	{
+		String config=configService.selectConfigByKey(key);
+		return  R.ok().put("data",config);
+
+	}
+
+
+	@PostMapping("uploadOSS")
+	public R uploadOSS(@RequestParam("file") MultipartFile file) throws Exception
+	{
+
+		if (file.isEmpty())
+		{
+			throw new OssException("上传文件不能为空");
+		}
+		// 上传文件
+		String fileName = file.getOriginalFilename();
+		String suffix = fileName.substring(fileName.lastIndexOf("."));
+		CloudStorageService storage = OSSFactory.build();
+		String url = storage.uploadSuffix(file.getBytes(), suffix);
+		return R.ok().put("url",url);
+	}
+
+	@PostMapping("/uploadHuaWeiVod")
+	public R uploadHuaWeiVod()
+	{
+		// 本地要上传的媒资路径
+		String filePath = "D:\\WeChat\\file\\WeChat Files\\wxid_cnp9jj0rcnr821\\FileStorage\\Video\\2024-07\\4faef56eb3d8c22f33f5d619a20232fb.mp4";
+
+		// 上传媒资文件
+//		huaweiVodService.uploadPartFile(filePath);
+		return R.ok();
+	}
+
+	@GetMapping("/getHuaWeiUrl")
+	public R getHuaWeiUrl()
+	{
+		BaseInfo data = huaweiVodService.getBaseInfo("5117c9850a69ffc7cddd3cb528c546d6");
+		return R.ok().put("data",data);
+	}
+
+	@GetMapping(value = "/testInquiryOrder")
+	@ApiOperation("测试开药结束")
+	public R testInquiryOrder()
+	{
+		FsInquiryOrderFinishParam param=new FsInquiryOrderFinishParam();
+		param.setOrderId(740653l);
+		param.setDoctorId(113l);
+		R  r=inquiryOrderService.finishOrder(param);
+		return r;
+	}
+
+	@GetMapping(value = "/getTlsSig")
+	@ApiOperation("获取腾讯云签名")
+	public R getTlsSig(@Validated SignParam signParam)
+	{
+		FsSysConfig fsConfig = configUtil.getSysConfig();
+		TLSSigAPIv2 api = new TLSSigAPIv2(fsConfig.getSdkAppId(), fsConfig.getSdkAppKey());
+		String sign=api.genUserSig(signParam.getUserId(),180*86400);
+		return R.ok().put("data",sign);
+	}
+	@GetMapping(value = "/testSend")
+	@ApiOperation("testSend")
+	public R testSend( )
+	{
+//		MsgDTO msgDTO=new MsgDTO();
+//		msgDTO.setFrom_Account("D-6");
+//		msgDTO.setTo_Account("U-40487");
+//		List<MsgDataDTO> msgs=new ArrayList<>();
+//		MsgDataDTO msg=new MsgDataDTO();
+//		FsInquiryOrderReport report=reportService.selectFsInquiryOrderReportByOrderId(252l);
+//		String ext= JSONUtil.toJsonStr(report);
+//		String orderId="252";
+//		msg.setMsgContent(new MsgDataFormatDTO("report",ext,orderId));
+//		msg.setMsgType("TIMCustomElem");//TIMCustomElem
+//		msgs.add(msg);
+//		msgDTO.setMsgBody(msgs);
+
+		MsgDTO msgDTO=new MsgDTO();
+
+		MsgCustomDTO customDTO=new MsgCustomDTO();
+		customDTO.setType("startInquiry");
+		customDTO.setOrderId("279");
+		customDTO.setFollowId("1");
+		customDTO.setImType(1);
+		msgDTO.setCloudCustomData(JSONUtil.toJsonStr(customDTO));
+
+
+		msgDTO.setTo_Account("D-63");
+		msgDTO.setFrom_Account("U-40479");
+		List<MsgDataDTO> msgs=new ArrayList<>();
+		MsgDataDTO msg=new MsgDataDTO();
+		InquiryOrderMsgDTO startDTO=new InquiryOrderMsgDTO();
+		startDTO.setTitle("张医生为您服务");
+		String ext= JSONUtil.toJsonStr(startDTO);
+		String orderId="231";
+		msg.setMsgContent(new MsgDataFormatDTO("test"));
+		msg.setMsgType("TIMTextElem");//TIMCustomElem
+		msgs.add(msg);
+		msgDTO.setMsgBody(msgs);
+		imService.sendMsg(msgDTO);
+		return R.ok();
+	}
+
+	@ApiOperation("获取城市数据")
+	@GetMapping("/getCitys")
+	@Cacheable("cityData")
+	public R getCitys(){
+		List<FsCity> list=cityService.selectFsCityList(new FsCity());
+		List<CityVO> cityVOS = Lists.newArrayList();
+		for (FsCity city : list){
+			CityVO cityVO = new CityVO();
+			cityVO.setV(city.getCityId());
+			cityVO.setN(city.getCityName());
+			cityVO.setPid(city.getParentId());
+			cityVOS.add(cityVO);
+		}
+		return R.ok().put("data", CityTreeUtil.list2TreeConverter(cityVOS, "0"));
+
+	}
+
+	@ApiOperation("获取医院列表")
+	@GetMapping("/getHospitalList")
+	public R getHospitalList(){
+		FsHospital map=new FsHospital();
+		map.setStatus(1);
+		List<FsHospital> list=hospitalService.selectFsHospitalList(map);
+		return R.ok().put("data",list);
+	}
+	@ApiOperation("获取科室列表")
+	@GetMapping("/getDepartmentList")
+	public R getDepartmentList(){
+		FsDepartment map=new FsDepartment();
+		map.setStatus(1);
+		List<FsDepartment> list=departmentService.selectFsDepartmentList(map);
+		return R.ok().put("data",list);
+	}
+
+	@ApiOperation("获取最新版本")
+	@GetMapping("/getAppVersion")
+	public R getAppVersion(@RequestParam("type")Integer type)
+	{
+		FsAppVersion version = appVersionService.getNewUserAppVersion(type);
+		return R.ok().put("data",version);
+	}
+	@ApiOperation("test")
+	@GetMapping("/test")
+	public R test()
+	{
+		String orderCode =  OrderCodeUtils.getOrderSn();
+		if(com.fs.common.utils.StringUtils.isEmpty(orderCode)) {
+			return R.error("订单生成失败,请重试");
+		}
+		return R.ok(orderCode);
+
+	}
+
+	@ApiOperation("百度营销监控地址")
+	@GetMapping(value = "/bdNotice")
+	public AjaxResult notice(
+			@RequestParam(name = "imei_md5", required = false) String imeiMd5,
+			@RequestParam(name = "oaid", required = false) String oaid,
+			@RequestParam(name = "ip", required = false) String ip,
+			@RequestParam(name = "ua", required = false) String ua,
+			@RequestParam(name = "model", required = false) String model,
+			@RequestParam(name = "os_version", required = false) String osVersion,
+			@RequestParam(name = "os_type", required = false) String os_type,
+			@RequestParam(name = "userid", required = false) String userId,
+			@RequestParam(name = "android_id_md5", required = false) String androidMd5,
+			@RequestParam(name = "pid", required = false) String planId,
+			@RequestParam(name = "uid", required = false) String userUid,
+			@RequestParam(name = "aid", required = false) String ideaId,
+			@RequestParam(name = "ts", required = false) Long ts,
+			@RequestParam(name = "click_id", required = false) String clickId,
+			@RequestParam(name = "callback_url", required = false) String callbackUrl) {
+		// 处理接收到的参数
+		StringBuilder response = new StringBuilder("");
+		response.append("\nIMEI MD5: ").append(imeiMd5);
+		response.append("\nIP: ").append(ip);
+		response.append("\nTimestamp: ").append(ts);
+		response.append("\nUser ID: ").append(userId);
+		response.append("\nPlan ID: ").append(planId);
+		response.append("\nUser UID: ").append(userUid);
+		response.append("\nIdea ID: ").append(ideaId);
+		response.append("\nClick ID: ").append(clickId);
+		response.append("\nCallback URL: ").append(callbackUrl);
+		System.out.println("---qxj bdNotice params:"+response.toString());
+		//if(StringUtils.isNotEmpty(clickId)){
+		FsAdvSem advSem=new FsAdvSem();
+		advSem.setImei(imeiMd5);
+		advSem.setOaid(oaid);
+		advSem.setIp(ip);
+		advSem.setCmdType(-1);//未操作
+		//advSem.setUa(ua);
+		advSem.setModel(model);
+		advSem.setOsType(Integer.parseInt(os_type));
+		advSem.setCallbackUrl(callbackUrl);
+		advSem.setClickId(clickId);
+		advSemService.insertFsAdvSem(advSem);
+		//}
+		return AjaxResult.success("ok");
+	}
+
+
+	@ApiOperation("百度营销回调")
+	@GetMapping(value = "/bdCallBack")
+	public AjaxResult bdCallBack(
+			@RequestParam(name = "oaid", required = false) String oaid,
+			@RequestParam(name = "ip", required = false) String ip,
+			@RequestParam(name = "ua", required = false) String ua,
+			@RequestParam(name = "aType", required = false) String aType,
+			@RequestParam(name = "aValue", required = false) String aValue,
+			@RequestParam(name = "model", required = false) String model,
+			@RequestParam(name = "osType", required = false) Integer osType,
+			@RequestParam(name = "userId", required = false)Long userId) {
+
+		FsAdvSem advSem=null;
+		String callBackUrl="";
+		String md5Sign;
+		if(StringUtils.isNotEmpty(oaid)){
+			advSem=advSemService.selectFsAdvSemByOaid(oaid);
+			if(advSem==null){
+				advSem=new FsAdvSem();
+			}
+			if(StringUtils.isNotEmpty(advSem.getCallbackUrl())){
+				callBackUrl=advSem.getCallbackUrl()+"&join_type=oaid";
+			}
+		}else{
+			advSem=advSemService.selectFsAdvSemByModel(model,osType);
+			if(advSem==null){
+				advSem=new FsAdvSem();
+			}
+			if(StringUtils.isNotEmpty(advSem.getCallbackUrl())){
+				callBackUrl=advSem.getCallbackUrl()+"&join_type=model";
+			}
+		}
+		if(aType.contentEquals("activate")){
+			advSem.setCmdType(0);//激活
+		}
+		if(aType.contentEquals("register")){
+			advSem.setCmdType(1);//注册
+		}
+		if(aType.contentEquals("orders")){
+			advSem.setCmdType(2); //下单
+		}
+		if(userId!=null){
+			advSem.setUserId(userId);
+		}
+		advSem.setAType(aType);
+		if(advSem!=null && advSem.getId()!=null){
+			advSemService.updateFsAdvSem(advSem);
+			String rspStr="";
+			if(StringUtils.isNotEmpty(callBackUrl)){
+				callBackUrl=callBackUrl.replace("{{ATYPE}}",aType).replace("{{AVALUE}}",aValue);
+				String akey="NTk0ODMyODM=";
+				md5Sign= Md5Utils.hash(callBackUrl+akey);
+				callBackUrl=callBackUrl+"&sign="+md5Sign;
+				rspStr = HttpUtils.sendGet(callBackUrl, "&sign="+md5Sign, Constants.UTF8);
+				//JSONObject obj = JSONObject.parseObject(rspStr);
+				//String errorCode = obj.getString("error_code");
+			}
+		}else{
+			//advSem.setImei(imeiMd5);
+			advSem.setOaid(oaid);
+			advSem.setIp(ip);
+			advSem.setCmdType(0);//未操作
+			//advSem.setUa(ua);
+			advSem.setModel(model);
+			advSem.setOsType(osType);
+			advSemService.insertFsAdvSem(advSem);
+		}
+		return AjaxResult.success("ok");
+	}
+
+
+	@ApiOperation("获取APP客服活码")
+	@GetMapping("/getAppContactWay")
+	public R getAppContactWay()
+	{
+		Long userId = getUserId();
+
+		String appContactWayImgCode = qwAppContactWayService.getAppContactWayImgCode(userId);
+		return R.ok().put("data",appContactWayImgCode);
+	}
+
+	@GetMapping("/getRealLinkDomainName")
+	public R getRealLinkDomainName( )
+	{
+		String json = configService.selectConfigByKey("course.config");
+		CourseConfig config = JSON.parseObject(json, CourseConfig.class);
+		if (config!=null&& com.fs.common.utils.StringUtils.isNotEmpty(config.getRealLinkDomainName())){
+			return R.ok().put("data",config.getRealLinkDomainName());
+		}
+		return R.error("获取域名失败,请检查后台配置!");
+	}
+
+
+
+}

+ 14 - 0
fs-user-course/src/main/java/com/fs/course/param/SignParam.java

@@ -0,0 +1,14 @@
+package com.fs.course.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+
+@Data
+public class SignParam {
+    @NotBlank(message = "请填写USERID")
+    @ApiModelProperty(value = "userId")
+    private String userId;
+}

+ 85 - 0
fs-user-course/src/main/java/com/fs/course/utils/CityTreeUtil.java

@@ -0,0 +1,85 @@
+package com.fs.course.utils;
+import com.fs.course.vo.CityVO;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @ClassName 树形工具类
+ **/
+public class CityTreeUtil {
+    /**
+     * 获得指定节点下所有归档
+     *
+     * @param list
+     * @param parentId
+     * @return
+     */
+    public static List<CityVO> list2TreeConverter(List<CityVO> list, String parentId) {
+        List<CityVO> returnList = new ArrayList<>();
+
+        for (CityVO res : list) {
+            //判断对象是否为根节点
+
+            if (res.getPid().equals(parentId)) {
+                //该节点为根节点,开始递归
+
+                //通过递归为节点设置childList
+                recursionFn(list, res);
+
+                returnList.add(res);
+            }
+        }
+
+        return returnList;
+    }
+
+    /**
+     * 递归列表
+     * 通过递归,给指定t节点设置childList
+     *
+     * @param list
+     * @param t
+     */
+    public static void recursionFn(List<CityVO> list, CityVO t) {
+        //只能获取当前t节点的子节点集,并不是所有子节点集
+        List<CityVO> childsList = getChildList(list, t);
+
+        //设置他的子集对象集
+        t.setC(childsList);
+
+        //迭代子集对象集
+
+        //遍历完,则退出递归
+        for (CityVO nextChild : childsList) {
+
+            //判断子集对象是否还有子节点
+            if (!CollectionUtils.isEmpty(childsList)) {
+                //有下一个子节点,继续递归
+                recursionFn(list, nextChild);
+            }
+        }
+    }
+
+    /**
+     * 获得指定节点下的所有子节点
+     *
+     * @param list
+     * @param t
+     * @return
+     */
+    public static List<CityVO> getChildList(List<CityVO> list, CityVO t) {
+        List<CityVO> childsList = new ArrayList<>();
+        //遍历集合元素,如果元素的Parentid==指定元素的id,则说明是该元素的子节点
+        for (CityVO t1 : list) {
+            if (t1.getPid().equals(t.getV())) {
+                childsList.add(t1);
+            }
+        }
+
+        return childsList;
+    }
+
+
+}