波塞冬:伴魚運營活動前端配置化實踐

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"前言","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"波塞冬,是伴魚活動運營解決方案的總稱,包含活動規則體系、h5 可視化開發平臺等,名稱來源於古希臘神話,波塞冬是海洋和所有水系的管理者,寓意爲 palfish 發展提供超能力。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"目前的問題","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/06/06f2d8fa9529424c46040c5025933f2c.png","alt":"avatar","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"隨着伴魚業務的高速發展,大量促增長的活動接踵而來, 原有的研發模式暴漏出一系列問題,如後端邏輯混雜、複用度低、維護成本高,前端靈活性差、效率低,爲了提升公司運營效率,我們急需探索一套符合公司現狀的技術體系,爲公司的業務高速發展提供平臺支撐。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"萬物終有源,要解決掉面臨的問題,我們從整個研發、運營鏈路出發尋找答案。研發鏈路上在前後端分離的技術大背景下,我們的目標是要最大化的實現後端服務複用、前端頁面複用,對運營而言是能夠快速靈活的對活動策略、展示作出修改,來查驗各種活動對業務的作用效果,基於以上思考,我們抽象了波塞冬平臺的業務模型。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"平臺概覽","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/bf/bf0a2b832dd5fe6626fc3c00f93fbb04.png","alt":"avatar","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"波塞冬平臺主要分爲三大部分:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基礎服務規則:如消息通知、用戶畫像等服務。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"各種業務類型規則:例如拼團、簽到、任務等類型的規則服務,在業務層面集成基礎規則服務。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"h5 可視化管理平臺:集成業務規則層邏輯,完成輸出給 c 端用戶。","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲什麼要這樣分呢?我們結合現在運營場景進行簡述。運營的呈現宣傳方式以分爲線下,線上兩種方式,這裏我們只談線上。每一場運營活動都需要一些通用的服務,比如活動需要發送消息(微信、短信、站內信等),來增加活動的曝光,對於不同特徵的用戶我們希望展示不同的分流策略,這裏有些用戶特是不區別業務線的,比如用戶基礎信息(性別、年齡等);有些跟業務線強耦合,比如繪本的會員,少兒一對一的購買等,這些我們在應用層都統一成畫像規則,最後由各業務畫像規則引擎解析提供給下游消費,此類的基礎能力我們統稱爲基礎服務規則。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在基礎服務之外還會有各種類型的活動,比如業務常用的任務玩法(錄製繪本、去分享),簽到玩法、拼團玩法等此類的玩法在服務層是可高度固化的,形式標準的 FaaS 服務(函數即服務),同樣爲了對運營友好使用,我們做成標準的業務規則模版,在業務規則層面通常會結合基礎服務,比如一個拼團活動需要對新老客發送不同的獎勵,對任務中的用戶來發送通知提醒,督促用戶來成活動。這樣每一次的規則相互解耦,又可以靈活組合,從而達到服務高度複用,效率提升的目標。以上兩層主要解決了服務端的複用。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於 c 端我們應該如何複用?答案當然是組件化能力建設、可視化能力建設的範疇了,鑑於當前活動主推的運營場景是 h5 活動下面我們會重點介紹一下 h5 可視化平臺的建設。以上就是對三大模塊拆分的場景。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"h5 可視化開發的部分","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可視化開發一直是前端開發的熱點話題,幾乎所有大的公司都有自己的可視化配置平臺,我們在建設可視化平臺之前也做了充分的調研,下面以平臺對比和總結的方式介紹。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"業界對比","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"h5 可視化平臺的建設我們也調研了很多業界很多相關的資料,下面做了簡單的彙總。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/23/2309bf113d302902a31058e2c551facb.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"總結要點","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ff/ff357f5b96cd864ee2ced68bea9beca9.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過對業界的總結,我們需要尋找出符合公司技術現狀的技技術方案。這裏先描述一下 h5 活動開發的現狀,現在每個業務線的 h5 活動都放在各自代碼倉庫,由於活動的性質(週期短,頻次高)造成了了代碼倉庫的不斷膨脹,且很多活動都是經過多次迭代,代碼經手多人,代碼邏輯不清晰,長時間會造成很多冗餘代碼,導致的結果就是維護成本上升,研發效率降低。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"此外活動的變更也是比較頻繁的很多就是文字描述、背景圖片等,這些改動不管是提測中,還是上線後都在發生,每次小的改動都需要走代碼提交,發佈的流程,且每次小的變更都需要全量發佈,(比如多個活動同步進行,一些將要發佈的代碼已經合併到 master,而小的變更急需發佈)產生一定項目風險。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基於上述的描述總結一下問題:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"代碼倉庫龐大,長期代碼冗餘加劇,維護成本高,導致代碼質量、研發效率降低。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對運營的支撐不靈活,小的發版對整體項目造成安全隱患。","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"因此基於質量、效率、安全的緯度,我將 h5 可視化平臺劃分爲三個模塊","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"組件開發腳手架:我們提供了腳手架讓開發高效、規範化的進行組的開發與發佈","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可視化編輯器:提供將組件拼裝成頁面的能力。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"管理後臺:人員、組件、頁面等緯度的權限與版本管理能力。","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"組件開發","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"該模塊我們要從代碼源頭把握研發的質量與效率,因此腳手架提供了統一的組件開發模版,且每個組件在發佈時候都需要關聯到 git 源代碼管理的倉庫,這樣就將原有龐大的代碼倉庫,以研發組件緯度進行了倉庫解耦,到這裏你可能會有疑問,解耦之後我的通用模塊如何調用?比如橋功能,接口調用,這裏我們結合 webpack 的生態能力,在研發模式下,我們將通用能力的以 externals 的形式在組件中調用,同時在打包發佈階段只發布組件本身的內容,從而減少了組件代碼體積。當然影響研發效率的問題還有很多,比如 h5 開發通常用到橋的能力,本地預覽的能力,屬性編輯的能力等這裏我們都研發對應的模擬橋工具,動態表單,iframe 等模式來解決上面的問題。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了去研發模式的思考,基於業務我們也將組件進行了劃分,方便對業務進行有力的支撐,以下是我們的組件模塊劃分。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"業務組件:顧名思義就是我們之前整理好各種常用業務規則所開發的組件,爲特定業務所服務,比如我在業務規則 服務劃分的時候有拼團、簽到等服務模塊,對應的展示層我們一些通用的組件方便類似業務的直接使用。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"基礎組件:基礎組件是我們常用的基本 ui 組件,比如按鈕,文本、圖片等,達到基礎的視圖要求。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"功能組件(待討論):這個是我們比較特殊的一個組件類型,業務組件與基礎組件都有一些通用的行爲,比如我點擊按鈕彈出橋分享的能力以及對組件統計曝光的能力,此類的組件沒有 ui 的作用,僅提爲組件注入通用的交互行爲。","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面以圖文的形式大家作下展示","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/9a/9aa47800b64a588e9ec1e6175b9d2854.png","alt":"avatar","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這是我們組件開發的界面,爲了可以更好的給開發者提供開發環境,我們集成了編輯器的所有功能,從而保證展示效果是一致的。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"功能","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"組件作爲整個波塞冬重要的部分,在設計的時候我們考慮集成了以下大功能:","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"配置數據","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對頁面的可編輯部分, 需要準確描述可編輯部分所需的配置數據; 配置數據是異構的, 不同頁面、不同區塊的配置數據各不相同。所以需要對不同頁面、不同區塊定義各自配置數據的數據結構和字段類型。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"最理想的配置數據格式爲 JSON, 因爲其格式靈活, 前端友好; 最理想的配置數據描述是 JSON Schema, 因爲其支持表單動態生成和數據校驗。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"組件交互","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面我們有講到,將所有的組件代碼解耦分佈在不同的倉庫,看下圖描述的場景。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/9d/9d0d80b08fa61735d98d7fbeedb0d845.png","alt":"avatar","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們最終要解決的是不同組件的通信問題,跨組件通信大家都不陌生,比如EventBus等,結合到業務我們需要解決將組件的內部的方法暴露給其他組件,並且在指定的綁定事件(點擊、焦點等)中觸發方法。在實踐中劃分兩部分解決這個問題:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"1)組件開發階段,在組件描述的中定義方法名字,比如我們約定描述屬性名稱爲editorMethods,需要對外暴露的方法爲goShare,這樣組件就對外提供了方法。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"2)組件編輯階段,編輯器內部維護了一個存放當前組件中所有對外方法的數組,以及可以交互的事件,當選中具體組件的時候,可以指定綁定組件的事件方法。下圖爲在編輯器中的使用展示。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c0/c0ed084de947d57cd6f658feec4aa930.png","alt":"avatar","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"數據總線","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"數據總線主要解決了組件之間數據共享問題。同樣結合下面圖的場景理解,後端接口的數據多個組件都會使用到,每個組件中都調用一次接口會造成性能問題。vuex可以很好的解決這個問題,在編輯器內部定義約定Store的對象,不同的接口數據設置不同的Store對象屬性,既可實現數據共享的能力。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/93/939cb71c9b4632da7a04572166c262bf.png","alt":"avatar","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"頁面模板","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"模板是帶有默認數據的頁面; 對於組件化的頁面, 模板是從組件庫中選取部分組件, 並帶有各個組件的默認數據。採用模板生成頁面, 只需對模板進行少量編輯即可實現頁面快速生成,比如項目中沉澱了許多海報模版,,素材庫模版,直播模版等","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"頁面編輯器","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原有的方式中都是一個代碼倉庫中代碼形式的組件複用,編輯器讓組件的複用也可視化的方式,簡單的頁面組裝讓非研發同學也可以做頁面。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b2/b26ed193343dcf5dbb7de82e91db8f3b.png","alt":"avatar","title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這是我們波塞冬編輯器的編輯頁面,總共五個部分。頂部主要是我們的頁面設置部分,提供了頁面的保存發佈預覽等功能。下部分從左往右依次是:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"組件列表:這裏展示我們通過組件工具發佈的所有組件。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"頁面組件樹:頁面組件樹是頁面的骨架,由內置的各個組件組成。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"展示編輯區域:這裏主要是進行組件的位置操作,拖拽組件的位置,進行頁面編輯。","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"屬性模塊:因爲每個組件都有可配置的屬性,這裏主要是根據選中的組件進行配置,比如按鈕組件的顏色大小等,取決於這個組件有什麼屬性。","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"管理後臺","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"管理後臺是整個可視化的控制樞紐,重點在於對業務場景應用的管控。做爲一個平臺組件可以隨心所欲的發佈,但不可發佈的組件並不能都生效,因此平臺要對發佈組件做質量檢查,通過過審覈後才能在可視化編輯區使用;同樣頁面可以隨意的創建,但是不能讓別人輕易動我創建的頁面,比如 a 業務的同學,編輯併發布了 b 業務的頁面,因此在頁面上層我們劃分了項目團隊的概念,只有項目中的成員可以修改歸屬於項目的頁面。現在我們發佈頁面方便了,原有代碼部署的方式發現錯誤我們可以快速回滾,這裏我們同樣提供了頁面回滾的能力,每次的編輯器內發佈的內容都會有一條 content 內容發佈記錄,方便回滾歷史提交,以上就是對後臺的介紹。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"展望","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"目前波塞冬平臺體系還處於建設的初級階段,可視化部分承載了目前業務內的所有海報生成工作以及部分活動頁面,在互聯網已經進入下半場輿論下,用戶運營已經成爲各大公司的重中之重,能夠對用戶做到精細化的運營,對公司成本、效率越來越重要,做爲技術人員我們以技術驅動產生平臺,用平臺支撐業務發展,從而使公司變得更大更強,未來我們期待波塞冬體系能夠成爲建設完成,成爲真正的海神。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"參考文獻","attrs":{}}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://juejin.im/post/6844903608614387720","title":null},"content":[{"type":"text","text":"頁面可視化搭建工具前生今世","attrs":{}}]}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://tech.meituan.com/2017/03/09/waimai-lego.html","title":null},"content":[{"type":"text","text":"美團樂高","attrs":{}}]}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://godspen.ymm56.com/","title":null},"content":[{"type":"text","text":"godspen","attrs":{}}]}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章