日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

魔方APP项目-07-客户端提交登录信息、在APICloud中集成防水墙验证码,前端获取显示并校验验证码、服务端校验验证码、保存用户登录状态,APICloud提供的数据存储、客户端保存用户登陆数据

發布時間:2024/3/24 HTML 50 豆豆

用戶登錄

一、客戶端提交登錄信息

html/login.html,代碼:

<!DOCTYPE html> <html> <head><title>登錄</title><meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"><meta charset="utf-8"><link rel="stylesheet" href="../static/css/main.css"><script src="../static/js/vue.js"></script><script src="../static/js/axios.js"></script><script src="../static/js/main.js"></script><script src="../static/js/uuid.js"></script><script src="../static/js/settings.js"></script><script src="../static/js/TCaptcha.js"></script> </head> <body><div class="app" id="app"><img class="music" :class="music_play?'music2':''" @click="music_play=!music_play" src="../static/images/player.png"><div class="bg"><img src="../static/images/bg0.jpg"></div><div class="form"><div class="form-title"><img src="../static/images/login.png"><img class="back" src="../static/images/back.png"></div><div class="form-data"><div class="form-data-bg"><img src="../static/images/bg1.png"></div><div class="form-item"><label class="text">賬戶</label><input type="text" v-model="account" placeholder="請輸入手機號/郵箱/用戶名"></div><div class="form-item"><label class="text">密碼</label><input type="password" v-model="password" placeholder="請輸入密碼"></div><div class="form-item"><input type="checkbox" class="agree remember" v-model="remember" checked><label><span class="agree_text ">記住密碼,下次免登錄</span></label></div><div class="form-item"><img class="commit" @click="loginHandle" src="../static/images/commit.png"></div><div class="form-item"><p class="toreg" @click="goto_register">立即注冊</p><p class="tofind">忘記密碼</p></div></div></div></div><script>apiready = function(){init();new Vue({el:"#app",data(){return {account: "",password: "",remember: false, // 是否記住登陸music_play:true,prev:{name:"",url:"",params:{}},current:{name:"login",url:"login.html",params:{}},}},watch:{music_play(){if(this.music_play){this.game.play_music("../static/mp3/bg1.mp3");}else{this.game.stop_music();}}},methods:{loginHandle(){// 登錄處理this.game.play_music('../static/mp3/btn1.mp3');// 驗證密碼和賬戶是否填寫if(this.account.length<1 || this.password.length<1){api.alert({title: '警告',msg: '賬戶或密碼不能為空!',});return;}// 發送登錄信息this.axios.post('', {'jsonrpc': '2.0','id': this.uuid(),'method': 'User.login','params': {'account': this.account,'password': this.password,}}).then(response=>{// 獲取服務端數據this.game.print(response.data);}).catch(error=>{if(error.response){// 服務端返回錯誤this.game.print(error.response.data.errmsg);}else {// 本地代碼出現錯誤this.game.print(error);}})},goto_register(){this.game.goGroup("user",1);},}})}</script> </body> </html>

二、在APICloud中集成防水墻驗證碼

