国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
NetBPM工作流之架構設計及實現(xiàn)淺析 (轉 LuBen Park - 博客園)

NetBPM工作流的架構設計及實現(xiàn)淺析

Made by LuBen:2007年08月01日


目錄

NetBPM組件接口

       定義組件(Definition Component)

       運行組件(Execution Component)

       組織架構組件(Oorganization Component)

       日志組件(Log Component)

       任務調度組件(Scheduler Component)

       管理監(jiān)控組件(Admin Component)

NetBpm中的幾個重要概念

       flow

       attributes(屬性)

       引擎運行時上下文環(huán)境(Execution Context)

       委托類

流程定義版本問題

異常處理機制

流程定義元素類圖

NetBpm中使用的框架或組件

       IOC容器――Castle

       數(shù)據(jù)持久層―― NHibernate

       示例Web層――MonoRail

       系統(tǒng)日志 ――Log4Net

       單元測試工具――NUnit

后記


讀前的話:由于本文涉及內容頗多,若有地方讀來不很明白,建議先跳過,整體上有個認識后,再回過頭來理解。作者認識有限,若有錯誤,歡迎斧正:)原文地址: NetBPM工作流的架構設計及實現(xiàn)淺析(轉載請保留)

NetBPM組件接口

    NetBPM由一系列的組件構成,每一個組件都實現(xiàn)一個核心接口(采用Facade Pattern)。不同組件各自負責的核心功能根據(jù)WfMC規(guī)范而來。
    NetBPM接口圖:

 
  1. 為流程開發(fā)者提供的接口(Process Developer):該接口負責加載流程定義到NetBpm引擎。首先,流程開發(fā)者依照nPdl創(chuàng)建一個流程定義,并將其打包成流程定義壓縮包(該包包含一個業(yè)務流程的所有信息),然后通過NetBPM Web界面或者是其他方式把流程定義壓縮包加載到NetBPM引擎,在加載過程中流程定義壓縮包將會被解析被保存到NetBPM數(shù)據(jù)庫中。
  2. 為用戶提供的接口(User):這里用戶表示執(zhí)行流程的人。流程運行主要有2種行為:開始一個流程和執(zhí)行一個活動(activity)。開始一個流程將創(chuàng)建該流程的一個流程實例,一個流程實例對應流程定義的一次執(zhí)行。一個流程實例包含了一個或多個并行的flow-of-execution(見flow)。對于處在activity-state(活動節(jié)點,見nPdl)的flow,系統(tǒng)一定會指派一個具體的人(或者組)或者第三方來執(zhí)行活動(activity)。執(zhí)行活動是Execution Interface的第二種行為。當然了,運轉接口還會實現(xiàn)一些其他的方法如獲取任務列表,獲取有效流程定義列表等。  
  3. 外部IT系統(tǒng)(External IT Systems)和NetBpm引擎之間的接口:外部IT系統(tǒng)能以2種方式實現(xiàn)和NetBPM的交互。
    •  系統(tǒng)發(fā)起交互:系統(tǒng)直接和外部IT系統(tǒng)交互。當系統(tǒng)想要觸發(fā)流程中的某一個action時,它必須使用上面提到的Execution Interface。
    •  流程發(fā)起交互:對于流程發(fā)起交互這種類型來說,需要有Interactors。這些Interactors是流程定義的一部分,它包含在流程定義包內(實際上Interactors就是能夠訪問FlowContext的.NET程序集,也就是我們后面要說到的包含委托類的程序集合)。Interactors在FlowContext(FLOW運行上下文環(huán)境)和外部IT系統(tǒng)之間建立起了通信渠道。
  4. 組織架構數(shù)據(jù)(Organisational Datastore)和NetBpm之間的接口:仔細想想,NetBpm是不是還缺了點什么,沒錯,那就是組織架構的信息:比如說人、團隊、部門、角色等。因為在現(xiàn)實情況中,對于不同的組織結構,組織架構信息可能被保存在不同類型的數(shù)據(jù)庫中,如LDAP系統(tǒng),關系型數(shù)據(jù)庫等。為了讓NetBPM能夠在一個現(xiàn)實的組織架構中實現(xiàn)快速部署,NetBPM把所有的組織架構信息都聚集在一個組件(Organisation Component)中。這種做法也就是我們通常說道會話門面模式(Session Façade Pattern),它使得NetBPM訪問來自不同數(shù)據(jù)源的組織架構信息變得更為簡單。

     下面我們逐步介紹NetBPM的各個組件,下面是NetBpm組件結構圖:

 

