首页
归档
留言
广告合作
友链
美女主播
Search
1
博瑞GE车机升级/降级
5,157 阅读
2
Mac打印机设置黑白打印
4,519 阅读
3
修改elementUI中el-table树形结构图标
4,518 阅读
4
Mac客户端添加腾讯企业邮箱方法
4,355 阅读
5
intelliJ Idea 2022.2.X破解
4,064 阅读
Java
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
登录
/
注册
Search
标签搜索
Spring Boot
Java
Spring Cloud
Mac
mybatis
WordPress
Nacos
Spring Cloud Alibaba
Mybatis-Plus
jQuery
Java Script
asp.net
微信小程序
Sentinel
UniApp
MySQL
asp.net core
IntelliJ IDEA
Jpa
树莓派
Laughing
累计撰写
573
篇文章
累计收到
1,424
条评论
首页
栏目
Java
HarmonyOS Next
Web前端
微信开发
开发辅助
App开发
数据库
随笔日记
页面
归档
留言
广告合作
友链
美女主播
搜索到
5
篇与
的结果
2025-01-12
开源免费的微信视频号下载工具
主要功能一键下载:在视频号页面直接添加下载按钮,无需复制链接或者抓包多画质选择:支持下载不同清晰度的视频,包括原始视频质量图片下载:支持批量下载视频号中的图片内容,自动打包成压缩文件直播回放:支持下载视频号的直播回放内容跨平台支持:同时支持 Windows 和 macOS 系统 使用说明安装过程非常简单,只需要下载对应系统的可执行文件即可使用,不过 Windows 和 macOS 的安装步骤略有不同。Windows安装说明下载 Windows 版本的可执行文件,以管理员身份运行,首次打开会自动安装证书,然后启动服务。当终端提示「服务已正确启动」就说明可以使用了。Mac OS安装说明- 下载 macOS 版本的可执行文件(文件名类似 wx_video_download_drawin_xxx)- 打开终端,进入文件所在目录- 执行以下命令赋予文件执行权限:chmod +x ./wx_video_download_drawin_xxx- 使用管理员权限运行程序sudo ./wx_video_download_drawin_xxx- 请求安装证书权限,同意即可使用说明打开微信PC端,点击需要下载的视频,在视频下方的操作按钮一栏,会多出一个下载按钮,如下所示- 如果没有,可以看看「更多」这里是否有「下载视频」按钮。- 等待视频开始播放,然后暂停视频,点击下载按扭即可下载视频。下载成功后,会在上方显示已下载的文件,下载文件名最后面会标志该视频质量。项目地址{anote icon="fa-download" href="https://github.com/ltaoo/wx_channels_download?tab=readme-ov-file" type="secondary" content="https://github.com/ltaoo/wx_channels_download?tab=readme-ov-file"/}
2025年01月12日
17 阅读
0 评论
0 点赞
2022-11-17
油耗笔记OilNote周边搜索能力由高德地图切换成百度地图
一、交代下背景以前油耗笔记OilNote检索周边加油站功能,都是用的高德地图,起初,也不知道高德Api限制多少访问量,反正一直也没提示过超额,但是今天,莫名的收到了两条超额的短信。一开始收到80%超额的时候也没太当回事,觉得可能这个月改版,调试用的数量比较大,但是紧接着就收到了超额100%的提示,就感觉到不太对劲了,于是登录了高德后台,查询了一下配额。结果真是乖了个乖,搜索服务每日限额100次,这简直就是坑了,100次跟没有没啥区别,高德这是直接劝退个人开发者的节奏。查了下站内信,2022年10月26日发的站内信(没短信),通知2022年10月27日调整限额,连给你调整的时间都不给。坑你没商量呀。二、百度地图为什么选择百度地图呢?介个,国内好像除了高德就是百度了,不用也没办法。因为我就用到了地点检索,百度地图目前还算比较良心的,个人开发者每日限额是5000次。是高德地图的50倍。并发限制都是一样的30QPS。百度地图创建应用的时候,记得选择微信小程序,否则逆地理编码是不能用的。三、微信公众平台配置如果使用百度地图,必须提前把百度地图Api放到域名白名单里面。微信小程序后台,依次定位到开发管理→开发设置→服务器域名,在request合法域名里面加上百度地图的网址https://api.map.baidu.com如果微信开发者工具提示域名不合法,记得刷新一下开发者工具的域名信息。刷新后记得重新编译项目。三、功能改造既然决定了用百度地图,那么剩下的就是如何对程序进行改造了。因为我的小程序是使用uniapp开发的,所以这里就介绍一下uniapp的整个的改造过程。为了不影响在线版本,暂时先不删除高德域名。3.1、manifest.json改造manifest.json用于配置地图的Key,因为我之前使用的是高德的地图,切换到百度后,需要将相关配置改成百度地图的。其实我现在只是用了微信小程序,AK我直接在代码里面写死了,这里配置的appkey我感觉没啥用,对uniapp理解不是很深入,这块可能更多的是给App用的吧。我们Maps需要勾选百度地图并取消高德地图。具体的key,可以在百度开放平台,个人创建的应用中找到。3.2、获取附近加油站功能改造其实改造也比较简单,高德跟百度Api还是比较类似的。3.2.1、原来高德获取周边加油站的代码let getLocation = function(radius = 1000, successFn) { var latitude = '' //纬度 var longitude = '' //经度 if (uni.getStorageSync('position') == '') { uni.getLocation({ geocode: true, type: 'gcj02', altitude: true, accuracy: 'best', isHighAccuracy: true, success: (res) => { console.log('位置是', res) latitude = res.latitude longitude = res.longitude uni.setStorageSync('latitude', latitude) uni.setStorageSync('longitude', longitude) uni.request({ url: 'https://restapi.amap.com/v3/geocode/regeo?key=AK' + '&location=' + longitude + ',' + latitude + '&poitype=010100&radius=' + radius + '&extensions=all&batch=false&roadlevel=0', success: function(res) { var regeocode = res.data.regeocode // 省份名称 uni.setStorageSync('province', regeocode.addressComponent.province) // 城市名称 uni.setStorageSync('city', regeocode.addressComponent.city) // 城市编号 uni.setStorageSync('citycode', regeocode.addressComponent.citycode) successFn(regeocode) }, fail(err) { console.log('获取加油站信息失败:' + JSON.stringify(err)) } }) }, fail: (err) => { console.log('获取加油站信息失败:' + JSON.stringify(err)) } }) } }3.2.2、百度地图获取逆地址编码(根据坐标获取位置)let getLocation = function(radius = 1000, successFn) { var latitude = '' //纬度 var longitude = '' //经度 uni.getLocation({ geocode: true, type: 'gcj02', altitude: true, accuracy: 'best', isHighAccuracy: true, success: (res) => { console.log('位置是', res) latitude = res.latitude longitude = res.longitude uni.request({ url: 'https://api.map.baidu.com/geoconv/v1/?' + 'ak=您的AK(类型是服务端的)' + '&coords=' + longitude + ',' + latitude + '&from=3&to=5&output=json', success: function(res) { debugger if (res.data.status === 0) { longitude = res.data.result[0].x latitude = res.data.result[0].y uni.setStorageSync('latitude', latitude) uni.setStorageSync('longitude', longitude) uni.request({ url: 'https://api.map.baidu.com/reverse_geocoding/v3/?' + 'ak=您的AK(类型是小程序的)&output=json' + '&coord_type=gcj02ll' + '&location=' + latitude + ',' + longitude + '&radius=' + radius, success: function(res) { if (res.data.status === 0) { // 省份名称 uni.setStorageSync('province', res.data .result.addressComponent .province) // 城市名称 uni.setStorageSync('city', res.data .result.addressComponent .city) // 城市编号 uni.setStorageSync('citycode', res.data .result.cityCode) successFn(res.data, res.data.result .addressComponent.province, res.data.result .addressComponent.city) } }, fail(err) { console.log('获取位置信息失败:' + JSON.stringify(err)) } }) } }, fail(err) { console.log('获取位置信息失败:' + JSON.stringify(err)) } }) }, fail: (err) => { console.log('获取位置信息失败:' + JSON.stringify(err)) } }) }需要注意,uni.getLocation获取gcj02时的坐标适用于高德等地图,但是不适用百度地图,需要调用百度地图坐标转换接口geoconv转换成百度地图的坐标,不然会有较大的误差,同时地图转换接口使用的AK需要是服务端类型的应用的AK,也就是说我们实际上使用了两种AK,一种是服务端的,一种是小程序的。3.2.3、百度地图获取附近加油站let getOilStation = function(radius = 1000, successFn) { let latitude = uni.getStorageSync('latitude') //纬度 let longitude = uni.getStorageSync('longitude') //经度 uni.request({ url: 'https://api.map.baidu.com/place/v2/search?' + 'query=充电站$加油站&ak=您的AK(类型是小程序的)&output=json' + '&scope=2' + '&coord_type=2' + '&page_size=20' + '&location=' + latitude + ',' + longitude + '&radius=' + radius, success: function(res) { successFn(res) } }) }改造完成后验证一下四、使用百度地图一些问题目前切换到百度地图之后遇到的一些问题搜索功能显示不全,我家附近其实就有一个中国石化,但是百度地图搜索不到,充电站搜索还算比较全的不能显示图片,如果photo_show开启,会提示授权失败。
2022年11月17日
1,056 阅读
0 评论
0 点赞
2021-05-02
微信公众号开发之回复用户留言
在微信公众号开发之公众号基础配置一文中,我们介绍了如何对微信公众号进行基础配置。下面基于李森的博客的一个需求说明一下如何实现公众号用户的回复开发。需求描述用户给公众号发送消息时,我们查询博客的内容,然后回复给用户。代码实现其实用户回复的请求,跟微信公众号开发之公众号基础配置中配置的URL是一致的。区别在于我们在微信公众号开发之公众号基础配置中配置的请求是GET请求,用户回复的时候,微信会通过POST请求到后台。定义Controller相应微信请求POST请求定义其实没啥特别的,代码如下 @PostMapping("official") public void post(HttpServletRequest request, HttpServletResponse response) { try { request.setCharacterEncoding("UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } response.setCharacterEncoding("UTF-8"); // 调用核心业务类接收消息、处理消息 // String respMessage = weixinPost(request); String respMessage = messageService.newMessageRequest(request); // 响应消息 PrintWriter out = null; try { out = response.getWriter(); out.print(respMessage); } catch (IOException e) { e.printStackTrace(); logger.error(e.getMessage()); } finally { out.close(); out = null; } }封装实体封装消息基础实体BaseMessage.java/** * 微信自动回复消息封装 */ @Data public class BaseMessage { // 开发者微信号 private String ToUserName; // 发送方帐号(一个OpenID) private String FromUserName; // 消息创建时间 (整型) private long CreateTime; // 消息类型(text/image/location/link) private String MsgType; // 消息id,64位整型 private long MsgId; /** * 位0x0001被标志时,星标刚收到的消息 */ private int FuncFlag; }封装普通文本消息实体TextMessage.java@EqualsAndHashCode(callSuper = true) @Data public class TextMessage extends BaseMessage{ // 消息内容 private String Content; }封装图文消息实体Article.java@Data public class Article { /** * 图文消息描述 */ private String Description; /** * 图片链接,支持JPG、PNG格式,<br> * 较好的效果为大图640*320,小图80*80 */ private String PicUrl; /** * 图文消息名称 */ private String Title; /** * 点击图文消息跳转链接 */ private String Url; }封装多条图文消息实体'NewsMessage.java'@EqualsAndHashCode(callSuper = true) @Data public class NewsMessage extends BaseMessage{ /** * 图文消息个数,限制为10条以内 */ private Integer ArticleCount; /** * 多条图文消息信息,默认第一个item为大图 */ private List<Article> Articles; }封装工具类我们需要将实体转换成xml结构,微信消息都是通过xml格式进行数据交互的。public class MessageUtil { /** * 返回消息类型:文本 */ public static final String RESP_MESSAGE_TYPE_TEXT = "text"; /** * 返回消息类型:音乐 */ public static final String RESP_MESSAGE_TYPE_MUSIC = "music"; /** * 返回消息类型:图文 */ public static final String RESP_MESSAGE_TYPE_NEWS = "news"; /** * 请求消息类型:文本 */ public static final String REQ_MESSAGE_TYPE_TEXT = "text"; /** * 请求消息类型:图片 */ public static final String REQ_MESSAGE_TYPE_IMAGE = "image"; /** * 请求消息类型:链接 */ public static final String REQ_MESSAGE_TYPE_LINK = "link"; /** * 请求消息类型:地理位置 */ public static final String REQ_MESSAGE_TYPE_LOCATION = "location"; /** * 请求消息类型:音频 */ public static final String REQ_MESSAGE_TYPE_VOICE = "voice"; /** * 请求消息类型:推送 */ public static final String REQ_MESSAGE_TYPE_EVENT = "event"; /** * 事件类型:subscribe(订阅) */ public static final String EVENT_TYPE_SUBSCRIBE = "subscribe"; /** * 事件类型:unsubscribe(取消订阅) */ public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe"; /** * 事件类型:CLICK(自定义菜单点击事件) */ public static final String EVENT_TYPE_CLICK = "CLICK"; /** * xml转换为map * * @param request * @return * @throws IOException */ public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException { Map<String, String> map = new HashMap<String, String>(); SAXReader reader = new SAXReader(); InputStream ins = null; try { ins = request.getInputStream(); } catch (IOException e1) { e1.printStackTrace(); } Document doc = null; try { doc = reader.read(ins); Element root = doc.getRootElement(); List<Element> list = root.elements(); for (Element e : list) { map.put(e.getName(), e.getText()); } return map; } catch (DocumentException e1) { e1.printStackTrace(); } finally { ins.close(); } return null; } /** * @param @param request * @param @return * @param @throws Exception * @Description: 解析微信发来的请求(XML) */ public static Map<String, String> parseXml(HttpServletRequest request) throws Exception { // 将解析结果存储在HashMap中 Map<String, String> map = new HashMap<String, String>(); // 从request中取得输入流 InputStream inputStream = request.getInputStream(); // 读取输入流 SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); // 得到xml根元素 Element root = document.getRootElement(); // 得到根元素的所有子节点 List<Element> elementList = root.elements(); // 遍历所有子节点 for (Element e : elementList) map.put(e.getName(), e.getText()); // 释放资源 inputStream.close(); inputStream = null; return map; } // public static XStream xstream = new XStream(); /** * 文本消息对象转换成xml * * @param textMessage 文本消息对象 * @return xml */ public static String textMessageToXml(TextMessage textMessage) { // XStream xstream = new XStream(); xstream.alias("xml", textMessage.getClass()); return xstream.toXML(textMessage); } /** * @param @param newsMessage * @param @return * @Description: 图文消息对象转换成xml */ public static String newsMessageToXml(NewsMessage newsMessage) { xstream.alias("xml", newsMessage.getClass()); xstream.alias("item", new Article().getClass()); return xstream.toXML(newsMessage); } /** * 对象到xml的处理 */ private static XStream xstream = new XStream(new XppDriver() { public HierarchicalStreamWriter createWriter(Writer out) { return new PrettyPrintWriter(out) { // 对所有xml节点的转换都增加CDATA标记 boolean cdata = true; @SuppressWarnings("rawtypes") public void startNode(String name, Class clazz) { super.startNode(name, clazz); } protected void writeText(QuickWriter writer, String text) { if (cdata) { writer.write("<![CDATA["); writer.write(text); writer.write("]]>"); } else { writer.write(text); } } }; } }); }封装服务层 /** * 微信公众号处理 * * @param request * @return */ @Override public String newMessageRequest(HttpServletRequest request) { String respMessage = null; try { // xml请求解析 Map<String, String> requestMap = MessageUtil.xmlToMap(request); // 发送方帐号(open_id) String fromUserName = requestMap.get("FromUserName"); // 公众帐号 String toUserName = requestMap.get("ToUserName"); // 消息类型 String msgType = requestMap.get("MsgType"); // 用户发送的消息消息内容 String content = requestMap.get("Content"); logger.info("FromUserName is:" + fromUserName + ", ToUserName is:" + toUserName + ", MsgType is:" + msgType + ",content:" + content); // 文本消息 if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) { logger.info("进入方法内"); QueryWrapper<TypechoContents> queryWrapper = new QueryWrapper<>(); queryWrapper.lambda() .like(TypechoContents::getTitle, content) .or() .like(TypechoContents::getText, content); List<TypechoContents> typechoContentsList = typechoContentsMapper.selectTypechoContentsList(content); logger.info("数据查询完成:" + typechoContentsList.size()); if (typechoContentsList.size() <= 0) { //自动回复 TextMessage text = new TextMessage(); String string = "未找到要查询的内容,请换个关键字试试"; text.setContent(string); text.setToUserName(fromUserName); text.setFromUserName(toUserName); text.setCreateTime(new Date().getTime()); text.setMsgType(msgType); respMessage = MessageUtil.textMessageToXml(text); return respMessage; } else if (typechoContentsList.size() > 1) { TextMessage text = new TextMessage(); StringBuilder stringBuilder = new StringBuilder("搜索到以下内容:\r\n"); for (TypechoContents typechoContents : typechoContentsList) { stringBuilder.append("<a href='https://www.xiangcaowuyu.net/").append(typechoContents.getCategory()).append("/").append(typechoContents.getSlug()).append(".html'>").append(typechoContents.getTitle()).append("</a>"); stringBuilder.append("\r\n"); } text.setContent(stringBuilder.toString()); text.setToUserName(fromUserName); text.setFromUserName(toUserName); text.setCreateTime(new Date().getTime()); text.setMsgType(msgType); respMessage = MessageUtil.textMessageToXml(text); return respMessage; } else { //一条回复图文消息 NewsMessage newsMessage = new NewsMessage(); newsMessage.setArticles(new ArrayList<>()); newsMessage.setArticleCount(typechoContentsList.size()); newsMessage.setToUserName(fromUserName); newsMessage.setFromUserName(toUserName); newsMessage.setCreateTime(new Date().getTime()); newsMessage.setMsgType("news"); for (TypechoContents typechoContents : typechoContentsList) { Article article = new Article(); article.setUrl("https://www.xiangcaowuyu.net/" + typechoContents.getCategory() + "/" + typechoContents.getSlug() + ".html"); article.setDescription(typechoContents.getTitle()); List<String> imageUrlList = MessageUtil.getMatchString(typechoContents.getText()); if (imageUrlList.size() <= 0) { article.setPicUrl("https://www.xiangcaowuyu.net/usr/themes/xiangcaowuyu/assets/img/logo.png"); } else { logger.info(imageUrlList.get(0)); article.setPicUrl(imageUrlList.get(0)); } article.setTitle(typechoContents.getTitle()); newsMessage.getArticles().add(article); } respMessage = MessageUtil.newsMessageToXml(newsMessage); return respMessage; } } // 事件推送 else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) { String eventType = requestMap.get("Event");// 事件类型 // 订阅 if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) { //文本消息 TextMessage text = new TextMessage(); logger.info(XiangCaoWuYuConfig.getResp()); text.setContent(XiangCaoWuYuConfig.getResp().replace("<br/>","\n")); text.setToUserName(fromUserName); text.setFromUserName(toUserName); text.setCreateTime(new Date().getTime()); text.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT); respMessage = MessageUtil.textMessageToXml(text); return respMessage; } // 取消订阅后用户再收不到公众号发送的消息,因此不需要回复消息 else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {// 取消订阅 } } } catch (Exception e) { logger.error("error......"); } return respMessage; }
2021年05月02日
1,025 阅读
0 评论
0 点赞
2021-04-22
微信小程序自定义不一样的tabBar
实现过程其中扫码买单,这个按钮效果,微信自带的tabBar是无法实现的,其后尝试了下custom-tab-bar 也是无法实现。没办法了,既然微信的tabBar无法实现。那就自己弄个真-自定义tabBar来实现好了。各位看官莫慌,下面就把解决方案放上来。首先先来讲下解决方案的思路,然后再把代码送上。思路: 微信的tabBar无法实现,那么就放弃微信的tabBar,改用Component 来实现。把微信自带的tabBar隐藏起来,用Component 做成伪tabBar并应该到页面上。把app.json下的 tabBar 给干掉。这样在首页就不会有tabBar显示了。写Component 伪tabBar并应该到页面上。代码app.json删除 tabBar自定义component<!--Componet/tabBar/tabBar.wxml--> <view class="tabBar"> <view class="cont"> <block wx:for="{{tabBar}}" wx:for-item="item" wx:key="tabBar"> <view class="item {{item.switchQr?'switchQr':''}}" catchtap="{{!item.switchQr?'goToTab':'switchQr'}}" data-url="{{item.pagePath}}" data-index="{{index}}"> <image class="ico" src="{{idx === index ? item.selectedIconPath : item.iconPath}}"></image> <view class="txt {{idx === index ? 'selectedColor' : ''}}">{{item.text}} </view> </view> </block> </view> </view>// Componet/tabBar/tabBar.js Component({ /** * 组件的属性列表 */ properties: { idx: { type: Number, value: 0 }, }, /** * 组件的初始数据 */ data: { tabBar: [{ "pagePath": "../../pages/index/index", "text": "首页", "switchQr": false, "iconPath": "/image/home.svg", "selectedIconPath": "/image/home_sel.svg", }, { "pagePath": "", "text": "扫码买单", "switchQr": true, "iconPath": "/image/saoma.svg", }, { "pagePath": "../../pages/user/user", "text": "我的", "switchQr": false, "iconPath": "/image/mine.svg", "selectedIconPath": "/image/mine_sel.svg", }, ] }, /** * 组件的方法列表 */ methods: { goToTab: function (e) { //如果点击当前页面则不进行跳转 if (this.data.idx == e.currentTarget.dataset.index) { return false } wx.navigateTo({ url: e.currentTarget.dataset.url }) }, // 扫码 switchQr() { // console.log('扫码') }, } })/* Componet/tabBar/tabBar.wxss */ .tabBar { width: 100%; position: fixed; bottom: 0; font-size: 20rpx; color: #8A8A8A; background: #fff; /* border-top: 2rpx solid #eee; */ box-shadow: 0rpx 1rpx 6rpx rgba(0,0,0,0.3); } .cont { margin-top: 10rpx; padding: 0; z-index: 0; height: calc(100rpx + env(safe-area-inset-bottom) / 2); padding-bottom: calc(env(safe-area-inset-bottom) / 2); display: flex; } .cont .item { font-size: 24rpx; position: relative; flex: 1; text-align: center; padding: 0; display: block; height: auto; line-height: 1; margin: 0; background-color: inherit; overflow: initial; justify-content: center; align-items: center; } .cont .item .ico { width: 46rpx; height: 46rpx; margin: auto } .cont .item .txt{ margin-top: 8rpx; color: #333; } .cont .switchQr .ico { position: absolute; width: 106rpx !important; z-index: 2; height: 106rpx !important; border-radius: 50%; font-size: 50rpx; top: -50rpx; left: 0; right: 0; margin: auto; padding: 0; } .cont .switchQr .txt{ margin-top: 56rpx; } .cont .item .selectedColor{ color: #ff4e4e; }使用在index/user的页面上应用。要在index.json/user.json文件引用component"usingComponents": { "tabBar":"/Componet/tabBar/tabBar" },在页面的引用component <!-- index.wxml --> <tabBar idx="0"></tabBar> <!--user.wxml --> <tabBar idx="2"></tabBar>
2021年04月22日
1,358 阅读
0 评论
24 点赞
2018-07-15
关于微信小程序使用wxParse报错: thirdScriptError console.dir is not a function
最近在开发小程序,有一个详细展示的页面,为了展示html代码,调用了wxParse的代码,当时在模拟器上面模拟是没有问题的,但是在我安卓手机(坚果Pro2)上面进行调试时,文章展示html页面,始终是一片空白。当时感觉不对劲,然后拿着我老婆的苹果手机试了一下,没有任何问题。此时,果断打开手机的调试功能,看到错误信息thirdScriptError console.dir is not a function。百度了一下,终于找到了解决办法。解决办法把wxParse插件下的·html2json.js·里的·console.dir·注释掉或者替换成·console.log·。
2018年07月15日
1,366 阅读
0 评论
0 点赞