孙永军 1 рік тому
батько
коміт
96f67dab63

+ 23 - 3
src/main/java/com/smcic/api/conference/controller/ConferenceLiveController.java

@@ -1,9 +1,13 @@
 package com.smcic.api.conference.controller;
 
 
-import org.springframework.web.bind.annotation.RequestMapping;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.smcic.api.conference.entity.ConferenceLive;
+import com.smcic.api.conference.service.impl.ConferenceLiveServiceImpl;
+import org.springframework.web.bind.annotation.*;
 
-import org.springframework.web.bind.annotation.RestController;
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
 
 /**
  * <p>
@@ -14,7 +18,23 @@ import org.springframework.web.bind.annotation.RestController;
  * @since 2024-03-27
  */
 @RestController
-@RequestMapping("/conference/conference-live")
+@RequestMapping("/conference/live")
 public class ConferenceLiveController {
 
+    @Resource
+    private ConferenceLiveServiceImpl conferenceLiveService;
+
+    @RequestMapping("create")
+    public ConferenceLive create(@RequestBody ConferenceLive conferenceLive) {
+        conferenceLive.setCreateTime( LocalDateTime.now() );
+        conferenceLiveService.save(conferenceLive);
+        return conferenceLive;
+    }
+
+    @RequestMapping("list/{id}")
+    public Page<ConferenceLive> list(@PathVariable( "id" ) Long id,
+                                     @RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
+                                     @RequestParam(value = "pageSize", required = false, defaultValue = "20") Integer size) {
+        return conferenceLiveService.livePage(id, page, size);
+    }
 }

+ 19 - 3
src/main/java/com/smcic/api/conference/controller/ConferenceSubscriptionController.java

@@ -1,9 +1,12 @@
 package com.smcic.api.conference.controller;
 
 
-import org.springframework.web.bind.annotation.RequestMapping;
+import com.smcic.api.conference.entity.ConferenceSubscription;
+import com.smcic.api.conference.service.impl.ConferenceSubscriptionServiceImpl;
+import org.springframework.web.bind.annotation.*;
 
-import org.springframework.web.bind.annotation.RestController;
+import javax.annotation.Resource;
+import java.util.List;
 
 /**
  * <p>
@@ -14,7 +17,20 @@ import org.springframework.web.bind.annotation.RestController;
  * @since 2024-03-27
  */
 @RestController
-@RequestMapping("/conference/conference-subscription")
+@RequestMapping("/conference/subscription")
 public class ConferenceSubscriptionController {
 
+    @Resource
+    private ConferenceSubscriptionServiceImpl subscriptionService;
+
+    @PostMapping("create")
+    public void createSubscription(@RequestBody ConferenceSubscription conferenceSubscription, @RequestParam("code") String code) {
+        subscriptionService.create( conferenceSubscription, code);
+    }
+
+    @GetMapping("get/{id}")
+    public List<ConferenceSubscription> getSubscription(@PathVariable("id") Long id, @RequestParam("code") String code) {
+        return subscriptionService.getByCode( id, code);
+    }
+
 }

+ 21 - 2
src/main/java/com/smcic/api/conference/controller/UserThirdController.java

@@ -1,9 +1,14 @@
 package com.smcic.api.conference.controller;
 
 
-import org.springframework.web.bind.annotation.RequestMapping;
+import com.google.common.collect.ImmutableMap;
+import com.smcic.api.conference.entity.UserThird;
+import com.smcic.api.conference.service.impl.UserThirdServiceImpl;
+import org.springframework.web.bind.annotation.*;
 