定義組件(Definition Component)

     該組件實現(xiàn)核心接口IDefinitionSessionLocal,用來解析、加載流程定義壓縮包,并將其保存到數(shù)據(jù)庫中。此外,它還提供獲取某個流程定義,獲取所有有效流程定義列表等和流程定義相關的方法。

運轉組件(Execution Component)

     該組件實現(xiàn)了核心接口IExecutionSessionLocal,它是NetBPM引擎推動核心,如前面如述,它主要實現(xiàn)2個方法:開始一個流程實例(Start ProcessInstance)和執(zhí)行一個活動(Perform Activity)。另外,它還提供獲取用戶任務列表,取消流程實例等輔助流程運轉的方法。

組織架構組件(Organization Component)

     該組件實現(xiàn)接口IOrganisationSessionLocal,它把所有的組織架構信息都聚集在一起,包括Users、Groups和Memberships。運轉組件在為activitie-state指定執(zhí)行者時,需要有關user和group的信息。這些信息將以只讀模式由組織架構組件向運轉組件提供。下面是NetBPM默認的組織架構組織數(shù)據(jù)模型。在此基礎上,我們可以很方便的實現(xiàn)自定義的適合實際項目需求的組織架構組件,以和我們的用戶數(shù)據(jù)庫或者是LDAP系統(tǒng)相關聯(lián)。

     NOTE:NetBPM源碼中實現(xiàn)的只是一個簡單的組織架構模型,但它提供了一種思考方向,我們可以很方便在此基礎上進行擴展來實現(xiàn)滿足切實需求的自定義組織架構組件:)

日志組件(Log Component)

     該組件實現(xiàn)接口ILogSessionLocal,用來記錄工作流引擎的操作痕跡,象屬性值的更新(如用戶提交的表單被上級打回重新填寫,那么就會出現(xiàn)多次表單數(shù)據(jù),這就是一種屬性更新),委托類的調用情況等都會被記錄下來保存到數(shù)據(jù)庫中。

任務調度組件(scheduler component)

     該組件實現(xiàn)接口ISchedulerSessionLocal,在現(xiàn)實的業(yè)務流程中,我們經(jīng)常會遇到需要定時觸發(fā)某個任務的需求,任務調度組件正是作用于此。引擎或者是第三方把需要在某個時刻執(zhí)行的任務信息(包括任務執(zhí)行環(huán)境、執(zhí)行時間等)封裝成Job保存到數(shù)據(jù)庫中。任務調度組件將按照指定的時間間隔不停的掃描任務表,根據(jù)執(zhí)行時間對比來執(zhí)行定時到了的Job。

管理監(jiān)控組件(Admin Component)

     該組件用來對流程定義,流程實例執(zhí)行情況等進行監(jiān)控。(源碼待完善)下面是NetBpm核心項目在Visual 該組件用來對流程定義,流程實例執(zhí)行情況等進行監(jiān)控。(源碼待完善)

 下面是NetBPM核心項目在Visual Studio解決方案中的源碼結構圖,所有組件都包含在Workflow文件夾下,每一個文件夾分別對應實現(xiàn)了一個核心組件。
 

 

NetBpm中的幾個重要概念