使用微信掃碼登錄騰訊云控制臺,然后根據官方文檔,把驗證碼集成到項目中
官網: https://007.qq.com
驗證碼控制臺: https://console.cloud.tencent.com/captcha
快速接入:https://007.qq.com/python-access.html?ADTAG=acces.start

  • 訪問驗證碼控制臺: https://console.cloud.tencent.com/captcha

  • 新建驗證應用,獲取秘鑰和應用ID[ 新用戶可以領取一個免費的驗證碼套餐 ]

  • 點擊詳情:
    把驗證碼應用的ID和秘鑰保存到application/settings/dev.py配置文件中.

  • # 防水墻驗證碼CAPTCHA_GATEWAY="https://ssl.captcha.qq.com/ticket/verify"CAPTCHA_APP_ID="2041284967"CAPTCHA_APP_SECRET_KEY="0FrDthTnnU8vG-jSwz7DOAA**"

    1.前端獲取顯示并校驗驗證碼

    把防水墻的前端核心js文件在客戶端根目錄下index.html中使用script引入或者在src/main.js中通過import引入。
    下載地址:https://ssl.captcha.qq.com/TCaptcha.js

    在客戶端項目的settings.js中添加配置app_id:

    function init(){var game = new Game("../mp3/bg1.mp3");Vue.prototype.game = game;// 初始化axiosaxios.defaults.baseURL = "http://192.168.20.158:5000/api" // 服務端api接口網關地址axios.defaults.timeout = 2500; // 請求超時時間axios.defaults.withCredentials = false; // 跨域請求資源的情況下,忽略cookie的發送Vue.prototype.axios = axios;Vue.prototype.uuid = UUID.generate;Vue.prototype.settings = {app_id: "2041284967"} }

    2.客戶端展示驗證碼

    html/login.html,代碼:

    <!DOCTYPE html> <html> <head><title>登錄</title><meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"><meta charset="utf-8"><link rel="stylesheet" href="../static/css/main.css"><script src="../static/js/vue.js"></script><script src="../static/js/axios.js"></script><script src="../static/js/main.js"></script><script src="../static/js/uuid.js"></script><script src="../static/js/settings.js"></script><script src="../static/js/Tcaptcha.js"></script> </head> <body><div class="app" id="app"><img class="music" :class="music_play?'music2':''" @click="music_play=!music_play" src="../static/images/player.png"><div class="bg"><img src="../static/images/bg0.jpg"></div><div class="form"><div class="form-title"><img src="../static/images/login.png"><img class="back" src="../static/images/back.png"></div><div class="form-data"><div class="form-data-bg"><img src="../static/images/bg1.png"></div><div class="form-item"><label class="text">賬戶</label><input type="text" v-model="account" placeholder="請輸入手機號/郵箱/用戶名"></div><div class="form-item"><label class="text">密碼</label><input type="password" v-model="password" placeholder="請輸入密碼"></div><div class="form-item"><input type="checkbox" class="agree remember" v-model="remember" checked><label><span class="agree_text ">記住密碼,下次免登錄</span></label></div><div class="form-item"><img class="commit" @click="loginHandle" src="../static/images/commit.png"></div><div class="form-item"><p class="toreg" @click="goto_register">立即注冊</p><p class="tofind">忘記密碼</p></div></div></div></div><script>apiready = function(){init();new Vue({el:"#app",data(){return {account: "",password: "",remember: false, // 是否記住登陸music_play:true,prev:{name:"",url:"",params:{}},current:{name:"login",url:"login.html",params:{}},}},watch:{music_play(){if(this.music_play){this.game.play_music("../static/mp3/bg1.mp3");}else{this.game.stop_music();}}},methods:{loginHandle(){// 登錄處理this.game.play_music('../static/mp3/btn1.mp3');// 驗證密碼和賬戶是否填寫if(this.account.length<1 || this.password.length<1){api.alert({title: '警告',msg: '賬戶或密碼不能為空!',});return;}// 圖形驗證碼var captcha1 = new TencentCaptcha(this.settings.captcha_app_id, res=>{// 當用戶操作驗證碼成功以后的回調處理,這里需要把參數發送到當前應用的服務端/*res的返回結果包含以下4個成員"appid":"2041284967","ret":0,"ticket":"t03WemDcWVY9tCdU0eiUtR41IlaU0Xk6Xop02s_COXMWuC0j4eA2UKHqdFnFIxk982gQD4sFSfsnrg8QPk6br4nDZd7dSQwAVl6vOPdApNr3wc*","randstr":"@SOF"*/if(res.ret == 0){// 當用戶操作驗證通過以后, 發送登錄信息和驗證校驗信息this.axios.post('', {'jsonrpc': '2.0','id': this.uuid(),'method': "User.login",'params': {'ticket': res.ticket, // 驗證通過以后的服務端驗證碼返回的臨時憑證,需要發送給服務端,和騰訊服務器進行校驗'randstr': res.randstr, // 隨機數, 為了讓ticket更加隨機和安全'account': this.account,'password': this.password}}).then(response=>{// 獲取服務端數據this.game.print(response.data);}).catch(error=>{if(error.response{// 服務端返回錯誤this.game.print(error.response.data.errmsg);}else {// 本地代碼出現錯誤this.game.print(error);}});}});captcha1.show(); // 顯示驗證碼},goto_register(){this.game.goGroup("user",1);},}})}</script> </body> </html>

    3.服務端校驗驗證碼是否正確

    application/apps/users/views.py

    from application import jsonrpc,db from .marshmallow import MobileSchema,UserSchema from marshmallow import ValidationError from message import ErrorMessage as Message from status import APIStatus as status @jsonrpc.method("User.mobile") def mobile(mobile):"""驗證手機號碼是否已經注冊"""ms = MobileSchema()try:ms.load({"mobile":mobile})ret = {"errno":status.CODE_OK, "errmsg":Message.ok}except ValidationError as e:ret = {"errno":status.CODE_VALIDATE_ERROR, "errmsg": e.messages["mobile"][0]}return ret@jsonrpc.method("User.register") def register(mobile,password,password2, sms_code):"""用戶信息注冊"""try:ms = MobileSchema()ms.load({"mobile": mobile})us = UserSchema()user = us.load({"mobile":mobile,"password":password,"password2":password2,"sms_code": sms_code})data = {"errno": status.CODE_OK,"errmsg":us.dump(user)}except ValidationError as e:data = {"errno": status.CODE_VALIDATE_ERROR,"errmsg":e.messages}return datafrom flask_jwt_extended import create_access_token,create_refresh_token,jwt_required,get_jwt_identity,jwt_refresh_token_required from flask import jsonify,json from sqlalchemy import or_ from .models import User from message import ErrorMessage as message from status import APIStatus as status from flask import current_app, request from urllib.parse import urlencode from urllib.request import urlopen@jsonrpc.method("User.login") def login(ticket, randstr, account, password):"""根據用戶登錄信息生成token"""# 校驗防水墻驗證碼params = {'aid': current_app.config.get('CAPTCHA_APP_ID'),'AppSecretKey': current_app.config.get('CAPTCHA_APP_SECRET_KEY'),'Ticket': ticket,'Randstr': randstr,'UserIP': request.remote_addr}# 把字典數據轉換成地址欄的查詢字符串格式# aid=xxx&AppSecretKey=xxx&xxxxxparams = urlencode(params)url = current_app.config.get('CAPTCHA_GATEWAY')# 發送http的get請求f = urlopen('%s?%s' % (url, params))# https://ssl.captcha.qq.com/ticket/verify?aid=xxx&AppSecretKey=xxx&xxxxxcontent = f.read()res = json.loads(content)print(res)if int(res.get('response')) != 1:# 驗證失敗return {'errno': status.CODE_CAPTCHA_ERROR, 'errmsg': message.captcaht_no_match}# 1. 根據賬戶信息和密碼獲取用戶if len(account) < 1:return {"errno":status.CODE_NO_ACCOUNT,"errmsg":message.account_no_data}user = User.query.filter(or_(User.mobile == account,User.email == account,User.name == account)).first()if user is None:return {"errno": status.CODE_NO_USER,"errmsg":message.user_not_exists}# 驗證密碼if not user.check_password(password):return {"errno": status.CODE_PASSWORD_ERROR, "errmsg":message.password_error}# 2. 生成jwt tokenaccess_token = create_access_token(identity=user.id)refresh_token = create_refresh_token(identity=user.id)return {'errno': status.CODE_OK,'errmsg': message.ok,'id': user.id,'nickname': user.nickname if user.nickname else account,"access_token": access_token,"refresh_token": refresh_token}@jsonrpc.method("User.info") @jwt_required # 驗證jwt def info():"""獲取用戶信息"""user_data = json.loads(get_jwt_identity()) # get_jwt_identity 用于獲取載荷中的數據print(user_data)return "ok"@jsonrpc.method("User.refresh") @jwt_refresh_token_required def refresh():"""重新獲取新的認證令牌token"""current_user = get_jwt_identity()# 重新生成tokenaccess_token = create_access_token(identity=current_user)return access_token

    application/utils/language/message.py

    class ErrorMessage():ok = "ok"mobile_format_error = "手機號碼格式有誤!"mobile_is_use = "對不起,當前手機已經被注冊!"username_is_use = "對不起,當前用戶名已經被使用!"password_not_match = "密碼和驗證密碼不匹配!"sms_send_error = "短信發送失敗!"sms_interval_time = "短信發送冷卻中!"sms_code_expired = "短信驗證碼已過期!"sms_code_error = "短信驗證碼不正確!"sms_is_send = "短信發送中,請留意您的手機短信。"no_authorization = "用戶認證信息校驗失敗!"authorization_has_expired = "用戶認證信息已過期,請重新登錄!"authorization_is_invalid = "無效的認證信息!"account_no_data = "對不起,用戶賬戶必須填寫!"user_not_exists = "用戶不存在!"password_error = "密碼錯誤!"captcaht_no_match = "驗證碼驗證失敗!"

    application/utils/language/status.py

    class APIStatus():CODE_OK = 1000 # 接口操作成功CODE_VALIDATE_ERROR = 1001 # 驗證有誤!CODE_SMS_ERROR = 1002 # 短信功能執行失敗CODE_INTERVAL_TIME = 1003 # 短信發送冷卻中CODE_NO_AUTHORIZATION = 1004 # 請求中沒有附帶認證信息CODE_SIGNATURE_EXPIRED = 1005 # 請求中的認證信息已過期CODE_INVALID_AUTHORIZATION = 1006 # 請求中的認證信息無效CODE_NO_ACCOUNT = 1007 # 請求中沒有賬戶信息CODE_NO_USER = 1008 # 用戶不存在CODE_PASSWORD_ERROR = 1009 # 密碼錯誤CODE_CAPTCHA_ERROR = 1010 # 驗證碼驗證失敗

    三、保存用戶登錄狀態

    1.APICloud提供的數據存儲

    基于APICloud提供的本地存儲可以有效保存數據

    // 保存數據到內存中 api.setGlobalData({key: 'userName',value: 'api' }); // 從內存中獲取數據 var userName = api.getGlobalData({key: 'userName' });// 保存數據到文件中 api.setPrefs({//儲存key: 'userName',value: 'api' }); // 從文件中獲取數據 api.getPrefs({//獲取key: 'userName' }, function(ret, err) {... }); // 注意:基于api.getPrefs獲取數組時,會出現轉義格式的字符// 從文件中刪除數據 api.removePrefs({//刪除key: 'userName' });

    2.客戶端保存用戶登陸數據

    static/js/main.js,代碼:

    class Game{constructor(bg_music){// 構造函數,相當于python中類的__init__方法this.init();if(bg_music){this.play_music(bg_music);}}open(){}init(){// 初始化console.log("系統初始化");this.rem();// 幀頁面組的初始化this.groupname = null;this.groupindex = 0;}print(data){// 打印數據console.log(JSON.stringify(data));}back(prev){// 返回上一頁this.go(prev.name,prev.url,{...prev});}outWin(name){// 關閉窗口api.closeWin(name);}goWin(name,url,pageParam){// 新建窗口api.openWin({name: name, // 自定義窗口名稱bounces: false, // 窗口是否上下拉動reload: true, // 如果頁面已經在之前被打開了,是否要重新加載當前窗口中的頁面useWKWebView:true,historyGestureEnabled:true,url: url, // 窗口創建時展示的html頁面的本地路徑[相對于當前代碼所在文件的路徑]animation:{ // 打開新建窗口時的過渡動畫效果type: "push", //動畫類型(詳見動畫類型常量)subType: "from_right", //動畫子類型(詳見動畫子類型常量)duration:300 //動畫過渡時間,默認300毫秒},pageParam: pageParam // 傳遞給下一個窗口使用的參數.將來可以在新窗口中通過 api.pageParam.name 獲取});}goFrame(name,url,pageParam,rect=null){// 創建幀頁面if(rect === null){rect = {// 方式1,設置矩形大小寬高x: 0, // 左上角x軸坐標y: 0, // 左上角y軸坐標w: 'auto', // 當前幀頁面的寬度, auto表示滿屏h: 'auto' // 當前幀頁面的高度, auto表示滿屏}}api.openFrame({name: name, // 幀頁面的名稱url: url, // 幀頁面打開的url地址bounces:false, // 頁面是否可以下拉拖動reload: true, // 幀頁面如果已經存在,是否重新刷新加載useWKWebView: true,historyGestureEnabled:true,animation:{type:"push", //動畫類型(詳見動畫類型常量)subType:"from_right", //動畫子類型(詳見動畫子類型常量)duration:300 //動畫過渡時間,默認300毫秒},rect: rect, // 當前幀的寬高范圍pageParam: pageParam, // 要傳遞新建幀頁面的參數,在新頁面可通過 api.pageParam.name 獲取});}outFrame(name){// 關閉幀頁面api.closeFrame({name: name,});}openGroup(name,frames,preload=1,rect=null){// 創建frame組if(rect === null){rect = { // 幀頁面組的顯示矩形范圍x:0, //左上角x坐標,數字類型y:0, //左上角y坐標,數字類型w:'auto', //寬度,若傳'auto',頁面從x位置開始自動充滿父頁面寬度,數字或固定值'auto'h:'auto', //高度,若傳'auto',頁面從y位置開始自動充滿父頁面高度,數字或固定值'auto'};}api.openFrameGroup({name: name, // 組名scrollEnabled: false, // 頁面組是否可以左右滾動index: 0, // 默認顯示頁面的索引rect: rect, // 頁面寬高范圍preload: preload, // 默認預加載的頁面數量frames: frames, // 幀頁面組的幀頁面成員}, (ret, err)=>{// 當前幀頁面發生頁面顯示變化時,當前幀的索引.this.groupindex = ret.index;});}outGroup(name){// 關閉 frame組api.closeFrameGroup({name: name // 組名});}goGroup(name,index){// 切換顯示frame組下某一個幀頁面api.setFrameGroupIndex({name: name, // 組名index: index // 索引,從0開始});}rem(){if(window.innerWidth<1200){this.UIWidth = document.documentElement.clientWidth;this.UIHeight = document.documentElement.clientHeight;document.documentElement.style.fontSize = (0.01*this.UIWidth*3)+"px";document.querySelector("#app").style.height=this.UIHeight+"px"}window.onresize = ()=>{if(window.innerWidth<1200){this.UIWidth = document.documentElement.clientWidth;this.UIHeight = document.documentElement.clientHeight;document.documentElement.style.fontSize = (0.01*this.UIWidth*3)+"px";}}}save(data){// 保存數據到內存中for(var key in data){api.setGlobalData({key: key,value: data[key]})}}get(data){// 從內存中獲取數據if(!Array.isArray(data)){data = [data];}var result = {};for(var key of data){result[key] = api.getGlobalData({'key': key});}return result;}fsave(data){// 保存數據到文件中for(var key in data){api.setPrefs({'key': key,value: data[key]});}}fremove(dat){// 從文件中刪除數據if(!Array.isArray(data)){data = [data];}for(var key of data){api.removePrefs({'key': key});}}fget(data){// 從文件中獲取數據if(!Array.isArray(data)){data = [data];}var value;var result = {}for(var key of data){result[key] = api.getPrefs({sync: true,key: key}); }return result;}stop_music(){this.print("停止背景音樂");document.body.removeChild(this.audio);}play_music(src){this.print("播放背景音樂");this.audio = document.createElement("audio");this.source = document.createElement("source");this.source.type = "audio/mp3";this.audio.autoplay = "autoplay";this.source.src=src;this.audio.appendChild(this.source);/*<audio autoplay="autoplay"><source type="audio/mp3" src="../static/mp3/bg1.mp3"></audio>*/document.body.appendChild(this.audio);// 自動暫停關閉背景音樂var t = setInterval(()=>{if(this.audio.readyState > 0){if(this.audio.ended){clearInterval(t);try{document.body.removeChild(this.audio);}catch(error){// 不處理}}}},100);} }

    html/login.html,代碼:

    <!DOCTYPE html> <html> <head><title>登錄</title><meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"><meta charset="utf-8"><link rel="stylesheet" href="../static/css/main.css"><script src="../static/js/vue.js"></script><script src="../static/js/axios.js"></script><script src="../static/js/main.js"></script><script src="../static/js/uuid.js"></script><script src="../static/js/settings.js"></script><script src="../static/js/TCaptcha.js"></script> </head> <body><div class="app" id="app"><img class="music" :class="music_play?'music2':''" @click="music_play=!music_play" src="../static/images/player.png"><div class="bg"><img src="../static/images/bg0.jpg"></div><div class="form"><div class="form-title"><img src="../static/images/login.png"><img class="back" src="../static/images/back.png"></div><div class="form-data"><div class="form-data-bg"><img src="../static/images/bg1.png"></div><div class="form-item"><label class="text">賬戶</label><input type="text" v-model="account" placeholder="請輸入手機號/郵箱/用戶名"></div><div class="form-item"><label class="text">密碼</label><input type="password" v-model="password" placeholder="請輸入密碼"></div><div class="form-item"><input type="checkbox" class="agree remember" v-model="remember" checked><label><span class="agree_text ">記住密碼,下次免登錄</span></label></div><div class="form-item"><img class="commit" @click="loginHandle" src="../static/images/commit.png"></div><div class="form-item"><p class="toreg" @click="goto_register">立即注冊</p><p class="tofind">忘記密碼</p></div></div></div></div><script>apiready = function(){init();new Vue({el:"#app",data(){return {account: "",password: "",remember: false, // 是否記住登陸music_play:true,prev:{name:"",url:"",params:{}},current:{name:"login",url:"login.html",params:{}},}},watch:{music_play(){if(this.music_play){this.game.play_music("../static/mp3/bg1.mp3");}else{this.game.stop_music();}}},methods:{loginHandle(){// 登錄處理this.game.play_music('../static/mp3/btn1.mp3');// 驗證密碼和賬戶是否填寫if(this.account.length<1 || this.password.length<1){api.alert({title: '警告',msg: '賬戶或密碼不能為空!',});return;}// 圖形驗證碼var captcha1 = new TencentCaptcha(this.settings.captcha_app_id, res=>{// 當用戶操作驗證碼成功以后的回調處理,這里需要把參數發送到當前應用的服務端/*res的返回結果包含以下4個成員"appid":"2041284967","ret":0,"ticket":"t03WemDcWVY9tCdU0eiUtR41IlaU0Xk6Xop02s_COXMWuC0j4eA2UKHqdFnFIxk982gQD4sFSfsnrg8QPk6br4nDZd7dSQwAVl6vOPdApNr3wc*","randstr":"@SOF"*/if(res.ret == 0){// 當用戶操作驗證通過以后, 發送登錄信息和驗證校驗信息this.axios.post('', {'jsonrpc': '2.0','id': this.uuid(),'method': "User.login",'params': {'ticket': res.ticket, // 驗證通過以后的服務端驗證碼返回的臨時憑證,需要發送給服務端,和騰訊服務器進行校驗'randstr': res.randstr, // 隨機數, 為了讓ticket更加隨機和安全'account': this.account,'password': this.password}}).then(response=>{// 獲取服務端數據if(response.data.result.errno == 1000){if(this.remember){// 記住登錄this.game.fsave({'id': response.data.result.id,'nickname': response.data.result.nickname,'access_token': response.data.result.access_token,'refresh_token': response.data.result.refresh_token});}else {// 不記住登錄this.game.save({'id': response.data.result.id,'nickname': response.data.result.nickname,'access_token': response.data.result.access_token,'refresh_token': response.data.result.refresh_token,});}}}).catch(error=>{if(error.response){// 服務端返回錯誤this.game.print(error.response.data);}else {// 本地代碼出現錯誤this.game.print(error);}});}});captcha1.show(); // 顯示驗證碼},goto_register(){this.game.goGroup("user",1);},}})}</script> </body> </html>

    總結

    以上是生活随笔為你收集整理的魔方APP项目-07-客户端提交登录信息、在APICloud中集成防水墙验证码,前端获取显示并校验验证码、服务端校验验证码、保存用户登录状态,APICloud提供的数据存储、客户端保存用户登陆数据的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。