-import org.springframework.web.bind.annotation.RestController;
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.util.Map;
 
 /**
  * <p>
@@ -17,4 +22,18 @@ import org.springframework.web.bind.annotation.RestController;
 @RequestMapping("/conference/user-third")
 public class UserThirdController {
 
+    @Resource
+    private UserThirdServiceImpl userThirdService;
+
+    @GetMapping("getPhone/{id}")
+    public Map<String, String> getPhone(@PathVariable("id") Long id, @RequestParam("code") String code) {
+        return ImmutableMap.of("phone", userThirdService.getPhone(id, code)) ;
+    }
+
+    @PostMapping("create")
+    public void create(@RequestBody UserThird userThird) {
+        userThird.setCreateTime(LocalDateTime.now());
+        userThirdService.save(userThird);
+    }
+
 }

+ 39 - 0
src/main/java/com/smcic/api/conference/dto/WxPhoneDTO.java

@@ -0,0 +1,39 @@
+package com.smcic.api.conference.dto;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor
+@Data
+public class WxPhoneDTO {
+
+    @JSONField(name = "errcode")
+    private Integer errcode;
+    @JSONField(name = "errmsg")
+    private String errmsg;
+    @JSONField(name = "phone_info")
+    private PhoneInfoDTO phoneInfo;
+
+    @NoArgsConstructor
+    @Data
+    public static class PhoneInfoDTO {
+        @JSONField(name = "phoneNumber")
+        private String phoneNumber;
+        @JSONField(name = "purePhoneNumber")
+        private String purePhoneNumber;
+        @JSONField(name = "countryCode")
+        private String countryCode;
+        @JSONField(name = "watermark")
+        private WatermarkDTO watermark;
+
+        @NoArgsConstructor
+        @Data
+        public static class WatermarkDTO {
+            @JSONField(name = "timestamp")
+            private Integer timestamp;
+            @JSONField(name = "appid")
+            private String appid;
+        }
+    }
+}

+ 2 - 0
src/main/java/com/smcic/api/conference/entity/Conference.java

@@ -83,5 +83,7 @@ public class Conference implements Serializable {
     @JsonFormat( pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime endTime;
 
+    private String wxVideoUid;
+
 
 }

+ 7 - 2
src/main/java/com/smcic/api/conference/entity/ConferenceLive.java

@@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 import java.time.LocalDateTime;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -34,18 +36,21 @@ public class ConferenceLive implements Serializable {
 
     private String liveDesc;
 
-    private String conver;
+    private String cover;
+
+    private String fnderUid;
 
     /**
      * 直播间视频号id
      */
     private String roomId;
 
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime liveTime;
 
     private Integer liveDuration;
 
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime createTime;
 
-
 }

+ 4 - 1
src/main/java/com/smcic/api/conference/entity/ConferenceSubscription.java

@@ -1,5 +1,7 @@
 package com.smcic.api.conference.entity;
 
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 import lombok.Getter;
@@ -20,11 +22,12 @@ public class ConferenceSubscription implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
+    @TableId(value = "id",  type = IdType.AUTO)
     private Long id;
 
     private Long conferenceId;
 
-    private Long uid;
+    private String phone;
 
     private Long agendaId;
 

+ 6 - 3
src/main/java/com/smcic/api/conference/entity/UserThird.java