flow

     flow不知道翻譯為什么好,在JBPM中叫做Token,翻譯為令牌,這里我們就叫做flow吧。它代表activity-states(活動節(jié)點,見nPdl)的一個“thread of execution”,相當于是一次流程實例執(zhí)行過程中在流程定義模板中的令牌(還真難描述清楚,看下面一起理解:))。前面說了,一個流程實例代表一個流程定義的一次執(zhí)行。如下圖所示,流程實例的狀態(tài)可以看成是一顆flows樹。

      當開始一個流程實例后,在start-state(開始節(jié)點,見nPdl,start-state實際上可以看做是一種特殊的activity-state)引擎將自動產(chǎn)生一個名為root的flow。flow中包含了該流程實例的相關信息,如屬性值、流程定義信息、flow所在activity-state的執(zhí)行者等。root flow在遇到fork(分散節(jié)點,見nPdl)之前,將更新其帶有的實時信息(如執(zhí)行者、屬性值等),這些實時信息隨著流程的運轉而變化。遇到fork后,根據(jù)ForkHandler委托類,root flow將分散成若干(>1個)forked flow(我們可以把root flow稱為這些forked flow的父flow)。若是分散為多個,則此時forked flow將并行運行,父flow則暫時退隱,只至到join(匯聚節(jié)點,見nPdl)匯聚,引擎將根據(jù)join定義的JoinHandler委托類來確定激活父flow的機制。

     NOTE:關于fork和join機制,請參考nPdl fork、join小節(jié)一起理解。

attributes(屬性)

     attribute用來表示流程實例中的變量。一個attribute-instance(屬性實例,也就是屬性值)代表一次流程實例執(zhí)行過程中對應屬性的實例。屬性一般有幾種,一種是activity-state(包括start-state)需要用戶或者第三方來填寫(更新)的屬性(一般對應用戶Web界面表單上要填寫的值),一種是角色對應的屬性,還有一些用作標識屬性(用來存儲某些信息以方便后面的節(jié)點運用這些信息處理邏輯判斷)。

  1. serializer(屬性的序列化):

    Serializer和HtmlFormatter都是委托類,Serializer負責把屬性實例在.NET-Objects和文本兩種狀態(tài)間進行轉換,以方便把屬性值存入和取出數(shù)據(jù)庫。而Htmlformatter主要用來聯(lián)系屬性值和Web Forms顯示時對應的http-text。
  2. attribute的范圍:attribute-instances(屬性實例)和flow有關。在process-definition(流程定義根節(jié)點,見nPdl)節(jié)點中定義的attribute和root-flow關聯(lián),而在concurrnet-block(并行運行塊,見nPdl)中定義的局部attribute實例則和forked flow關聯(lián)。一個flow能夠“看見”和它關聯(lián)的所有屬性以及該flow的父flow的所有屬性。

引擎運行時上下文環(huán)境(Execution Context)

    

因為圖片太大,關于繼承IHandlerContext的接口關系圖查看點擊這里

     ExecutionContext(ExecutionContextImpl類型的對象,我們暫且翻譯為運行時上下文環(huán)境:)) 包含了引擎在運行時和流程實例相關的所有有用信息(上文中提到的flowcontext就是一種ExecutionContext),它在委托類(包括流程定義壓縮包中程序集中定義的委托類)和流程引擎之間建立起了相互聯(lián)系的渠道,這是非常關鍵的。如上面ExectutionContext 類圖所示,ExecutionContextImpl實現(xiàn)了下面這些接口:IAssignmentContext、IDecisionContext、IForkContext、IActionContext、IJoinContext、IProcessInvocationContext、ITaskContext,這些接口都是為匹配特定的委托類而設計,它們規(guī)范了一種特定的上下文環(huán)境,如IActionContext匹配action類型委托類,IDecisionContext匹配DecisionHandler類型委托類等,而ExectutionContext是所有這些特殊的運行時上下文環(huán)境的一個綜合。當引擎在運轉組件把ExectutionContext作為參數(shù)傳送到具體類型的委托類時(關鍵:這就是委托類和流程引擎建立聯(lián)系的方式),ExecutionContext對象將“拆箱”成為特殊的Context,如:把ExecutionContext對象傳給action類型的委托類Run()方法時,ExecutionContext對象將拆箱為ActionContext對象以限制其能夠調用的方法。

     如“繼承自IHandlerContext的接口”圖中所示,這些接口都繼承了同一個接口IHandlerContext。IHandlerContext是一個規(guī)范了最基本的委托類處理上下文環(huán)境的接口,實現(xiàn)該接口的繼承幾口也就都要實現(xiàn)IHandlerContext中定義的方法,當然每一種繼承它的特定接口又都可以具有其特定的方法。我們先看公共接口IHanlderContext類圖:如上IHandlerContext接口圖所示,這些接口都繼承了同一個接口IHandlerContext。IHandlerContext是一個規(guī)范了最基本的委托類處理上下文環(huán)境的接口,實現(xiàn)該接口繼承接口的類也就都實現(xiàn)了IHandlerContext中定義的方法。當然,每一種繼承它的特定接口又都可以具有其特定的方法。我們先看公共接口IHanlderContext類圖:

     大多數(shù)的方法,我們從方法名稱就可以看出其具體作用了,這里重點介紹下GetAttribute()方法和GetConfiguration()方法,這是我們在寫委托類實現(xiàn)時,要經(jīng)常用到的2個方法。GetAttribute()用來獲取流程實例中的屬性值,包括流程前面處理者產(chǎn)生的屬性值(如用戶填寫表單的值)和前面處理引擎事件中設置的表示屬性值(注:IActionHandler具有SetAttribute()方法,該方法經(jīng)常用來標識屬性值,供后面程序邏輯用)等。而GetConfiguration()用來獲取流程定義中設置的parameter(參數(shù),請nPdlparameter小節(jié))。

     下面再來看幾種典型的特定上下文環(huán)境接口:

  • IAssignmentContext:為IAssignmentHandler委托類提供引擎上下文環(huán)境,該接口定義了獲取組織架構信息的方法,具體實現(xiàn)方法見類圖。
  • IActionContext:為action提供引擎上下文環(huán)境,注意其具有SetAttribute的方法,可以為流程實例中的屬性賦值,具體實現(xiàn)方法見類圖。
  • IForkContext:為IForkHandler委托類提供引擎上下文環(huán)境,它定義了如何從父flow分散forked flow的方法,見類圖。
  • IJoinContext:為IJoinHandler委托類提供引擎上下文環(huán)境,它定義了獲取其他并行flows的方法,見類圖。
  • IProcessInvocationContext: 為IProcessInvocationHandler委托提供引擎上下文環(huán)境,實現(xiàn)方法見類圖。
  • 其他的委托類型上下文環(huán)境除了實現(xiàn)基本IHandlerContext方法外,沒有特定的方法,請參考IHandlerContext方法。

