加拿大減塑 2021年底前禁六大類一次性塑膠製品

摘錄自2020年10月8日中央社報導

加拿大環境部長今(7日)宣布,2021年底之前,加拿大將禁用塑膠袋、塑膠吸管等一次性塑膠用品;他也坦言,加國在回收方面落後歐洲。

今天公布的禁令另將涵蓋攪拌棒、啤酒提環、餐盤以及難以回收的塑膠製餐具,是總理杜魯道(Justin Trudeau)放眼2030年前消滅塑膠垃圾,兌現氣候與環境政見核心的計畫一環。

但環境部長威金森(Jonathan Wilkinson)坦言:「我們這方面不在世界的前段班。」

政府表示,加拿大人每年丟棄300萬公噸塑膠垃圾,其中包括一年丟棄150億個塑膠袋、每天丟掉5700萬支塑膠吸管,在這之中,僅有9%回收。

污染治理
國際新聞
加拿大
一次性塑膠製品
禁塑
塑膠垃圾
一次性塑膠袋

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

瑞典船運業推出「海洋鳥」 以風為動力可遠洋運輸

摘錄自2020年9月24日科技新報報導

瑞典造船公司 Wallenius Marine 近日宣布推出以風為主要動力、全新的遠洋運輸船「海洋鳥」(Oceanbird),盼開啟環保航運新的一頁。

由於海洋鳥上的機翼帆採取伸縮式結構,當通過橋下或遭遇強風時便能迅速縮小帆體的表面積來進行控制,船體同時也配備輔助的綠能引擎,做為進出港口使用的安全措施。

由於使用風能為主要航行動力,海洋鳥的航行速度較傳統貨輪來的慢,僅能以約 10 節的平均速度航行,橫渡北大西洋約需要 12 天的時間,但在不需要使用高污染燃油下,海洋鳥可以減少近 90% 的排放。

在瑞典運輸署的支持下,Wallenius 已經建造出海洋鳥的小型模型,將於接下來幾個月進行測試,預計完整設計明年底前將準備就緒,2025 年首艘船將正式登場。

能源轉型
國際新聞
瑞典
航運
海運

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

疫情肆虐下 日本民眾提高對太陽能板裝設興趣

文:宋瑞文(加州能源特約撰述)

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※產品缺大量曝光嗎?你需要的是一流包裝設計!

印尼就業環保新法救經濟 勞工抗議延燒

摘錄自2020年10月7日中央社報導

疫情重創經濟,印尼政府加速鬆綁勞動及環保法規,日前突襲通過新法,盼改善投資環境增加就業機會,卻引發大規模抗議,遭質疑修法犧牲勞工權益及環保,爭議恐持續延燒。

印尼政府年初提出創造就業綜合法案後,民間抗議聲浪不斷,勞工團體多次上街表達不滿。

印尼國會5日趕在全國性大罷工前夕審查完法案。印尼請願網站當天發起拒絕創造就業綜合法案的連署迅速累積逾120萬人支持,各大城市爆發罷工示威潮。

在國會審議前,印尼總統佐科威(Joko Widodo)重要幕僚、海洋事務統籌部長盧胡特(Luhut Panjaitan)指出,政府因處理武漢肺炎疫情,這項法案自4月延宕至今。該法案是促進投資的關鍵,幾經協商,全國8大主要工會組織中有6大工會組織同意立法。

不過,由印尼工會聯盟(KSPI)、印尼工人工會聯合會(KSPSI)等團體發動的罷工6日在各大城市許多工業區吸引成千上萬勞工參與。

除了勞動法規,創造就業綜合法案通過也影響環保及稅務等超過70個法律,主要目的是降低投資障礙,方便投資者取得土地及相關證照。這部分引起環保團憂心將弱化環境影響評估的把關機制,不利環境永續發展。

印尼綠色和平資深森林專員亞塞普(Asep Komarudin)7日對中央社指出,現行法規有很多嚴格確保環境保護的條文都因創造就業綜合法案通過而遭廢除,例如未來有些投資案可不經環境影響評估,環評也將限制只有受影響者才參與,不再開放公民參與。

亞塞普說,根據創造就業綜合法案,未來開發案與環保衝突時,被視為與國家策略發展相關的計畫都要給予優先考量,主導開發的國家與企業肯定會持續與原住民族發生衝突,巴布亞(Papua)、加里曼丹(Kalimantan)、蘇門答臘(Sumatra)等地的林地面積可能會再減少3成以上,「我們非常擔心」。

國際新聞
印尼
修法
環保法
勞工剝削
抗議

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

※產品缺大量曝光嗎?你需要的是一流包裝設計!

等同666個台灣 南極臭氧層破洞創近年「最大最深」

摘錄自2020年10月7日自由時報報導

聯合國世界氣象組織(WMO)宣布,南極臭氧層破洞已經創下近年來的「最大最深」,破洞於8月中旬起迅速變大,10月初面積達2400萬平方公里,以台灣面積為3.6萬平方公里來看,相當於666個台灣。

根據美國《ABC新聞》報導,聯合國世界氣象組織指出,目前出現在南極上空的破洞是近幾年來「最大」和「最深」的,強烈的極地渦流是此次臭氧層的導火線,負78度的極度低溫條件下形成「極地平流層雲」,雲中含有冰晶,經太陽光照射後就會產生化學反應,開始大量消耗臭氧。

美國太空總署表示,異常的南極天氣是造成這種情況的原因;歐洲中期天氣預報中心哥白尼大氣監測局局長佩奇(Vincent-Henri Peuch)認為,每年發生的南極臭氧層破洞事件都有很大的差異,這也表明人們需要持續減少排放有害物質,繼續執行《蒙特婁議定書》的規範事項。

氣候變遷
國際新聞
南極
南極臭氧層

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

受農藥所苦的「空中王者」 柬埔寨三種瀕危兀鷲數量持續下降

環境資訊中心綜合外電;黃鈺婷 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

15萬買啥車?有轎車有SUV,這2款合資車可以放心買