@@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import java.io.Serializable;
 import java.time.LocalDateTime;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -23,9 +25,6 @@ public class UserThird implements Serializable {
 
     private static final long serialVersionUID = 1L;
 
-    @TableId(value = "id", type = IdType.AUTO)
-    private Long id;
-
     private String openId;
 
     /**
@@ -37,6 +36,8 @@ public class UserThird implements Serializable {
 
     private String photo;
 
+
+    @TableId(value = "id")
     private String phone;
 
     private String email;
@@ -56,8 +57,10 @@ public class UserThird implements Serializable {
      */
     private String position;
 
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime createTime;
 
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private LocalDateTime lastLoginTime;
 
     private Integer status;

+ 10 - 0
src/main/java/com/smcic/api/conference/service/impl/ConferenceLiveServiceImpl.java

@@ -1,6 +1,9 @@
 package com.smcic.api.conference.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.smcic.api.conference.entity.ConferenceLive;
+import com.smcic.api.conference.entity.ConferenceLiveVideo;
 import com.smcic.api.conference.mapper.ConferenceLiveMapper;
 import com.smcic.api.conference.service.IConferenceLiveService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -17,4 +20,11 @@ import org.springframework.stereotype.Service;
 @Service
 public class ConferenceLiveServiceImpl extends ServiceImpl<ConferenceLiveMapper, ConferenceLive> implements IConferenceLiveService {
 
+    public Page<ConferenceLive> livePage(Long id, Integer page, Integer size) {
+        Page<ConferenceLive> page1 = new Page<>(page, size);
+
+        LambdaQueryWrapper<ConferenceLive> wrapper = new LambdaQueryWrapper<>();
+        return this.baseMapper.selectPage(page1,
+                wrapper.eq(ConferenceLive::getAgendaId, id).orderByDesc(ConferenceLive::getId));
+    }
 }

+ 26 - 0
src/main/java/com/smcic/api/conference/service/impl/ConferenceSubscriptionServiceImpl.java

@@ -4,8 +4,14 @@ import com.smcic.api.conference.entity.ConferenceSubscription;
 import com.smcic.api.conference.mapper.ConferenceSubscriptionMapper;
 import com.smcic.api.conference.service.IConferenceSubscriptionService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.smcic.core.advice.APIException;
+import org.apache.http.util.TextUtils;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
+import java.util.List;
+
 /**
  * <p>
  *  服务实现类
@@ -16,5 +22,25 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class ConferenceSubscriptionServiceImpl extends ServiceImpl<ConferenceSubscriptionMapper, ConferenceSubscription> implements IConferenceSubscriptionService {
+    @Resource
+    private RedisTemplate<String, String> redisTemplate;
+
+    public ConferenceSubscription create(ConferenceSubscription conferenceSubscription, String code){
+        String phone =  redisTemplate.opsForValue().get("WX_CODE_" + code); // 从redis中获取手机号
+        if (TextUtils.isEmpty(phone)) {
+            throw new APIException("账号已过期,请重新登陆");
+        }
+        conferenceSubscription.setPhone(phone);
+        save(conferenceSubscription);
+        return conferenceSubscription;
+    }
 
+    public List<ConferenceSubscription> getByCode(Long id, String code){
+        String phone =  redisTemplate.opsForValue().get("WX_CODE_" + code); // 从redis中获取手机号
+        if (TextUtils.isEmpty(phone)) {
+            throw new APIException("账号已过期,请重新登陆");
+        }
+        return lambdaQuery().eq(ConferenceSubscription::getConferenceId, id).eq(ConferenceSubscription::getPhone, phone)
+                .eq(ConferenceSubscription::getStatus, 1).list();
+    }
 }

+ 70 - 1
src/main/java/com/smcic/api/conference/service/impl/UserThirdServiceImpl.java

@@ -1,11 +1,26 @@
 package com.smcic.api.conference.service.impl;
 
+import cn.hutool.http.HttpUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.TypeReference;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.ImmutableMap;
+import com.smcic.api.conference.dto.WxPhoneDTO;
+import com.smcic.api.conference.entity.ConferenceWxAccount;
 import com.smcic.api.conference.entity.UserThird;
 import com.smcic.api.conference.mapper.UserThirdMapper;
 import com.smcic.api.conference.service.IUserThirdService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.smcic.api.operate.entity.KeysConst;
+import com.smcic.core.advice.APIException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.util.TextUtils;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
 /**
  * <p>
  *  服务实现类
@@ -15,6 +30,60 @@ import org.springframework.stereotype.Service;
  * @since 2024-03-27
  */
 @Service
+@Slf4j
 public class UserThirdServiceImpl extends ServiceImpl<UserThirdMapper, UserThird> implements IUserThirdService {
 
+    private Map<Long, String> access_token = new ConcurrentHashMap<>();
+
+    @Resource
+    private ConferenceWxAccountServiceImpl conferenceWxAccountService;
+
+    @Resource
+    private RedisTemplate<String, String> redisTemplate;
+
+
+    public String  getAccessToken(String appid, String secret) {
+        // 1.拼接请求地址
+        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appid + "&secret=" + secret;
+        // 2.发送请求,获取响应数据
+        String response = HttpUtil.get(url);
+        // 3.提取access_token
+        Map<String, String> map = JSON.parseObject(response, new TypeReference<Map<String, String>>(){});
+        return map.get("access_token");
+    }
+
+    public String getPhone(Long cid, String code){
+        String phone = redisTemplate.opsForValue().get("WX_CODE_" + code);
+        if(!TextUtils.isEmpty(phone)){
+            return phone; // 从缓存中获取
+        }
+        ConferenceWxAccount wxAccount = conferenceWxAccountService.getById(cid);
+        if (wxAccount == null) {
+            throw new APIException("请先配置会议微信账号");
+        }
+        String token;
+        if (!access_token.containsKey(cid)){
+            token = getAccessToken(wxAccount.getWxAppid(), wxAccount.getWxSecret());
+            access_token.put(cid, token);
+        }else{
+            token =  access_token.get(cid);
+        }
+        String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" + token;
+        String response = HttpUtil.post(url, JSON.toJSONString(ImmutableMap.of("code", code)));
+        WxPhoneDTO wxPhoneDTO = JSON.parseObject(response, WxPhoneDTO.class);
+        log.info("获取wx手机号{}", response);
+        if (wxPhoneDTO.getErrcode() != 0){
+            throw new APIException("获取用户手机号失败");
+        }
+        redisTemplate.opsForValue().set("WX_CODE_" + code, wxPhoneDTO.getPhoneInfo().getPhoneNumber(), 60 * 60 * 24 * 30);  // 30天过期
+        return wxPhoneDTO.getPhoneInfo().getPhoneNumber();
+    }
+
+    public void allRefresh(){
+        for (ConferenceWxAccount wxAccount  : conferenceWxAccountService.list()){
+            String token = getAccessToken(wxAccount.getWxAppid(), wxAccount.getWxSecret());
+            access_token.put(wxAccount.getConferenceId(), token);
+        }
+    }
+
 }

+ 52 - 15
src/test/java/conference.http

@@ -13,7 +13,8 @@ Content-Type: application/json
   "theme": "green",
   "logo": "logo",
   "startTime": "2024-04-16 10:00:00",
-  "endTime": "2024-04-20 18:00:00"
+  "endTime": "2024-04-20 18:00:00",
+  "wxVideoUid": "微信视频号id"
 }
 
 ### 会议列表