委托類

     在前面我們一直提到委托類,那么委托類到底是什么呢?這里委托的概念指的不是.NET Framework中delegate,這里可以理解它為“委托、代為處理”這樣的概念就好。

     NetBPM被設計成通用的流程處理引擎,NetBPM核心執(zhí)行引擎只負責處理最基本的業(yè)務流程邏輯,所有不定的邏輯都被委托給一系列的接口,這些接口稱作Delegation Interfaces(委托接口),而實現(xiàn)這些接口的類就是委托類。流程定義約定在什么場合使用什么委托類型,引擎和委托類如何關聯(lián)也在流程定義中完成。

    為了達到最大的可擴展性,流程開發(fā)者在流程定義時可以選擇下面任意一種委托類實現(xiàn)方式:

  1. 使用已經(jīng)在NetBpm引擎中實現(xiàn)的有效的委托類。(具有通用性的委托建議采用這種方式在引擎中定義,以便重用)
  2. 使用自定義的委托類,以.NET程序集的形式通過流程定義壓縮包動態(tài)加載。

     正是方式2這種形式給NetBPM帶來了極大的靈活性,把只適合于某個特定流程的的程序邏輯(這些往往占了大多數(shù))以.NET程序集的形式定義在流程定義壓縮包中,NetBpm通過流程定義組件將其解析并保存至數(shù)據(jù)庫。當引擎運轉流程需要調用委托類時,引擎利用反射技術實例化出委托類對象,然后利用上文介紹的運行時上下時環(huán)境(ExecutionContext)建立起委托類和引擎之間的交互渠道,這真是一個令人興奮的設計:)

     下面是NetBpm中的委托類型(建議和ExecutionContext一節(jié)一起理解):

  • AssignmentHandler
           實現(xiàn)接口IAssignmentHandler, 它可以和組織架構中的IT-System相互通信,用來為activty-state指定執(zhí)行者。IAssignmentHandler具有唯一的方法SelectActor(IAssignmentContext assignerContext),其中的assignerContext是其和引擎聯(lián)系的渠道;
  • ActionHandler:實現(xiàn)接口IActionHandler,它用來執(zhí)行一段流程引擎外完成的程序邏輯,關于action在哪里執(zhí)行,什么時候執(zhí)行等在流程定義中被定義。actions可以被看作一系列流程執(zhí)行事件的偵聽接口,它具有方法Run(IActionContext actionContext),actionContext是它和引擎聯(lián)系的渠道。
  • DecisionHandler:實現(xiàn)接口IDecisionHandler,它用來選擇決定走哪一條transition(邊,見nPdl),具有方法Decide(IDecisionContext decisionContext),該方法返回選擇要走的邊的名稱,decisionContext是其和引擎聯(lián)系的渠道。
  • ForkHandler:實現(xiàn)接口IForkHandler,當執(zhí)行到fork節(jié)點時,F(xiàn)orkhandler用來決定從fork流程的邊中哪些邊需要“forking”。它具有方法Fork(IForkContext forkContext),forkContext是其和引擎聯(lián)系的渠道。注:forkhandler可以在同一條邊上分散多個forked flow。
  • JoinHandler:實現(xiàn)接口IJoinHandler,當執(zhí)行到join時,JoinHandler決定是否要激活父flow,它具有方法Join(IJoinContext joinContext),joinContext是其和引擎聯(lián)系的渠道。
  • Serializer:實現(xiàn)接口ISerializer,具有方法Serialize(Object valueObject)和Deserialize(String text),該委托接口負責用來轉換屬性值,把屬性值在.NET-objects(.NET對象)和text-format(文本)之間轉換。其中,text-format(文本)用來存儲屬性值到數(shù)據(jù)庫中。
  • HtmlFormatter:實現(xiàn)接口IHtmlFormatter,該委托主要用來在屬性值和其相對應的web界面元素之間建立聯(lián)系,同時負責解析web界面元素具有的值。若移植到ASP.NET平臺,該接口建議重寫。
  • ProcessInvocationHandler:實現(xiàn)接口IProcessInvocationHandler,該委托實現(xiàn)收集子流程的初始化數(shù)據(jù)、收集處理結果、指定完成子流程后要流入的邊等方法,processInvocationContext是其和引擎聯(lián)系的渠道。