勁客的優勢在於成熟可靠的動力總成,採用1。5L自然吸氣發動機+CVT無級變速器的搭配能夠帶來非常平順線性的輸出,油門調校靈敏,能夠很好地應付日常市區內行駛,並且也非常省油,可靠性較高。不過其檔次感與配置水平不如哈弗H2。

15萬左右比較推薦的是本田XR-V與豐田卡羅拉,這兩款車目前在市場上都有着不錯的銷量、保值率以及口碑,XR-V在小型SUV市場混得風生水起,靠的就是其成熟的動力系統和越級的空間表現,家用是個非常棒的選擇。而卡羅拉乃全球銷量神車,中庸就是其最大的武器,除了汽油版本外還有雙擎版本可選,擁有非常優秀的燃油經濟性,能夠滿足許許多多的消費者,除了隔音濾振差點,其它方面的表現都非常不錯,乃家用車的不二之選。

一輛是接近中型車的緊湊型車,一輛是標準的中型車,凌渡280DSG豪華版擁有更加豐富的配置,不過因為其比較扁平的設計所以頭部空間表現一般,而君威中型車的身份自然擁有更大的空間以及更高的檔次感,同時全系標配9AT也讓其競爭力進一步上升,採用的1.5T發動機也有着不錯的動力輸出,因此更推薦君威1.5T中配。

510採用的是6擋手動變速器和5擋AMT變速器,假設會開手動擋的話更加推薦手動車型,6個擋位在高速行駛時把轉速壓得更低,能帶來更好的燃油經濟性,同時擁有更高的傳動效率及可靠性,510的手動擋換擋手感不錯,有吸入感並且行程不長,離合器的力度也不沉,沒那麼容易疲勞。而AMT變速器雖然說省去了踩離合器的麻煩,但是其換擋邏輯不清晰,而且頓挫比較嚴重,尤其是在起步階段或者是在堵車狀況下,因此更加推薦510的手動版車型。

兩車都是定位小型SUV,哈弗H2擁有更加親民的售價,更加大氣上檔次的外觀內飾設計,同時配置更加豐富,採用的1.5T發動機+7擋雙離合的搭配,擁有不錯的爆發力,但是雙離合變速器的邏輯有待提高,並且油耗也會偏高。

勁客的優勢在於成熟可靠的動力總成,採用1.5L自然吸氣發動機+CVT無級變速器的搭配能夠帶來非常平順線性的輸出,油門調校靈敏,能夠很好地應付日常市區內行駛,並且也非常省油,可靠性較高。不過其檔次感與配置水平不如哈弗H2。

綜上,假如你預算充足的話,更加建議購買勁客的中配以上車型,而預算不是很足的話,那麼家用選擇H2是一個非常具有性價比的選擇。

2018款飛度新增了運動套件車型,不過在配置方面還是一如既往的寒酸,比較推薦指導價為8.88萬的1.5L CVT潮跑版,在配置上面擁有主/副駕駛座安全氣囊、運動外觀套件、行車電腦显示屏、前霧燈等,類似比較常用的电子車身穩定系統、駐車雷達要到頂配才配備,但是飛度的動力和空間還是非常不錯的,1.5L自吸發動機就能爆發出131匹馬力,日常市區駕駛毫無壓力,加上本田“MM”理念,讓它的空間能夠滿足大多數人的使用需求,市面上大量的改裝件也能讓每位飛度車主把愛車改成獨一無二的樣子。

以上就是本期網友問答欄目的全部內容,假如你也想上牆的話,點擊下方留言留下你的問題並且點個贊,就有機會在下期欄目看見你的身影!本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

Node.js躬行記(4)——自建前端監控系統

  這套前端監控系統用到的技術棧是:React+MongoDB+Node.js+Koa2。將性能和錯誤量化。因為自己平時喜歡吃菠蘿,所以就取名叫菠蘿系統。其實在很早以前就有這個想法,當時已經實現了前端的參數搜集,只是後台遲遲沒有動手,也就拖着。

  • 目前完成的還只是個雛形,僅僅是搜集了錯誤和相關的性能參數。

  • 後台樣式採用了封裝過的matrix。

  • 分析功能還很薄弱,只是做了簡單的演示,並且各種基礎功能還有待完善。

  • 後面打算強化數據分析,並且還要實現錯誤的回放機制,思路的話以前也調研過,參考之前的一篇文章

  現在的這個系統還只能算是個玩具,後期還需要雕琢雕琢。下面是這套系統的目錄結構。

├── pingapple --------------------------------- 菠蘿監控系統
│   ├── client -------------------------------- 系統的前端部分
│   ├── sdk ----------------------------------- 信息搜集代碼庫
│   ├── server -------------------------------- 系統的後端部分

一、SDK

1)primus.js

  在之前的《前端頁面性能參數搜集》一文中,詳細記載了各類性能指標的計算規則,並整理到了primus.js中。

  本次將在primus.js的基礎上做適當的修改,包括刪除代理、測速、資源信息等功能,改變部分性能指標的計算規則,例如從瀏覽器發起HTTP請求算起,忽略瀏覽器重定向的時間等。

2)錯誤處理

  完善錯誤處理,將錯誤分成三類:runtime、load和Promise。在window的error事件中,處理前兩種錯誤。像img元素載入的圖片地址不存在,就會執行formatLoadError()函數;像變量未定義,就會執行formatRuntimerError()函數。

window.addEventListener("error", function (event) {
    var errorTarget = event.target;
    // 過濾 target 為 window 的異常
    if (
      errorTarget !== window &&
      errorTarget.nodeName &&
      LOAD_ERROR_TYPE[errorTarget.nodeName.toUpperCase()]
    ) {
      handleError(formatLoadError(errorTarget));
    } else {
      handleError(
        formatRuntimerError(
          event.message,
          event.filename,
          event.lineno,
          event.colno,
          event.error
        )
      );
    }
  }, true
);

  將window綁定unhandledrejection事件后,就會在Promise被拒絕且沒有reject的回調函數時觸發。