@@ -44,7 +45,7 @@ GET {{ip}}/conference/conf/list/1066
 GET {{ip}}/conference/conf/info/1066/MANUAL
 
 ### 会议议程
-### 程添加
+### 程添加
 POST {{ip}}/conference/agenda/create
 Content-Type: application/json
 
@@ -53,14 +54,31 @@ Content-Type: application/json
   "agendaName": "第一场",
   "agendaCover": "封面地址",
   "agendaDesc": "议程简述xxxx",
-  "agendaTime": "2024-04-16 10:00:00",
+  "agendaTime": "2024-04-16 10:00",
   "agendaContent": "<div>议程详细内容,xxxxxxxxxxxx</div>",
   "agendaVideo": "会议视频,结束后才有"
 }
 
-### 程列表
+### 程列表
 GET {{ip}}/conference/agenda/list/1066
 
+### 议程添加
+POST {{ip}}/conference/agenda-detail/create
+Content-Type: application/json
+
+{
+  "agendaId": 1,
+  "title": "大语言模型让我们更聪明还是更愚蠢?",
+  "speaker": "宗成庆",
+  "speakerTags": "中国科学院自动化研究所研究员",
+  "startTime": "2024-04-16 10:30",
+  "endTime": "2024-04-16 10:40"
+}
+
+### 根据日程查询议程列表
+GET {{ip}}/conference/agenda-detail/list/1
+
+
 ### 座次安排
 ### 座次配置
 POST {{ip}}/conference/agenda/seat/create
@@ -103,14 +121,14 @@ Content-Type: application/json
 
 {
   "conferenceId": 1066,
-  "userName": "诸葛亮",
-  "tags": "卧龙,蜀国丞相",
-  "photo": "头像",
-  "sortNumber": 1,
-  "userDesc": "诸葛亮,字孔明,本躬耕于南阳,苟全性命于乱世",
+  "userName": "梁昊",
+  "tags": "世界互联网大会常务副秘书长",
+  "photo": "https://cxzx.smcic.net/operate/cenference/1066/20240329/942aa221-321f-4bbc-b176-3d8d872eec36v2.jpg",
+  "sortNumber": 4,
+  "userDesc": "",
   "userType": 1,
-  "speechVideo": "演讲视频,讲过才有",
-  "speechCover": "演讲视频封面,讲过才有"
+  "speechVideo": "",
+  "speechCover": ""
 }
 
 ### 嘉宾查询,根据会议id和类型
@@ -143,7 +161,7 @@ Content-Type: multipart/form-data; boundary=WebAppBoundary
 Content-Disposition: form-data; name="file"; filename="v2.jpg"
 Content-Type: multipart/form-data
 
-< C:\Users\admin\Pictures\v2-a76668f37af2f88b3cf5b3a90b5dc9ce_b.jpg
+< C:\Users\admin\Pictures\internate-conference\梁昊.jpg
 --WebAppBoundary
 Content-Disposition: form-data; name="id"
 Content-Type: text/plain
@@ -173,7 +191,7 @@ Content-Type: text/plain
 1066
 --WebAppBoundary
 
-### 精彩视频 type: 1.小程序视频  2.视频号视频
+### 精彩视频 type: 1.小程序视频  2.视频号视频。 小程序,video是个url,如果视频号,video是俩id(fnderUserName,feedId)视频号id,视频id
 POST {{ip}}/conference/live-video/create
 Content-Type: application/json
 
@@ -205,8 +223,27 @@ Content-Type: application/json
 }
 
 ### 直播图片获取/conference/live-photo/list/{{id}}
-GET {{ip}}/conference/live-photo/list/1066?page=1&pageSize=20
+GET {{ip}}/conference/live-photo/list/1?page=1&pageSize=20
 
 
 ### 直播图片实时推送sse
-GET {{ip}}/conference/photo-sse/1066
+GET {{ip}}/conference/photo-sse/1066
+
+
+### 获取手机号
+GET {{ip}}/conference/user-third/getPhone/1066?code=xxx
+
+### 订阅, status: 1 订阅, 2 取消订阅
+POST {{ip}}/conference/subscription/create?code=xxx
+Content-Type: application/json
+
+{
+  "conferenceId": 1066,
+  "agendaId": 1,
+  "status": 1
+}
+
+### 我的订阅
+GET {{ip}}/conference/subscription/get/1066?code=xxx
+
+