当前位置:   article > 正文

java接入腾讯云即时通信IM_腾讯imjava对接

腾讯imjava对接

        最近需要开发一个客服的功能,由于对socket知识比较匮乏,为了不影响开发进度,准备接入第三方进行二次开发。

        第一步:在IM控制台中创建应用,获取SDKAppID和密钥。

        第二步:引入相关依赖

  1. <!-- 腾讯云IM-sdk -->
  2. <dependency>
  3. <groupId>com.github.tencentyun</groupId>
  4. <artifactId>tls-sig-api-v2</artifactId>
  5. <version>2.0</version>
  6. </dependency>

        第三步:yml配置

  1. #腾讯云IM配置
  2. IMConfig:
  3. sdkAppId: 这里填你自己的sdkAppId
  4. secretKey: 这里填入你的密钥

        第四步:腾讯云IM API路径封装

  1. public enum TencentCloudImApiEnum {
  2. /**
  3. * 账号管理
  4. */
  5. ACCOUNT_IMPORT("导入单个账号", "v4/im_open_login_svc/account_import"),
  6. MULTI_ACCOUNT_IMPORT("导入多个账号", "v4/im_open_login_svc/multiaccount_import"),
  7. ACCOUNT_DELETE("删除账号", "v4/im_open_login_svc/account_delete"),
  8. ACCOUNT_CHECK("查询账号", "v4/im_open_login_svc/account_check"),
  9. KICK("失效账号登录状态", "v4/im_open_login_svc/kick"),
  10. QUERY_ONLINE_STATE("查询账号在线状态", " v4/openim/query_online_status"),
  11. /**
  12. * 单聊消息
  13. */
  14. SEND_MSG("单发单聊消息", "v4/openim/sendmsg"),
  15. BATCH_SEND_MSG("批量发单聊消息", "v4/openim/batchsendmsg"),
  16. IMPORT_MSG("导入单聊消息", "v4/openim/importmsg"),
  17. ADMIN_GET_ROAM_MSG("查询单聊消息", "v4/openim/admin_getroammsg"),
  18. ADMIN_MSG_WITH_DRAW("撤回单聊消息", "v4/openim/admin_msgwithdraw"),
  19. ADMIN_SET_MSG_READ("设置单聊消息已读", "v4/openim/admin_set_msg_read"),
  20. GET_C2C_UNREAD_MSG_NUM("查询单聊未读消息计数", "v4/openim/get_c2c_unread_msg_num"),
  21. MODIFY_C2C_MSG("修改单聊历史消息", "v4/openim/modify_c2c_msg"),
  22. /**
  23. * 全员推送
  24. */
  25. IM_PUSH("全员推送", "v4/all_member_push/im_push"),
  26. IM_SET_ATTR_NAME("设置应用属性名称", "v4/all_member_push/im_set_attr_name"),
  27. IM_GET_ATTR_NAME("获取应用属性名称", "v4/all_member_push/im_get_attr_name"),
  28. IM_GET_ATTR("获取用户属性", "v4/all_member_push/im_get_attr"),
  29. IM_SET_ATTR("设置用户属性", "v4/all_member_push/im_set_attr"),
  30. IM_REMOVE_ATTR("删除用户属性", "v4/all_member_push/im_remove_attr"),
  31. IM_GET_TAG("获取用户标签", "v4/all_member_push/im_get_tag"),
  32. IM_ADD_TAG("添加用户标签", "v4/all_member_push/im_add_tag"),
  33. IM_REMOVE_TAG("删除用户标签", "v4/all_member_push/im_remove_tag"),
  34. IM_REMOVE_ADD_TAGS("删除用户所有标签", "v4/all_member_push/im_remove_all_tags"),
  35. /**
  36. * 资料管理
  37. */
  38. PORTRAIT_SET("设置资料", "v4/profile/portrait_set"),
  39. PORTRAIT_GET("拉取资料", "v4/profile/portrait_get"),
  40. /**
  41. * 关系链管理
  42. */
  43. FRIEND_ADD("添加好友", "v4/sns/friend_add"),
  44. FRIEND_IMPORT("导入好友", "v4/sns/friend_import"),
  45. FRIEND_UPDATE("更新好友", "v4/sns/friend_update"),
  46. FRIEND_DELETE("删除好友", "v4/sns/friend_delete"),
  47. FRIEND_DELETE_ALL("删除所有好友", "v4/sns/friend_delete_all"),
  48. FRIEND_CHECK("校验好友", "v4/sns/friend_check"),
  49. FRIEND_GET("拉取好友", "v4/sns/friend_get"),
  50. FRIEND_GET_LIST("拉取指定好友", "v4/sns/friend_get_list"),
  51. BLACK_LIST_ADD("添加黑名单", "v4/sns/black_list_add"),
  52. BLACK_LIST_DELETE("删除黑名单", "v4/sns/black_list_delete"),
  53. BLACK_LIST_GET("拉取黑名单", "v4/sns/black_list_get"),
  54. BLACK_LIST_CHECK("校验黑名单", "v4/sns/black_list_check"),
  55. GROUP_ADD("添加分组", "v4/sns/group_add"),
  56. GROUP_DELETE("删除分组", "v4/sns/group_delete"),
  57. GROUP_GET("拉取分组", "v4/sns/group_get"),
  58. /**
  59. * 最近联系人
  60. */
  61. CONTACT_GET_LIST("拉取会话列表", "v4/recentcontact/get_list"),
  62. CONTACT_DELETE("删除单个会话", "v4/recentcontact/delete"),
  63. CREATE_CONTACT_GROUP("创建会话分组数据", "v4/recentcontact/create_contact_group"),
  64. DEL_CONTACT_GROUP("删除会话分组数据", "v4/recentcontact/del_contact_group"),
  65. UPDATE_CONTACT_GROUP("更新会话分组数据", "v4/recentcontact/update_contact_group"),
  66. SEARCH_CONTACT_GROUP("搜索会话分组标记数据", "v4/recentcontact/search_contact_group"),
  67. MARK_CONTACT("创建或更新会话标记数据", "v4/recentcontact/mark_contact"),
  68. GET_CONTACT_GROUP("拉取会话分组标记数据", "v4/recentcontact/get_contact_group"),
  69. /**
  70. * 群组管理
  71. */
  72. GET_APPID_GROUP_LIST("获取APP中的所有群组", "v4/group_open_http_svc/get_appid_group_list"),
  73. CREATE_GROUP("创建群组", "v4/group_open_http_svc/create_group"),
  74. GET_GROUP_INFO("获取群详细资料", "v4/group_open_http_svc/get_group_info"),
  75. GET_GROUP_MEMBER_INFO("获取群成员详细资料", "v4/group_open_http_svc/get_group_member_info"),
  76. MODIFY_GROUP_BASE_INFO("修改群基础资料", "v4/group_open_http_svc/modify_group_base_info"),
  77. ADD_GROUP_MEMBER("增加群成员", "v4/group_open_http_svc/add_group_member"),
  78. DELETE_GROUP_MEMBER("删除群成员", "v4/group_open_http_svc/delete_group_member"),
  79. MODIFY_GROUP_MEMBER_INFO("修改群成员资料", "v4/group_open_http_svc/modify_group_member_info"),
  80. DESTROY_GROUP("解散群组", "v4/group_open_http_svc/destroy_group "),
  81. GET_JOINED_GROUP_LIST("获取用户所加入的群组", "v4/group_open_http_svc/get_joined_group_list"),
  82. GET_ROLE_IN_GROUP("查询用户在群组中的身份", "v4/group_open_http_svc/get_role_in_group"),
  83. FORBID_SEND_MSG("批量禁言和取消禁言", "v4/group_open_http_svc/forbid_send_msg"),
  84. GET_GROUP_MUTED_ACCOUNT("获取被禁言群成员列表", "v4/group_open_http_svc/get_group_muted_account"),
  85. SEND_GROUP_MSG("在群组中发送普通消息", "v4/group_open_http_svc/send_group_msg"),
  86. SEND_GROUP_SYSTEM_NOTIFICATION("在群组中发送系统通知", "v4/group_open_http_svc/send_group_system_notification"),
  87. GROUP_MSG_RECALL("撤回群消息", "v4/group_open_http_svc/group_msg_recall"),
  88. CHANGE_GROUP_OWNER("转让群主", "v4/group_open_http_svc/change_group_owner"),
  89. IMPORT_GROUP("导入群基础资料", "v4/group_open_http_svc/import_group"),
  90. IMPORT_GROUP_MSG("导入群消息", "v4/group_open_http_svc/import_group_msg "),
  91. IMPORT_GROUP_MEMBER("导入群成员", "v4/group_open_http_svc/import_group_member"),
  92. SET_UNREAD_MSG_NUM("设置成员未读消息计数", "v4/group_open_http_svc/set_unread_msg_num"),
  93. DELETE_GROUP_MSG_BY_SENDER("删除指定用户发送的消息", "v4/group_open_http_svc/delete_group_msg_by_sender"),
  94. GROUP_MSG_GET_SIMPLE("拉取群历史消息", "v4/group_open_http_svc/group_msg_get_simple"),
  95. GET_ONLINE_MEMBER_NUM("获取直播群在线人数", "v4/group_open_http_svc/get_online_member_num"),
  96. GET_MEMBERS("获取直播群在线成员列表", "v4/group_open_avchatroom_http_svc/get_members"),
  97. MODIFY_USER_INFO("设置直播群成员标记", "v4/group_open_avchatroom_http_svc/modify_user_info"),
  98. GET_GROUP_ATTR("获取群自定义属性", "v4/group_open_attr_http_svc/get_group_attr"),
  99. GET_GROUP_BAN_MEMBER("获取封禁群成员列表", "v4/group_open_http_svc/get_group_ban_member"),
  100. BAN_GROUP_MEMBER("群成员封禁", "v4/group_open_http_svc/ban_group_member"),
  101. UNBAN_GROUP_MEMBER("群成员解封", "v4/group_open_http_svc/unban_group_member"),
  102. MODIFY_GROUP_ATTR("修改群自定义属性", "v4/group_open_http_svc/modify_group_attr"),
  103. CLEAR_GROUP_ATTR("清空群自定义属性", "v4/group_open_http_svc/clear_group_attr"),
  104. SET_GROUP_ATTR("重置群自定义属性", "v4/group_open_http_svc/set_group_attr"),
  105. MODIFY_GROUP_MSG("修改群聊历史消息", "v4/openim/modify_group_msg"),
  106. SEND_BROADCAST_MSG("直播群广播消息", "v4/group_open_http_svc/send_broadcast_msg"),
  107. GET_GROUP_COUNTER("获取群计数器", "v4/group_open_http_svc/get_group_counter"),
  108. UPDATE_GROUP_COUNTER("更新群计数器", "v4/group_open_http_svc/update_group_counter"),
  109. DELETE_GROUP_COUNTER("删除群计数器", "v4/group_open_http_svc/delete_group_counter"),
  110. /**
  111. * 全局禁言管理
  112. */
  113. SET_NO_SPEAKING("设置全局禁言", " v4/openconfigsvr/setnospeaking"),
  114. GET_NO_SPEAKING("查询全局禁言", " v4/openconfigsvr/getnospeaking"),
  115. /**
  116. * 运营管理
  117. */
  118. GET_APP_INFO("拉取运营数据", "v4/openconfigsvr/getappinfo"),
  119. GET_HISTORY("下载消息记录", "v4/open_msg_svc/get_history"),
  120. GET_IP_LIST("获取服务器IP地址", "v4/ConfigSvc/GetIPList"),
  121. FORBID_ILLEGAL_OBJECT("聊天文件封禁", "v4/im_cos_msg/forbid_illegal_object"),
  122. ALLOW_BANNED_OBJECT("聊天文件解封", "v4/im_cos_msg/allow_banned_object"),
  123. GET_COS_SIG("聊天文件签名", "v4/im_cos_msg/get_cos_sig");
  124. private final String description;
  125. private final String url;
  126. TencentCloudImApiEnum(String description, String url) {
  127. this.description = description;
  128. this.url = url;
  129. }
  130. public String description() {
  131. return description;
  132. }
  133. public String getUrl() {
  134. return url;
  135. }
  136. }

        第五步:基础API封装

  1. @Slf4j
  2. @Component
  3. public class TencentCloudImUtil {
  4. private static final String HTTPS_URL_PREFIX = "https://console.tim.qq.com/";
  5. private static final String APP_MANAGER = "administrator";
  6. private static final String REDIS_IM_USER_SIG = "silence:im_user_sig:";
  7. @Value("${king.IMConfig.sdkAppId}")
  8. private long sdkAppId;
  9. @Value("${king.IMConfig.secretKey}")
  10. private String secretKey;
  11. @Autowired
  12. private Cache cache;
  13. /**
  14. * 获取腾讯云用户签名
  15. */
  16. public String getTxCloudUserSig() {
  17. String userSig = (String) cache.get(REDIS_IM_USER_SIG + APP_MANAGER);
  18. if (StringUtils.isEmpty(userSig)) {
  19. TLSSigAPIv2 tlsSigApi = new TLSSigAPIv2(sdkAppId, secretKey);
  20. userSig = tlsSigApi.genUserSig(APP_MANAGER, 86400);
  21. cache.put(REDIS_IM_USER_SIG + APP_MANAGER, userSig, 86400L);
  22. }
  23. return userSig;
  24. }
  25. /**
  26. * 获取腾讯im请求路径
  27. */
  28. private String getHttpsUrl(String imServiceApi, Integer random) {
  29. return String.format("%s%s?sdkappid=%s&identifier=%s&usersig=%s&random=%s&contenttype=json",
  30. HTTPS_URL_PREFIX, imServiceApi, sdkAppId, APP_MANAGER, this.getTxCloudUserSig(), random);
  31. }
  32. /**
  33. * 导入单个账号
  34. * @param userId 用户id
  35. */
  36. public void accountImport(String userId) {
  37. accountImport(userId, null);
  38. }
  39. public void accountImport(String userId, String userName) {
  40. accountImport(userId, userName, null);
  41. }
  42. public void accountImport(String userId, String userName, String faceUrl) {
  43. Integer random = RandomUtils.nextInt(0, 999999999);
  44. String httpsUrl = getHttpsUrl(TencentCloudImApiEnum.ACCOUNT_IMPORT.getUrl(), random);
  45. JSONObject jsonObject = new JSONObject();
  46. jsonObject.put("Identifier", userId);
  47. if (StringUtils.isNotEmpty(userName)) {
  48. jsonObject.put("Nick", userName);
  49. }
  50. if (StringUtils.isNotEmpty(faceUrl)) {
  51. jsonObject.put("FaceUrl", faceUrl);
  52. }
  53. log.info("腾讯云im导入单个账号,请求参数:{}", jsonObject.toString());
  54. String result = HttpClientUtils.doPost(httpsUrl, jsonObject);
  55. log.info("腾讯云im导入单个账号,返回结果:{}", result);
  56. }
  57. /**
  58. * 导入多个账号
  59. * @param userIds 用户id集合
  60. */
  61. public void multiAccountImport(List<String> userIds) {
  62. Integer random = RandomUtils.nextInt(0, 999999999);
  63. String httpsUrl = getHttpsUrl(TencentCloudImApiEnum.MULTI_ACCOUNT_IMPORT.getUrl(), random);
  64. JSONObject jsonObject = new JSONObject();
  65. jsonObject.put("Accounts", userIds);
  66. log.info("腾讯云im导入多个账号,请求参数:{}", jsonObject.toString());
  67. String result = HttpClientUtils.doPost(httpsUrl, jsonObject);
  68. log.info("腾讯云im导入单个账户,返回结果:{}", result);
  69. }
  70. /**
  71. * 批量删除账号
  72. * @param userIds 用户id集合
  73. */
  74. public void accountDeleteBatch(List<String> userIds) {
  75. Integer random = RandomUtils.nextInt(0, 999999999);
  76. String httpsUrl = getHttpsUrl(TencentCloudImApiEnum.ACCOUNT_DELETE.getUrl(), random);
  77. JSONObject jsonObject = new JSONObject();
  78. jsonObject.put("DeleteItem", getUserIdJsonList(userIds));
  79. log.info("腾讯云im删除账号,请求参数:{}", jsonObject.toString());
  80. String result = HttpClientUtils.doPost(httpsUrl, jsonObject);
  81. log.info("腾讯云im删除账户,返回结果:{}", result);
  82. }
  83. /**
  84. * 查询账号是否已经导入im
  85. * @param userIds 用户id集合
  86. */
  87. public String accountCheck(List<String> userIds) {
  88. Integer random = RandomUtils.nextInt(0, 999999999);
  89. String httpsUrl = getHttpsUrl(TencentCloudImApiEnum.ACCOUNT_CHECK.getUrl(), random);
  90. JSONObject jsonObject = new JSONObject();
  91. jsonObject.put("CheckItem", getUserIdJsonList(userIds));
  92. log.info("腾讯云im查询账号,请求参数:{}", jsonObject.toString());
  93. String result = HttpClientUtils.doPost(httpsUrl, jsonObject);
  94. log.info("腾讯云im查询账号,返回结果:{}", result);
  95. return result;
  96. }
  97. private List<JSONObject> getUserIdJsonList(List<String> userIds) {
  98. return userIds.stream().map(v -> {
  99. JSONObject userIdJson = new JSONObject();
  100. userIdJson.put("UserID", v);
  101. return userIdJson;
  102. }).collect(Collectors.toList());
  103. }
  104. /**
  105. * 单发单聊消息
  106. * @param syncOtherMachine 是否同步消息到发送方(1-同步,2-不同步)
  107. * @param fromUserId 发送方用户id
  108. * @param toUserId 接收方用户id
  109. * @param msgType 消息对象类型
  110. * @param msgContent 消息内容
  111. */
  112. public String sendMsg(Integer syncOtherMachine, String fromUserId, String toUserId, String msgType, String msgContent) {
  113. Integer random = RandomUtils.nextInt(0, 999999999);
  114. String httpsUrl = getHttpsUrl(TencentCloudImApiEnum.SEND_MSG.getUrl(), random);
  115. JSONObject jsonObject = new JSONObject();
  116. jsonObject.put("SyncOtherMachine", syncOtherMachine);
  117. if (StringUtils.isNotEmpty(fromUserId)) {
  118. // 发送方不为空表示指定发送用户,为空表示为管理员发送消息
  119. jsonObject.put("From_Account", fromUserId);
  120. }
  121. jsonObject.put("To_Account", toUserId);
  122. jsonObject.put("MsgRandom", random);
  123. List<JSONObject> msgBody = getMsgBody(msgType, msgContent);
  124. jsonObject.put("MsgBody", msgBody);
  125. log.info("腾讯云im单发单聊消息,请求参数:{}", jsonObject.toString());
  126. String result = HttpClientUtils.doPost(httpsUrl, jsonObject);
  127. log.info("腾讯云im单发单聊消息,返回结果:{}", result);
  128. return result;
  129. }
  130. /**
  131. * 批量发单聊消息
  132. * @param syncOtherMachine 是否同步消息到发送方(1-同步,2-不同步)
  133. * @param fromUserId 发送方用户id
  134. * @param toUserIds 接收方用户id集合
  135. * @param msgType 消息对象类型
  136. * @param msgContent 消息内容
  137. */
  138. public String batchSendMsg(Integer syncOtherMachine, String fromUserId, List<String> toUserIds, String msgType, String msgContent) {
  139. Integer random = RandomUtils.nextInt(0, 999999999);
  140. String httpsUrl = getHttpsUrl(TencentCloudImApiEnum.BATCH_SEND_MSG.getUrl(), random);
  141. JSONObject jsonObject = new JSONObject();
  142. jsonObject.put("SyncOtherMachine", syncOtherMachine);
  143. if (StringUtils.isNotEmpty(fromUserId)) {
  144. // 发送方不为空表示指定发送用户,为空表示为管理员发送消息
  145. jsonObject.put("From_Account", fromUserId);
  146. }
  147. jsonObject.put("To_Account", toUserIds);
  148. jsonObject.put("MsgRandom", random);
  149. List<JSONObject> msgBody = getMsgBody(msgType, msgContent);
  150. jsonObject.put("MsgBody", msgBody);
  151. log.info("腾讯云im批量发单聊消息,请求参数:{}", jsonObject.toString());
  152. String result = HttpClientUtils.doPost(httpsUrl, jsonObject);
  153. log.info("腾讯云im批量发单聊消息,返回结果:{}", result);
  154. return result;
  155. }
  156. /**
  157. * 拼接发送消息内容
  158. * @param msgType 消息类型
  159. * @param msgContent 发送消息内容
  160. * @return 消息内容
  161. */
  162. private List<JSONObject> getMsgBody(String msgType, String msgContent) {
  163. List<JSONObject> msgBody = new ArrayList<>();
  164. if (msgType.equals(TencentCloudImConstant.TIM_TEXT_ELEM)) {
  165. // 文本类型
  166. JSONObject msgBodyJson = new JSONObject();
  167. msgBodyJson.put("MsgType", msgType);
  168. JSONObject msgContentObj = new JSONObject();
  169. msgContentObj.put("Text", msgContent);
  170. msgBodyJson.put("MsgContent", msgContentObj);
  171. msgBody.add(msgBodyJson);
  172. }
  173. return msgBody;
  174. }
  175. /**
  176. * 查询单聊消息
  177. * @param fromUserId 发送方用户id
  178. * @param toUserId 接收方用户id
  179. * @param maxCnt 查询条数
  180. * @param startTime 起始时间(单位:秒)
  181. * @param endTime 结束时间(单位:秒)
  182. * @param lastMsgKey 最后一条消息的 MsgKey
  183. * @return 单聊消息列表
  184. */
  185. public String adminGetRoamMsg(String fromUserId, String toUserId, Integer maxCnt, Long startTime, Long endTime, String lastMsgKey) {
  186. Integer random = RandomUtils.nextInt(0, 999999999);
  187. String httpsUrl = getHttpsUrl(TencentCloudImApiEnum.ADMIN_GET_ROAM_MSG.getUrl(), random);
  188. JSONObject jsonObject = new JSONObject();
  189. jsonObject.put("From_Account", fromUserId);
  190. jsonObject.put("To_Account", toUserId);
  191. jsonObject.put("MaxCnt", maxCnt);
  192. jsonObject.put("MinTime", startTime);
  193. jsonObject.put("MaxTime", endTime);
  194. if (StringUtils.isNotEmpty(lastMsgKey)){
  195. jsonObject.put("LastMsgKey", lastMsgKey);
  196. }
  197. log.info("腾讯云im查询单聊消息,请求参数:{}", jsonObject.toString());
  198. String result = HttpClientUtils.doPost(httpsUrl, jsonObject);
  199. log.info("腾讯云im查询单聊消息,返回结果:{}", result);
  200. return result;
  201. }
  202. /**
  203. * 撤回单聊消息
  204. * @param fromUserId 发送方用户id
  205. * @param toUserId 接收方用户id
  206. * @param msgKey MsgKey
  207. */
  208. public void adminMsgWithDraw(String fromUserId, String toUserId, String msgKey) {
  209. Integer random = RandomUtils.nextInt(0, 999999999);
  210. String httpsUrl = getHttpsUrl(TencentCloudImApiEnum.ADMIN_MSG_WITH_DRAW.getUrl(), random);
  211. JSONObject jsonObject = new JSONObject();
  212. jsonObject.put("From_Account", fromUserId);
  213. jsonObject.put("To_Account", toUserId);
  214. jsonObject.put("MsgKey", msgKey);
  215. log.info("腾讯云im撤回单聊消息,请求参数:{}", jsonObject.toString());
  216. String result = HttpClientUtils.doPost(httpsUrl, jsonObject);
  217. log.info("腾讯云im撤回单聊消息,返回结果:{}", result);
  218. }
  219. /**
  220. * 设置单聊消息已读
  221. * @param reportUserId 读取消息的用户
  222. * @param peerUserId 发送消息的用户
  223. */
  224. public void adminSetMsgRead(String reportUserId, String peerUserId) {
  225. Integer random = RandomUtils.nextInt(0, 999999999);
  226. String httpsUrl = getHttpsUrl(TencentCloudImApiEnum.ADMIN_SET_MSG_READ.getUrl(), random);
  227. JSONObject jsonObject = new JSONObject();
  228. jsonObject.put("Report_Account", reportUserId);
  229. jsonObject.put("Peer_Account", peerUserId);
  230. log.info("腾讯云im设置单聊消息已读,请求参数:{}", jsonObject.toString());
  231. String result = HttpClientUtils.doPost(httpsUrl, jsonObject);
  232. log.info("腾讯云im设置单聊消息已读,返回结果:{}", result);
  233. }
  234. }

        到这一步已经差不多了,可以愉快的开始开发了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/70074
推荐阅读
相关标签
  

闽ICP备14008679号