window.addEventListener(
  "unhandledrejection",
  function (event) {
    // console.log('Unhandled Rejection at:', event.promise, 'reason:', event.reason);
    handleError({
      type: ERROR_PROMISE,
      desc: event.reason,
      stack: "no stack"
    });
  },
  true
);

3)初始化

  由於要計算白屏時間,DOM時間等,所以位置不能隨便放,得要放在head的最後面。

<head>
  <script>
    window.pineapple || (pineapple = {});
    pineapple.param = {
      "token": "dsadasd2323dsad23dsada"
    };
  </script>
  <script src="js/pineapple.js"></script>
</head>

二、服務端

1)Koa

  Koa是由Express原班人馬打造的Web輕量框架,通過組合各種中間件來避免繁瑣的回調函數嵌套,當前使用的版本是V2。

npm install --save koa

  使用的Koa腳手架:koa-generator,創建項目的結構,並且在此基礎上做了調整(目錄如下所示)。暫時還不會用到靜態資源和視圖層。

npm install -g koa-generator
├── server --------------------------------- 服務端
│   ├── bin -------------------------------- 命令
│   ├── config ----------------------------- 配置目錄
│   ├── controllers ------------------------ MVC中的邏輯層
│   ├── db --------------------------------- MVC中的數據層
│   ├── public ----------------------------- 靜態資源
│   ├── routes ----------------------------- 路由
│   ├── utils ------------------------------ 工具庫
│   ├── views ------------------------------ MVC中的視圖層
│   ├── app.js ----------------------------- 入口文件

  為了區分開發環境和生產環境,通過cross-env統一不同系統設置環境變量的方式。

npm install --save cross-env

  package.json中的命令如下,添加了環境配置。

"scripts": {
  "start": "node bin/www",
  "dev": "cross-env NODE_ENV=development ./node_modules/.bin/nodemon bin/www",
  "prd": "cross-env NODE_ENV=production pm2 start bin/www"
}

  prd按字面意思應該是生產環境的命令,其中使用了pm2,默認沒有安裝。還沒部署過Node.js,還不清楚裏面有多少坑。

npm install --save pm2

2)MongoDB

  MongoDB是一個開源的非關係型數據庫(圖1是下載界面),既沒有表、行等概念,也沒有固定的模式和結構,所有的數據以文檔(一個對象)的形式存儲。但其使用方式和關係型數據庫相似,並且還支持對數據建立索引,適用於高併發讀寫、海量數據存儲和實時分析等。

圖1

  注意,在安裝時默認會下載MongoDB Compress(一個可視化的MongoDB工具),默認下載會非常慢,建議自行下載,該工具的界面還是蠻清爽的,如圖2所示。

圖2

  在Mac上配置MongoDB比較麻煩,不像Windows那樣一件安裝,需要一些步驟,廢了點力氣才裝好,下面是執行的命令。

sudo mongod --dbpath=/Users/pw/data

3)Mongoose

  Mongoose是MongoDB的一個ORM(Object-Document Mapper,對象文檔映射)工具,可在Node.js環境中執行,封裝了MongoDB操作文檔的常用方法,包括引入數據庫連接(connect),定義模型(model),聲明文檔結構(scheme),實例化模型等操作數據庫的方法。

npm install --save mongoose

  借鑒了以前PHP數據分層的思想,單獨分離出數據庫的連接,並抽象通用的Model層(如下所示)。

const mongoose = require("./db");
class Mongodb {
  constructor(name, schema) {
    //聲明結構
    const mySchema = new mongoose.Schema(schema, { typeKey: "$type" });
    this.model = mongoose.model(name, mySchema);
  }
  //保存
  save(obj) {
    obj.created = Date.now();         //日期
    const doc = new this.model(obj);
    return new Promise((resolve, reject) => {
      doc.save((err, row) => {
        if (err) {
          reject(err);
          return;
        }
        resolve(row);
      });
    });
  }
}
module.exports = {
  model: Mongodb,
  mongoose
};

4)路由

  由於發送的地址是一張gif圖片,因此在處理路由時,返回本地的一張gif圖,如下所示,圖像地址得是絕對路徑,否則無法讀取。

router.get('/pa.gif', async (ctx, next) => {
  const ctr = new indexController();
  ctr.collect(ctx);
  const url = path.resolve(__dirname, "../public/images/blank.gif");
  ctx.body = fs.readFileSync(url);    //空白gif圖
});

5)代理分析

  在接收參數的時候分析代理所帶的信息,例如瀏覽器、操作系統、設備等。使用的是一個第三方庫:UAParser.js,四年前就關注過,當時GitHub上只有1K多個關注量,現在已經翻了4倍。

npm install --save ua-parser-js

6)假數據

  製作一套合適的假數據,新增命令“npm run data”,初始化數據,便於展示。

三、後台

1)UI

  後台模板採用了之前封裝過的Matrix,但不會依賴Bootstrap框架。

  將整個頁面分成五塊,分別是導航、側邊欄、麵包屑、底部欄以及主體。

  安裝react-router的history,用於路由。

npm install --save history

  期間也會安裝各類依賴包,例如不支持在類中直接聲明屬性等。

  在使用的過程中,ESLint會不時的彈出各種錯誤和警告,期間就不停的修改問題或查找相關配置忽略部分限制。

  後台的側邊欄和麵包屑等部分,會隨着URL的不同而發生狀態變化,本來想用多頁實現,但配置要改很多,就依然做成一個SPA,只是稍微做了些改動。

  組件庫採用了流行的Ant Design,調用了按鈕、單選框、日期等組件。

npm install --save antd

  圖表庫使用的是ECharts,目前只用到了折線圖和餅圖。在引用圖表時,為了優化構建,採取了按需引用的手段。

npm install --save echarts

2)項目管理

  首先建立一個項目,然後才能分析該項目的性能和錯誤,如圖3所示。

圖3

  用彈框的形式來創建項目,使用了Ant Design的Model、Form等組件,如圖4所示。