................///////////////////////////.............是否要添加委托類的例子


流程定義版本問題

流程定義的名稱與版本

     包含在一個流程定義壓縮包中的信息叫做流程定義。NetBpm中,流程是由字段name來區(qū)分的,也就是說引擎根據(jù)流程的name來判斷兩個流程是否相等。在流程定義包中不能指定版本,當一個流程定義被引擎加載后,NetBpm將檢查是否有該流程定義的舊版本。如果有,NetBpm將自動設置該新加載進來的流程版本為所有存在的舊版本流程定義中最高版本數(shù)目基礎上加1。

流程執(zhí)行與版本

     當調用運轉組件獲取流程定義列表方法時,只能獲取到每個流程的最高版本流程定義。這樣做保證了用戶總是從最新版本的流程定義開始一個流程實例。當新的流程版本加載到NetBpm時,所有正在運行的舊版本的流程實例將保持在原來流程定義方式下運行。

委托類與版本

     關于版本的另外一個方面是委托類。不同版本流程定義的委托類不是共享的,也就是說每個流程在執(zhí)行時只會“看到”它自己流程定義的委托類。


異常處理機制

     NetBpm作為一個集成平臺,當流程運行時,肯定會依賴公司很多其他的IT資源,一旦這些依賴導致流程執(zhí)行時出現(xiàn)錯誤,NetBpm提供了3種解決機制:

  1. 忽略錯誤
  2. 把錯誤日志記錄下來(默認采用的機制)
  3. 錯誤執(zhí)行回滾操作(rollback)

    執(zhí)行回滾機制中,流程實例將會被回滾到執(zhí)行activity之前的狀態(tài)。如果是對NetBpm 調用Eecution Interface時發(fā)生流程錯誤,所有的流過的transition(邊)都會執(zhí)行回滾。


流程定義元素類圖

     關于流程定義的詳細情況,參見nPdl


 


NetBpm中使用的框架或組件

     NetBpm中用到的框架、組件、工具比較多,它們大都是優(yōu)秀的開源項目。如Castle,NHibernate,Log4Net, NVelocity,NUnit,NAnt等,不要被這些框架嚇倒,實際上,它們僅僅只是“框架”而已:)