圖4

3)性能分析

  在第一個折線圖標籤中的過濾條件包括項目、字段、日期等,性能指標按平均值呈現,可看到每個性能指標的趨勢,如圖5所示。

圖5

  按分時日統計性能平均數,在MongoDB中計算。原先創建日期是以時間戳的形式存儲的,為了便於使用Aggregate,改成字符串形式。碰到一個坑,MongoDB中的Date類型採用的是格林尼治時間,而不是當前時區的時間,也就是說存在數據庫中的時間會比當前時間早8小時。

  在第二個列表標籤中,可以詳細看到每條記錄的信息,包括代理、網絡等,便於在了解趨勢的前提下,獲悉更為細節的內容,如圖6所示。

圖6

  點擊ajax那一列,可彈出具體的異步請求信息,如圖7所示。

圖7

4)錯誤分析

  有三個標籤,第一個也是折線圖,描繪的是某個時間的錯誤個數;第二個是錯誤列表,會給出具體的錯誤信息,如圖8所示。

圖8

  第三個是餅圖,餅圖主要體現的是發生錯誤的瀏覽器分佈情況(如圖9所示),點擊某一塊可查看瀏覽器的具體版本(如圖10所示)。

圖9

圖10

 

 

【參考資料】
PerformanceTiming

unhandledrejection 處理沒有顯式捕獲的 Promise 異常

狼書(卷2)

Node-區分環境

Koa從零搭建到Api實現—項目部署

koa如何連接MongoDB

Koa2進階學習筆記

如何計算首屏加載時間 

Mongoose Schema Error: “Cast to string failed for value” when pushing object to empty array

Support for the experimental syntax ‘classProperties’ isn’t currently enabled

Template string failing with Cannot read property ‘range’ of null

Disallow JSX props spreading (react/jsx-props-no-spreading)

TypeError: Cannot read property ‘range’ of null from template-curly-spacing

echarts項目的優化

使用 happypack 提升 Webpack 項目構建速度

mac下的mongoDB的安裝和啟動

安裝MongoDB報錯 mkdir: /data/db: Read-only file system

$sum mongoose

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

GitHub 熱點速覽 Vol.24:程序員自我增值,優雅賺零花錢

摘要:升職加薪,出任 CTO,迎娶白富美/高帥富,走向人生巔峰是很多人的夢想。在本期的熱點速覽中你將了解自由作者 Easy 如何優雅賺取零花錢的方法,以及定投改變命運 —— 讓時間陪你慢慢變富。說到程序員自我增值,除了優雅賺錢之外,還可以研究下各種生活中小工具的代碼實現,例如,收錄 20+ Web 小應用的 vanillawebprojects。將技術應用在生活中點滴,展現你的技術輔助日常“肝”口袋妖精,或者偶爾用技術給自己生活添加點小樂趣,用遺傳算法製作一個繪製圖像過程的小玩具。

以下內容摘錄自微博@HelloGitHub 的 GitHub Trending,選項標準:新發布 | 實用 | 有趣,根據項目 release 時間分類,發布時間不超過 7 day 的項目會標註 New,無該標誌則說明項目 release 超過一周。由於本文篇幅有限,還有部分項目未能在本文展示,望周知

  • 本文目錄
      1. 本周特推
      • 1.1 遺傳算法玩具:genetic-drawing
      • 1.2 馬斯克火箭:SpaceX-API
      1. GitHub Trending 周榜
      • 2.1 Go 語法書:go-ast-book
      • 2.2 數據庫好搭檔:xgenecloud
      • 2.3 前端小玩意:vanillawebprojects
      • 2.4 統計代碼:lihang-code
      • 2.5 Poke 輔助工具:Pokedex
      • 2.6 高性能框架:Fastapi
      • 2.7 JS 面經:javascript-questions
      1. 本周 GitHub Trending #程序員增值# 主題的主力軍
      • 3.1 優雅賺錢:howto-make-more-money
      • 3.2 定投改變命運:regular-investing-in-box
      • 3.3 機器學習課程個人筆記:Coursera-ML-AndrewNg-Notes
      1. 推薦閱讀

1. 本周特推

1.1 遺傳算法玩具:genetic-drawing

本周 star 增長數:1200+

Newgenetic-drawing 作者在 2017 年做的模仿給定目標圖像的繪製過程的玩具項目,效果見下圖。項目受到互聯網上許多基因繪製示例的啟發,由於項目深受歡迎,作者便在近日將其開源。

GitHub 地址→https://github.com/anopara/genetic-drawing

1.2 馬斯克火箭:SpaceX-API

本周 star 增長數:900+

SpaceX-API 是一個用於火箭、核心艙、太空艙、發射台和發射數據的開源 REST API。技術棧

  • 部署在美國中部 Linode 服務器上
  • 使用了 Nodejs 的 Koa 框架
  • 使用了 Redis、Nginx 和 Cloudflare 進行內容緩存
  • 使用了 Jest 和 Supertest 做測試
  • 使用了 Circle CI 進行持續集成/部署
  • 所有的數據存儲在 MongoDB Atlas 3 節點的副本集集群中
  • 使用 mongodump 在晚上進行數據備份

GitHub 地址→https://github.com/r-spacex/SpaceX-API

2. GitHub Trending 周榜

2.1 Go 語法書:go-ast-book

本周 star 增長數:1000+

go-ast-book 是一個 Go 語法樹入門項目。讓我們語法樹這個維度重新審視 Go 語言程序,我們將得到創建Go語言本身的技術。本書簡單介紹語法樹相關包的使用。

GitHub 地址→https://github.com/chai2010/go-ast-book

2.2 數據庫好搭檔:xgenecloud

本周 star 增長數:800+

New xgenecloud 是一個能即時生成任何數據庫上的 REST 和 GraphQL API 工具,它支持 MySQL、PostgreSQL、MsSQL、SQLite、MariaDB。特性:

  • 為現有數據庫生成 REST API
  • 提供用於調試的 GUI
  • 生成的 API 均可基於 Serverless 部署在任意雲平台

GitHub 地址→https://github.com/xgenecloud/xgenecloud

2.3 前端小玩意:vanillawebprojects

本周 star 增長數:1100+

vanillawebprojects 收錄了用前端技術(Javascript、CSS、HTML5)開發的 20+ 款小應用,包括:表單驗證、匯率計算、打字遊戲、語音閱讀、新年倒計時等等。

GitHub 地址→https://github.com/bradtraversy/vanillawebprojects

2.4 統計代碼:lihang-code

本周 star 增長數:10900+

《統計學習方法》可以說是機器學習的入門寶典,許多機器學習培訓班、互聯網企業的面試、筆試題目,很多都參考這本書。本項目收錄了該書的所有代碼實現,特別是監督學習方法,包括感知機、k 近鄰法、樸素貝恭弘=叶 恭弘斯法、決策樹、邏輯斯諦回歸與支持向量機、提升方法、em 算法、隱馬爾可夫模型和條件隨機場等。

GitHub 地址→https://github.com/fengdu78/lihang-code

2.5 Poke 輔助工具:Pokedex

本周 star 增長數:500+

NewPokedex 使用基於 MVVM 架構的 Dagger Hilt、Motion、Coroutines、Jetpack 開發的 Poke(口袋妖精)輔助工具。這個項目專註實現依賴注入的新庫,支持從網絡獲取數據,並通過存儲庫模式集成數據庫中的持久化數據。

GitHub 地址→https://github.com/skydoves/Pokedex

2.6 高性能框架:Fastapi

本周 star 增長數:1300+

Fastapi 是一個基於 python 的框架,該框架鼓勵使用 Pydantic 和 OpenAPI 進行文檔編製,使用 Docker 進行快速開發和部署以及基於 Starlette 框架進行的簡單測試。特性:

  • 高性能
  • 快速編寫代碼:將功能開發的速度提高大約 200% 至 300%
  • 錯誤更少:減少約40%的人為錯誤(開發人員)
  • 直觀:強大的編輯器支持。完成無處不在。調試時間更少
  • 簡易:旨在易於使用和學習。減少閱讀文檔的時間
  • 短:最小化代碼重複。每個參數聲明中的多個功能,更少的錯誤
  • 健壯:獲取可用於生產的代碼,具有自動交互式文檔。
  • 基於標準:基於(並完全兼容)API的開放標準

GitHub 地址→https://github.com/tiangolo/fastapi

2.7 JS 面經:javascript-questions

本周 star 增長數:800+

從基礎到高級,JavaScript Questions 收錄了 JS 相關的面試題及解法。

GitHub 地址→https://github.com/lydiahallie/javascript-questions

3. 本周 GitHub Trending #程序員增值#主題的主力軍

在本期主題模塊,小魚乾這裏選取了 3 個和增值相關的小工具,希望能提高你生活、工作的幸福值。

3.1 優雅賺錢:howto-make-more-money

howto-make-more-money 是一個程序員@Easy 現身講述優雅的掙零花錢的項目,雖然是一個教你如何賺零花錢的項目,但是通過閱讀本賺零花錢小書你可理清自己的核心資源,以及如何創造資產。

GitHub 地址→https://github.com/easychen/howto-make-more-money

3.2 定投改變命運:regular-investing-in-box

定投改變命運 —— 讓時間陪你慢慢變富。regular-investing-in-box 這本書要講的是普通人擺脫階層固化的路徑 —— 絕對可行,毫無水分,並且全靠你自己。這裏所說的普通人,不分國界、不分地域、不分種族、不分性別、不分年齡、不分高矮胖瘦美醜、不分何種性取向…… 關鍵在於,甚至壓根不分智商和學歷!換言之,這個解決方案,甚至對在北京跑腿送外賣的小哥都適用……

GitHub 地址→https://github.com/xiaolai/regular-investing-in-box

3.3 機器學習課程個人筆記:Coursera-ML-AndrewNg-Notes

Coursera-ML-AndrewNg-Notes 是吳恩達老師的機器學習課程個人筆記,旨在提供了一個廣泛的介紹機器學習、數據挖掘、統計模式識別的課程。主題包括:

  • 監督學習(參數/非參數算法,支持向量機,核函數,神經網絡)。
  • 無監督學習(聚類,降維,推薦系統,深入學習推薦)。
  • 在機器學習的最佳實踐(偏差/方差理論;在機器學習和人工智能創新過程)。

項目還將使用大量的案例研究,你可學習到如何運用學習算法構建智能機器人(感知,控制),文本的理解(Web 搜索,反垃圾郵件),計算機視覺,醫療信息,音頻,數據挖掘,和其他領域。

GitHub 地址→https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes

推薦閱讀

  • GitHub 熱點速覽 Vol.23:前後端最佳實踐
  • GitHub 熱點速覽 Vol.22:如何打造超級技術棧
  • GitHub 熱點速覽 Vol.21:Go 新手起手式,學就完事兒了

以上為 2020 年第 23 個工作周的 GitHub Trending 如果你 Pick 其他好玩、實用的 GitHub 項目,記得來 HelloGitHub issue 區和我們分享下喲

HelloGitHub 交流群現已全面開放,添加微信號:HelloGitHub 為好友入群,可同前端、Java、Go 等各界大佬談笑風生、切磋技術~

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(七)