IOC容器――Castle

     NetBpm使用了Castle框架,主要用它來實現(xiàn)IOC(控制反轉或者說依賴注入),以依賴注入的方式加載核心組件,如DBClassLoader,流程定義組件,運行組件,日志組件,組織架構組件,任務調度組件等。在Web程序啟動的時候,根據(jù)配置文件,所有的核心組件都將注冊到Caslte IOC容器中,以后當需要使用某個組件的時候,只需利用系統(tǒng)提供的ServiceLocator(服務加載工具類)從容器中獲取實例即可。另外,在任務調度組件中也有用到Castle的Startable Facility(注:大家把facility理解為注入性質的,對Castle IOC內核容器的功能擴充組件。Castle本身自帶實現(xiàn)了一些faciltiy,開發(fā)者也可以自定義facility),該facitlity主要用來自動運行程序(這里用來自動間隔掃描任務表,進行任務調度)。

     Castle是.NET平臺下一個功能強大的優(yōu)秀開源框架,關于Castle的更多信息,請看Castle官方網(wǎng)站。另外TerryLee的博客中關于Castle的中文資源也很豐富。

數(shù)據(jù)持久層―― NHibernate

     NetBpm中NHibernate組件是作為Castle的一個facility存在的,它用來實現(xiàn)NetBpm數(shù)據(jù)持久層, 并方便的實現(xiàn)了事務支持。關于NHibernate的更多信息,請看NHibernate官方網(wǎng)站,關于NHibernate作為Castle的facility相關請看這里。

示例web層――MonoRail

     大家在Demo演示體驗的時候,一定很奇怪,沒有看到熟悉的.aspx頁面,而是.rails頁面,為什么呢?答案就是NetBPM的Web層采用的是MonoRail框架,而不是我們熟悉ASP.NET框架。MonoRail是Caslte框架下針對web層編程的一個子框架,它從Ruby Rails獲取靈感而來,采用架構清晰分工明確的MVC模式。NetBPM采用的使用NVelocity作為頁面解析引擎的MonoRail,它只是對NetBPM核心API的一個Web界面演示示例,用來告訴我們該怎樣從Web層調用NetBpm API。所以,雖然MonoRail有其獨到之處,但是在其被普及并有好用工具支持之前,我們只需簡單了解下它的運行機制,用以熟悉web層如何利用NetBpm API,不需要了解它太多。用我們熟悉的ASP.NET實現(xiàn)Web部分顯然是更好的選擇:)。關于MonoRail的更多信息,請看這里。

系統(tǒng)日志 ――Log4Net

     log4net大家一定不陌生了,NetBpm使用它來記錄系統(tǒng)日志,關于log4net的更多信息,請看Log4Net官方網(wǎng)站,網(wǎng)上中文資源也很豐富.

單元測試工具――NUnit

     單元測試工具NUnit一直是大家用來單元測試的利器。 NetBPM源碼中已經(jīng)建有幾個測試工程。關于NUnit的更多信息,請看NUnit官方網(wǎng)站。

     注:移植到.NET Framework 2.0下,可能要更改其版本。


后記

     NetBPM的設計無疑是巧妙的,但是現(xiàn)階段的它顯然還不是一個完美的工作流引擎,缺乏如JBOSS這樣的強大后盾作支持,中途又遇上強敵WF,NetBPM遠沒有其兄弟JBPM風光,更新沒有它快(JBPM已經(jīng)出3.0版本了),獲取的支持也少許多, 但是.NET平臺下能有這樣一個優(yōu)秀的開源工作流項目是十分可貴的,如果您正在WF中苦苦掙扎,也許,開源的NetBPM將帶給您一個驚喜:)

待寫:NetBPM工作流nPdl詳解,一個NetBPM現(xiàn)實生活中請假審批示例

posted on 2007-08-04 13:37 LuBen 閱讀(663) 評論(0)  編輯 收藏 引用 網(wǎng)摘 所屬分類: WorkFlow & NetBpm

本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
值得關注
sunflow工作流管理系統(tǒng)v2.20
[轉]WfMC 工作流模型分類
三款工作流引擎比較:WWF、netBPM 和 ccflow
工作流術語和定義
認識工作流程引擎
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服