系列文章

  1. 基於 abp vNext 和 .NET Core 開發博客項目 – 使用 abp cli 搭建項目
  2. 基於 abp vNext 和 .NET Core 開發博客項目 – 給項目瘦身,讓它跑起來
  3. 基於 abp vNext 和 .NET Core 開發博客項目 – 完善與美化,Swagger登場
  4. 基於 abp vNext 和 .NET Core 開發博客項目 – 數據訪問和代碼優先
  5. 基於 abp vNext 和 .NET Core 開發博客項目 – 自定義倉儲之增刪改查
  6. 基於 abp vNext 和 .NET Core 開發博客項目 – 統一規範API,包裝返回模型
  7. 基於 abp vNext 和 .NET Core 開發博客項目 – 再說Swagger,分組、描述、小綠鎖
  8. 基於 abp vNext 和 .NET Core 開發博客項目 – 接入GitHub,用JWT保護你的API
  9. 基於 abp vNext 和 .NET Core 開發博客項目 – 異常處理和日誌記錄
  10. 基於 abp vNext 和 .NET Core 開發博客項目 – 使用Redis緩存數據
  11. 基於 abp vNext 和 .NET Core 開發博客項目 – 集成Hangfire實現定時任務處理
  12. 基於 abp vNext 和 .NET Core 開發博客項目 – 用AutoMapper搞定對象映射
  13. 基於 abp vNext 和 .NET Core 開發博客項目 – 定時任務最佳實戰(一)
  14. 基於 abp vNext 和 .NET Core 開發博客項目 – 定時任務最佳實戰(二)
  15. 基於 abp vNext 和 .NET Core 開發博客項目 – 定時任務最佳實戰(三)
  16. 基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(一)
  17. 基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(二)
  18. 基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(三)
  19. 基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(四)
  20. 基於 abp vNext 和 .NET Core 開發博客項目 – 博客接口實戰篇(五)
  21. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(一)
  22. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(二)
  23. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(三)
  24. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(四)
  25. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(五)
  26. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(六)
  27. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(七)
  28. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(八)
  29. 基於 abp vNext 和 .NET Core 開發博客項目 – Blazor 實戰系列(九)
  30. 基於 abp vNext 和 .NET Core 開發博客項目 – 終結篇之發布項目

上一篇完成了後台分類模塊的所有功能,本篇繼續將標籤模塊和友情鏈接模塊的增刪改查完成。

標籤管理

實現方式和之前的分類管理是一樣的,在Admin文件夾下面添加Tags.razor組件,設置路由@page "/admin/tags"

同樣的內容也需要放在AdminLayout組件下面,添加幾個參數:彈窗狀態bool Open、新增或更新時標籤字段string tagName, displayName、更新時的標籤Idint id、API返回的標籤列表接收參數ServiceResult<IEnumerable<QueryTagForAdminDto>> tags

/// <summary>
/// 默認隱藏Box
/// </summary>
private bool Open { get; set; } = false;

/// <summary>
/// 新增或者更新時候的標籤字段值
/// </summary>
private string tagName, displayName;

/// <summary>
/// 更新標籤的Id值
/// </summary>
private int id;

/// <summary>
/// API返回的標籤列表數據
/// </summary>
private ServiceResult<IEnumerable<QueryTagForAdminDto>> tags;
//QueryTagForAdminDto.cs
namespace Meowv.Blog.BlazorApp.Response.Blog
{
    public class QueryTagForAdminDto : QueryTagDto
    {
        /// <summary>
        /// 主鍵
        /// </summary>
        public int Id { get; set; }
    }
}

在初始化方法OnInitializedAsync()中獲取數據。

/// <summary>
/// 初始化
/// </summary>
/// <returns></returns>
protected override async Task OnInitializedAsync()
{
    var token = await Common.GetStorageAsync("token");
    Http.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");

    tags = await FetchData();
}

/// <summary>
/// 獲取數據
/// </summary>
/// <returns></returns>
private async Task<ServiceResult<IEnumerable<QueryTagForAdminDto>>> FetchData()
{
    return await Http.GetFromJsonAsync<ServiceResult<IEnumerable<QueryTagForAdminDto>>>("/blog/admin/tags");
}

注意需要設置請求頭,進行授權訪問,然後頁面上綁定數據。

<AdminLayout>
    @if (tags == null)
    {
        <Loading />
    }
    else
    {
        <div class="post-wrap tags">
            <h2 class="post-title">-&nbsp;Tags&nbsp;-</h2>
            @if (tags.Success && tags.Result.Any())
            {
                <div class="categories-card">
                    @foreach (var item in tags.Result)
                    {
                        <div class="card-item">
                            <div class="categories">
                                <NavLink title="刪除" @onclick="@(async () => await DeleteAsync(item.Id))"></NavLink>
                                <NavLink title="編輯" @onclick="@(() => ShowBox(item))"></NavLink>
                                <NavLink target="_blank" href="@($"/tag/{item.DisplayName}")">
                                    <h3>@item.TagName</h3>
                                    <small>(@item.Count)</small>
                                </NavLink>
                            </div>
                        </div>
                    }
                    <div class="card-item">
                        <div class="categories">
                            <NavLink><h3 @onclick="@(() => ShowBox())">~~~ 新增標籤 ~~~</h3></NavLink>
                        </div>
                    </div>
                </div>
            }
            else
            {
                <ErrorTip />
            }
        </div>

        <Box OnClickCallback="@SubmitAsync" Open="@Open">
            <div class="box-item">
                <b>DisplayName:</b><input type="text" @bind="@displayName" @bind:event="oninput" />
            </div>
            <div class="box-item">
                <b>TagName:</b><input type="text" @bind="@tagName" @bind:event="oninput" />
            </div>
        </Box>
    }
</AdminLayout>

tags沒獲取到數據的時候显示<Loading />組件內容,循環遍曆數據進行綁定,刪除按鈕綁定點擊事件調用DeleteAsync()方法。新增和編輯按鈕點擊事件調用ShowBox()方法显示彈窗。新增的時候不需要傳遞參數,編輯的時候需要將當前item即QueryTagForAdminDto傳遞進去。

<Box>組件中綁定了標籤的兩個參數,是否打開參數Opne和確認按鈕回調事件方法SubmitAsync()

刪除標籤的方法DeleteAsync(...)如下:

// 彈窗確認
bool confirmed = await Common.InvokeAsync<bool>("confirm", "\n真的要幹掉這個該死的標籤嗎");

if (confirmed)
{
    var response = await Http.DeleteAsync($"/blog/tag?id={id}");

    var result = await response.Content.ReadFromJsonAsync<ServiceResult>();

    if (result.Success)
    {
        tags = await FetchData();
    }
}

刪除之前進行二次確認,避免誤傷,刪除成功重新加載一遍數據。

彈窗的方法ShowBox(...)如下:

/// <summary>
/// 显示box,綁定字段
/// </summary>
/// <param name="dto"></param>
private void ShowBox(QueryTagForAdminDto dto = null)
{
    Open = true;
    id = 0;

    // 新增
    if (dto == null)
    {
        displayName = null;
        tagName = null;
    }
    else // 更新
    {
        id = dto.Id;
        displayName = dto.DisplayName;
        tagName = dto.TagName;
    }
}

最後在彈窗中確認按鈕的回調事件方法SubmitAsync()如下:

/// <summary>
/// 確認按鈕點擊事件
/// </summary>
/// <returns></returns>
private async Task SubmitAsync()
{
    var input = new EditTagInput()
    {
        DisplayName = displayName.Trim(),
        TagName = tagName.Trim()
    };

    if (string.IsNullOrEmpty(input.DisplayName) || string.IsNullOrEmpty(input.TagName))
    {
        return;
    }

    var responseMessage = new HttpResponseMessage();

    if (id > 0)
        responseMessage = await Http.PutAsJsonAsync($"/blog/tag?id={id}", input);
    else
        responseMessage = await Http.PostAsJsonAsync("/blog/tag", input);

    var result = await responseMessage.Content.ReadFromJsonAsync<ServiceResult>();
    if (result.Success)
    {
        tags = await FetchData();
        Open = false;
    }
}

輸入參數EditTagInput

namespace Meowv.Blog.BlazorApp.Response.Blog
{
    public class EditTagInput : TagDto
    {
    }
}

最終執行新增或者更新數據都在點擊事件中進行,將變量的值賦值給EditTagInput,根據id判斷走新增還是更新,成功后重新加載數據,關掉彈窗。

標籤管理頁面全部代碼如下:

點擊查看代碼

@page "/admin/categories"

<AdminLayout>
    @if (categories == null)
    {
        <Loading />
    }
    else
    {
        <div class="post-wrap categories">
            <h2 class="post-title">-&nbsp;Categories&nbsp;-</h2>
            @if (categories.Success && categories.Result.Any())
            {
                <div class="categories-card">
                    @foreach (var item in categories.Result)
                    {
                        <div class="card-item">
                            <div class="categories">
                                <NavLink title="刪除" @onclick="@(async () => await DeleteAsync(item.Id))"></NavLink>
                                <NavLink title="編輯" @onclick="@(() => ShowBox(item))"></NavLink>
                                <NavLink target="_blank" href="@($"/category/{item.DisplayName}")">
                                    <h3>@item.CategoryName</h3>
                                    <small>(@item.Count)</small>
                                </NavLink>
                            </div>
                        </div>
                    }
                    <div class="card-item">
                        <div class="categories">
                            <NavLink><h3 @onclick="@(() => ShowBox())">~~~ 新增分類 ~~~</h3></NavLink>
                        </div>
                    </div>
                </div>
            }
            else
            {
                <ErrorTip />
            }
        </div>

        <Box OnClickCallback="@SubmitAsync" Open="@Open">
            <div class="box-item">
                <b>DisplayName:</b><input type="text" @bind="@displayName" @bind:event="oninput" />
            </div>
            <div class="box-item">
                <b>CategoryName:</b><input type="text" @bind="@categoryName" @bind:event="oninput" />
            </div>
        </Box>
    }
</AdminLayout>

@code {
    /// <summary>
    /// 默認隱藏Box
    /// </summary>
    private bool Open { get; set; } = false;

    /// <summary>
    /// 新增或者更新時候的分類字段值
    /// </summary>
    private string categoryName, displayName;

    /// <summary>
    /// 更新分類的Id值
    /// </summary>
    private int id;

    /// <summary>
    /// API返回的分類列表數據
    /// </summary>
    private ServiceResult<IEnumerable<QueryCategoryForAdminDto>> categories;

    /// <summary>
    /// 初始化
    /// </summary>
    /// <returns></returns>
    protected override async Task OnInitializedAsync()
    {
        var token = await Common.GetStorageAsync("token");
        Http.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");

        categories = await FetchData();
    }

    /// <summary>
    /// 獲取數據
    /// </summary>
    /// <returns></returns>
    private async Task<ServiceResult<IEnumerable<QueryCategoryForAdminDto>>> FetchData()
    {
        return await Http.GetFromJsonAsync<ServiceResult<IEnumerable<QueryCategoryForAdminDto>>>("/blog/admin/categories");
    }

    /// <summary>
    /// 刪除分類
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    private async Task DeleteAsync(int id)
    {
        Open = false;

        // 彈窗確認
        bool confirmed = await Common.InvokeAsync<bool>("confirm", "\n真的要幹掉這個該死的分類嗎");

        if (confirmed)
        {
            var response = await Http.DeleteAsync($"/blog/category?id={id}");

            var result = await response.Content.ReadFromJsonAsync<ServiceResult>();

            if (result.Success)
            {
                categories = await FetchData();
            }
        }
    }

    /// <summary>
    /// 显示box,綁定字段
    /// </summary>
    /// <param name="dto"></param>
    private void ShowBox(QueryCategoryForAdminDto dto = null)
    {
        Open = true;
        id = 0;

        // 新增
        if (dto == null)
        {
            displayName = null;
            categoryName = null;
        }
        else // 更新
        {
            id = dto.Id;
            displayName = dto.DisplayName;
            categoryName = dto.CategoryName;
        }
    }

    /// <summary>
    /// 確認按鈕點擊事件
    /// </summary>
    /// <returns></returns>
    private async Task SubmitAsync()
    {
        var input = new EditCategoryInput()
        {
            DisplayName = displayName.Trim(),
            CategoryName = categoryName.Trim()
        };

        if (string.IsNullOrEmpty(input.DisplayName) || string.IsNullOrEmpty(input.CategoryName))
        {
            return;
        }

        var responseMessage = new HttpResponseMessage();

        if (id > 0)
            responseMessage = await Http.PutAsJsonAsync($"/blog/category?id={id}", input);
        else
            responseMessage = await Http.PostAsJsonAsync("/blog/category", input);

        var result = await responseMessage.Content.ReadFromJsonAsync<ServiceResult>();
        if (result.Success)
        {
            categories = await FetchData();
            Open = false;
        }
    }
}

友鏈管理

實現方式都是一樣的,這個就不多說了,直接上代碼。

先將API返回的接收參數和新增編輯的輸入參數添加一下。

//QueryFriendLinkForAdminDto.cs
namespace Meowv.Blog.BlazorApp.Response.Blog
{
    public class QueryFriendLinkForAdminDto : FriendLinkDto
    {
        /// <summary>
        /// 主鍵
        /// </summary>
        public int Id { get; set; }
    }
}

//EditFriendLinkInput.cs
namespace Meowv.Blog.BlazorApp.Response.Blog
{
    public class EditFriendLinkInput : FriendLinkDto
    {
    }
}
@page "/admin/friendlinks"

<AdminLayout>
    @if (friendlinks == null)
    {
        <Loading />
    }
    else
    {
        <div class="post-wrap categories">
            <h2 class="post-title">-&nbsp;FriendLinks&nbsp;-</h2>
            @if (friendlinks.Success && friendlinks.Result.Any())
            {
                <div class="categories-card">
                    @foreach (var item in friendlinks.Result)
                    {
                        <div class="card-item">
                            <div class="categories">
                                <NavLink title="刪除" @onclick="@(async () => await DeleteAsync(item.Id))"></NavLink>
                                <NavLink title="編輯" @onclick="@(() => ShowBox(item))"></NavLink>
                                <NavLink target="_blank" href="@item.LinkUrl">
                                    <h3>@item.Title</h3>
                                </NavLink>
                            </div>
                        </div>
                    }
                    <div class="card-item">
                        <div class="categories">
                            <NavLink><h3 @onclick="@(() => ShowBox())">~~~ 新增友鏈 ~~~</h3></NavLink>
                        </div>
                    </div>
                </div>
            }
            else
            {
                <ErrorTip />
            }
        </div>

        <Box OnClickCallback="@SubmitAsync" Open="@Open">
            <div class="box-item">
                <b>Title:</b><input type="text" @bind="@title" @bind:event="oninput" />
            </div>
            <div class="box-item">
                <b>LinkUrl:</b><input type="text" @bind="@linkUrl" @bind:event="oninput" />
            </div>
        </Box>
    }
</AdminLayout>

@code {
    /// <summary>
    /// 默認隱藏Box
    /// </summary>
    private bool Open { get; set; } = false;

    /// <summary>
    /// 新增或者更新時候的友鏈字段值
    /// </summary>
    private string title, linkUrl;

    /// <summary>
    /// 更新友鏈的Id值
    /// </summary>
    private int id;

    /// <summary>
    /// API返回的友鏈列表數據
    /// </summary>
    private ServiceResult<IEnumerable<QueryFriendLinkForAdminDto>> friendlinks;

    /// <summary>
    /// 初始化
    /// </summary>
    /// <returns></returns>
    protected override async Task OnInitializedAsync()
    {
        var token = await Common.GetStorageAsync("token");
        Http.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");

        friendlinks = await FetchData();
    }

    /// <summary>
    /// 獲取數據
    /// </summary>
    /// <returns></returns>
    private async Task<ServiceResult<IEnumerable<QueryFriendLinkForAdminDto>>> FetchData()
    {
        return await Http.GetFromJsonAsync<ServiceResult<IEnumerable<QueryFriendLinkForAdminDto>>>("/blog/admin/friendlinks");
    }

    /// <summary>
    /// 刪除分類
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    private async Task DeleteAsync(int id)
    {
        Open = false;

        // 彈窗確認
        bool confirmed = await Common.InvokeAsync<bool>("confirm", "\n真的要幹掉這個該死的分類嗎");

        if (confirmed)
        {
            var response = await Http.DeleteAsync($"/blog/friendlink?id={id}");

            var result = await response.Content.ReadFromJsonAsync<ServiceResult>();

            if (result.Success)
            {
                friendlinks = await FetchData();
            }
        }
    }

    /// <summary>
    /// 显示box,綁定字段
    /// </summary>
    /// <param name="dto"></param>
    private void ShowBox(QueryFriendLinkForAdminDto dto = null)
    {
        Open = true;
        id = 0;

        // 新增
        if (dto == null)
        {
            title = null;
            linkUrl = null;
        }
        else // 更新
        {
            id = dto.Id;
            title = dto.Title;
            linkUrl = dto.LinkUrl;
        }
    }

    /// <summary>
    /// 確認按鈕點擊事件
    /// </summary>
    /// <returns></returns>
    private async Task SubmitAsync()
    {
        var input = new EditFriendLinkInput()
        {
            Title = title.Trim(),
            LinkUrl = linkUrl.Trim()
        };

        if (string.IsNullOrEmpty(input.Title) || string.IsNullOrEmpty(input.LinkUrl))
        {
            return;
        }

        var responseMessage = new HttpResponseMessage();

        if (id > 0)
            responseMessage = await Http.PutAsJsonAsync($"/blog/friendlink?id={id}", input);
        else
            responseMessage = await Http.PostAsJsonAsync("/blog/friendlink", input);

        var result = await responseMessage.Content.ReadFromJsonAsync<ServiceResult>();
        if (result.Success)
        {
            friendlinks = await FetchData();
            Open = false;
        }
    }
}

截至目前為止,還剩下文章模塊的功能還沒做了,今天到這裏吧,明天繼續剛,未完待續…

開源地址:https://github.com/Meowv/Blog/tree/blog_tutorial

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※產品缺大量曝光嗎?你需要的是一流包裝設計!