在线不卡日本ⅴ一区v二区_精品一区二区中文字幕_天堂v在线视频_亚洲五月天婷婷中文网站

  • <menu id="lky3g"></menu>
  • <style id="lky3g"></style>
    <pre id="lky3g"><tt id="lky3g"></tt></pre>

    管理訂單狀態(tài),該上狀態(tài)機(jī)嗎?

    管理訂單狀態(tài),該上狀態(tài)機(jī)嗎?

    前言

    在平常的后端項(xiàng)目開發(fā)中,狀態(tài)機(jī)模式的使用其實(shí)沒有大家想象中那么常見,筆者之前由于不在電商領(lǐng)域工作,很少在業(yè)務(wù)代碼中用狀態(tài)機(jī)來管理各種狀態(tài),一般都是手動(dòng)get/set狀態(tài)值。去年筆者進(jìn)入了電商領(lǐng)域從事后端開發(fā)。電商領(lǐng)域,狀態(tài)又多又復(fù)雜,如果仍然在業(yè)務(wù)代碼中東一塊西一塊維護(hù)狀態(tài)值,很容易陷入出了問題難于Debug,難于追責(zé)的窘境。

    碰巧有個(gè)新啟動(dòng)的項(xiàng)目需要進(jìn)行訂單狀態(tài)的管理,我著手將Spring StateMachine接入了進(jìn)來,管理購物訂單狀態(tài),不得不說,Spring StateMachine全家桶的文檔寫的是不錯(cuò),并且Spring StateMachine也是有官方背書的。但是,它實(shí)在是太”重“了,想要簡單修改一個(gè)訂單的狀態(tài),需要十分復(fù)雜的代碼來實(shí)現(xiàn)。具體就不在這里展開了,不然我感覺可以吐槽一整天。

    說到底Spring StateMachine上手難度非常大,如果沒有用來做重型狀態(tài)機(jī)的需求,十分不推薦普通的小項(xiàng)目進(jìn)行接入。

    最最重要的是,由于Spring StateMachine狀態(tài)機(jī)實(shí)例不是無狀態(tài)的,無法做到線程安全,所以代碼要么需要使用鎖同步,要么需要用Threadlocal,非常的痛苦和難用。 例如下面的Spring StateMachine代碼就用了重量級(jí)鎖保證線程安全,在高并發(fā)的互聯(lián)網(wǎng)應(yīng)用中,這種代碼留的隱患非常大。

    private synchronized boolean sendEvent(Message message, OrderEntity orderEntity) { boolean result = false; try { stateMachine.start(); // 嘗試恢復(fù)狀態(tài)機(jī)狀態(tài) persister.restore(stateMachine, orderEntity); // 執(zhí)行事件 result = stateMachine.sendEvent(message); // 持久化狀態(tài)機(jī)狀態(tài) persister.persist(stateMachine, (OrderEntity) message.getHeaders().get(“purchaseOrder”)); } catch (Exception e) { log.error(“sendEvent error”, e); } finally { stateMachine.stop(); } return result; }

    吃了一次虧后,我再一次在網(wǎng)上翻閱各種Java狀態(tài)機(jī)的實(shí)現(xiàn),有大的開源項(xiàng)目,也有小而美的個(gè)人實(shí)現(xiàn)。結(jié)果在COLA架構(gòu)中發(fā)現(xiàn)了COLA還寫了一套狀態(tài)機(jī)實(shí)現(xiàn)。COLA的作者給我們提供了一個(gè)無狀態(tài)的,輕量化的狀態(tài)機(jī),接入十分簡單。并且由于無狀態(tài)的特點(diǎn),可以做到線程安全,支持電商的高并發(fā)場景。

    COLA是什么?如果你還沒聽說過COLA,不妨看一看我之前的文章,傳送門如下:

    https://mp.weixin.qq.com/s/07i3FjcFrZ8rxBCACgeWVQ

    如果你需要在項(xiàng)目中引入狀態(tài)機(jī),此時(shí)此刻,我會(huì)推薦使用COLA狀態(tài)機(jī)。

    COLA狀態(tài)機(jī)介紹

    COLA狀態(tài)機(jī)是在Github開源的,作者也寫了介紹文章:

    https://blog.csdn.net/significantfrank/article/details/104996419

    官方文章的前半部分重點(diǎn)介紹了DSL(Domain Specific Languages),這一部分比較抽象和概念化,大家感興趣,可以前往原文查看。我精簡一下DSL的主要含義:

    什么是DSL? DSL是一種工具,它的核心價(jià)值在于,它提供了一種手段,可以更加清晰地就系統(tǒng)某部分的意圖進(jìn)行溝通。

    比如正則表達(dá)式,/d{3}-d{3}-d{4}/就是一個(gè)典型的DSL,解決的是字符串匹配這個(gè)特定領(lǐng)域的問題。

    文章的后半部分重點(diǎn)闡述了作者為什么要做COLA狀態(tài)機(jī)?想必這也是讀者比較好奇的問題。我?guī)痛蠹揖喴幌略牡谋硎觯?/p>

    • 首先,狀態(tài)機(jī)的實(shí)現(xiàn)應(yīng)該可以非常的輕量,最簡單的狀態(tài)機(jī)用一個(gè)Enum就能實(shí)現(xiàn),基本是零成本。
    • 其次,使用狀態(tài)機(jī)的DSL來表達(dá)狀態(tài)的流轉(zhuǎn),語義會(huì)更加清晰,會(huì)增強(qiáng)代碼的可讀性和可維護(hù)性。
    • 開源狀態(tài)機(jī)太復(fù)雜: 就我們的項(xiàng)目而言(其實(shí)大部分項(xiàng)目都是如此)。我實(shí)在不需要那么多狀態(tài)機(jī)的高級(jí)玩法:比如狀態(tài)的嵌套(substate),狀態(tài)的并行(parallel,fork,join)、子狀態(tài)機(jī)等等。
    • 開源狀態(tài)機(jī)性能差: 這些開源的狀態(tài)機(jī)都是有狀態(tài)的(Stateful)的,因?yàn)橛袪顟B(tài),狀態(tài)機(jī)的實(shí)例就不是線程安全的,而我們的應(yīng)用服務(wù)器是分布式多線程的,所以在每一次狀態(tài)機(jī)在接受請求的時(shí)候,都不得不重新build一個(gè)新的狀態(tài)機(jī)實(shí)例。

    所以COLA狀態(tài)機(jī)設(shè)計(jì)的目標(biāo)很明確,有兩個(gè)核心理念:

  • 簡潔的僅支持狀態(tài)流轉(zhuǎn)的狀態(tài)機(jī),不需要支持嵌套、并行等高級(jí)玩法。
  • 狀態(tài)機(jī)本身需要是Stateless(無狀態(tài))的,這樣一個(gè)Singleton Instance就能服務(wù)所有的狀態(tài)流轉(zhuǎn)請求了。
  • COLA狀態(tài)機(jī)的核心概念如下圖所示,主要包括:

    State:狀態(tài) Event:事件,狀態(tài)由事件觸發(fā),引起變化 Transition:流轉(zhuǎn),表示從一個(gè)狀態(tài)到另一個(gè)狀態(tài) External Transition:外部流轉(zhuǎn),兩個(gè)不同狀態(tài)之間的流轉(zhuǎn) Internal Transition:內(nèi)部流轉(zhuǎn),同一個(gè)狀態(tài)之間的流轉(zhuǎn) Condition:條件,表示是否允許到達(dá)某個(gè)狀態(tài) Action:動(dòng)作,到達(dá)某個(gè)狀態(tài)之后,可以做什么 StateMachine:狀態(tài)機(jī)

    COLA狀態(tài)機(jī)原理

    這一小節(jié),我們先講幾個(gè)COLA狀態(tài)機(jī)最重要兩個(gè)部分,一個(gè)是它使用的連貫接口,一個(gè)是狀態(tài)機(jī)的注冊和使用原理。如果你暫時(shí)對(duì)它的實(shí)現(xiàn)原理不感興趣,可以直接跳過本小節(jié),直接看后面的實(shí)戰(zhàn)代碼部分。

    PS:講解的代碼版本為cola-component-statemachine 4.2.0-SNAPSHOT

    下圖展示了COLA狀態(tài)機(jī)的源代碼目錄,可以看到非常的簡潔。

    1. 連貫接口 Fluent Interfaces

    COLA狀態(tài)機(jī)的定義使用了連貫接口Fluent Interfaces,連貫接口的一個(gè)重要作用是,限定方法調(diào)用的順序。比如,在構(gòu)建狀態(tài)機(jī)的時(shí)候,我們只有在調(diào)用了from方法后,才能調(diào)用to方法,Builder模式?jīng)]有這個(gè)功能。

    下圖中可以看到,我們在使用的時(shí)候是被嚴(yán)格限制的:

    StateMachineBuilder builder = StateMachineBuilderFactory.create(); builder.externalTransition() .from(States.STATE1) .to(States.STATE2) .on(Events.EVENT1) .when(checkCondition()) .perform(doAction());

    這是如何實(shí)現(xiàn)的?其實(shí)是使用了Java接口來實(shí)現(xiàn)。

    2. 狀態(tài)機(jī)注冊和觸發(fā)原理

    這里簡單梳理一下狀態(tài)機(jī)的注冊和觸發(fā)原理。

    用戶執(zhí)行如下代碼來創(chuàng)建一個(gè)狀態(tài)機(jī),指定一個(gè)MACHINE_ID:

    StateMachine stateMachine = builder.build(MACHINE_ID);

    COLA會(huì)將該狀態(tài)機(jī)在StateMachineFactory類中,放入一個(gè)ConcurrentHashMap,以狀態(tài)機(jī)名為key注冊。

    static Map stateMachineMap = new ConcurrentHashMap();

    注冊好后,用戶便可以使用狀態(tài)機(jī),通過類似下方的代碼觸發(fā)狀態(tài)機(jī)的狀態(tài)流轉(zhuǎn):

    stateMachine.fireEvent(StateMachineTest.States.STATE1, StateMachineTest.Events.EVENT1, new Context(“1”));

    內(nèi)部實(shí)現(xiàn)如下:

  • 首先判斷COLA狀態(tài)機(jī)整個(gè)組件是否初始化完成。
  • 通過routeTransition尋找是否有符合條件的狀態(tài)流轉(zhuǎn)。
  • transition.transit執(zhí)行狀態(tài)流轉(zhuǎn)。
  • transition.transit方法中:

    檢查本次流轉(zhuǎn)是否符合condition,符合,則執(zhí)行對(duì)應(yīng)的action。

    COLA狀態(tài)機(jī)實(shí)戰(zhàn)

    **PS:以下實(shí)戰(zhàn)代碼取自COLA官方倉庫測試類

    一、狀態(tài)流轉(zhuǎn)使用示例

  • 從單一狀態(tài)流轉(zhuǎn)到另一個(gè)狀態(tài)
  • @Testpublic void testExternalNormal(){ StateMachineBuilder builder = StateMachineBuilderFactory.create(); builder.externalTransition() .from(States.STATE1) .to(States.STATE2) .on(Events.EVENT1) .when(checkCondition()) .perform(doAction()); StateMachine stateMachine = builder.build(MACHINE_ID); States target = stateMachine.fireEvent(States.STATE1, Events.EVENT1, new Context()); Assert.assertEquals(States.STATE2, target);}private Condition checkCondition() { return (ctx) -> {return true;};}private Action doAction() { return (from, to, event, ctx)->{ System.out.println(ctx.operator+” is operating “+ctx.entityId+” from:”+from+” to:”+to+” on:”+event); };}

    可以看到,每次進(jìn)行狀態(tài)流轉(zhuǎn)時(shí),檢查checkCondition(),當(dāng)返回true,執(zhí)行狀態(tài)流轉(zhuǎn)的操作doAction()。

    后面所有的checkCondition()和doAction()方法在下方就不再重復(fù)貼出了。

  • 從多個(gè)狀態(tài)流傳到新的狀態(tài)
  • @Testpublic void testExternalTransitionsNormal(){ StateMachineBuilder builder = StateMachineBuilderFactory.create(); builder.externalTransitions() .fromAmong(States.STATE1, States.STATE2, States.STATE3) .to(States.STATE4) .on(Events.EVENT1) .when(checkCondition()) .perform(doAction()); StateMachine stateMachine = builder.build(MACHINE_ID+”1″); States target = stateMachine.fireEvent(States.STATE2, Events.EVENT1, new Context()); Assert.assertEquals(States.STATE4, target);}

  • 狀態(tài)內(nèi)部觸發(fā)流轉(zhuǎn)
  • @Testpublic void testInternalNormal(){ StateMachineBuilder builder = StateMachineBuilderFactory.create(); builder.internalTransition() .within(States.STATE1) .on(Events.INTERNAL_EVENT) .when(checkCondition()) .perform(doAction()); StateMachine stateMachine = builder.build(MACHINE_ID+”2″); stateMachine.fireEvent(States.STATE1, Events.EVENT1, new Context()); States target = stateMachine.fireEvent(States.STATE1, Events.INTERNAL_EVENT, new Context()); Assert.assertEquals(States.STATE1, target);}

  • 多線程測試并發(fā)測試
  • @Testpublic void testMultiThread(){ buildStateMachine(“testMultiThread”); for(int i=0 ; i{ StateMachine stateMachine = StateMachineFactory.get(“testMultiThread”); States target = stateMachine.fireEvent(States.STATE1, Events.EVENT1, new Context()); Assert.assertEquals(States.STATE2, target); }); thread.start(); } for(int i=0 ; i { StateMachine stateMachine = StateMachineFactory.get(“testMultiThread”); States target = stateMachine.fireEvent(States.STATE1, Events.EVENT4, new Context()); Assert.assertEquals(States.STATE4, target); }); thread.start(); } for(int i=0 ; i { StateMachine stateMachine = StateMachineFactory.get(“testMultiThread”); States target = stateMachine.fireEvent(States.STATE1, Events.EVENT3, new Context()); Assert.assertEquals(States.STATE3, target); }); thread.start(); }}

    由于COLA狀態(tài)機(jī)時(shí)無狀態(tài)的狀態(tài)機(jī),所以性能是很高的。相比起來,SpringStateMachine由于是有狀態(tài)的,就需要使用者自行保證線程安全了。

    二、多分支狀態(tài)流轉(zhuǎn)示例

    /*** 測試選擇分支,針對(duì)同一個(gè)事件:EVENT1* if condition == “1”, STATE1 –> STATE1* if condition == “2” , STATE1 –> STATE2* if condition == “3” , STATE1 –> STATE3*/@Testpublic void testChoice(){ StateMachineBuilder builder = StateMachineBuilderFactory.create(); builder.internalTransition() .within(StateMachineTest.States.STATE1) .on(StateMachineTest.Events.EVENT1) .when(checkCondition1()) .perform(doAction()); builder.externalTransition() .from(StateMachineTest.States.STATE1) .to(StateMachineTest.States.STATE2) .on(StateMachineTest.Events.EVENT1) .when(checkCondition2()) .perform(doAction()); builder.externalTransition() .from(StateMachineTest.States.STATE1) .to(StateMachineTest.States.STATE3) .on(StateMachineTest.Events.EVENT1) .when(checkCondition3()) .perform(doAction()); StateMachine stateMachine = builder.build(“ChoiceConditionMachine”); StateMachineTest.States target1 = stateMachine.fireEvent(StateMachineTest.States.STATE1, StateMachineTest.Events.EVENT1, new Context(“1”)); Assert.assertEquals(StateMachineTest.States.STATE1,target1); StateMachineTest.States target2 = stateMachine.fireEvent(StateMachineTest.States.STATE1, StateMachineTest.Events.EVENT1, new Context(“2”)); Assert.assertEquals(StateMachineTest.States.STATE2,target2); StateMachineTest.States target3 = stateMachine.fireEvent(StateMachineTest.States.STATE1, StateMachineTest.Events.EVENT1, new Context(“3”)); Assert.assertEquals(StateMachineTest.States.STATE3,target3); }

    可以看到,編寫一個(gè)多分支的狀態(tài)機(jī)也是非常簡單明了的。

    三、通過狀態(tài)機(jī)反向生成PlantUml圖

    沒想到吧,還能通過代碼定義好的狀態(tài)機(jī)反向生成plantUML圖,實(shí)現(xiàn)狀態(tài)機(jī)的可視化。(可以用圖說話,和產(chǎn)品對(duì)比下狀態(tài)實(shí)現(xiàn)的是否正確了。)

    四、特殊使用示例

  • 不滿足狀態(tài)流轉(zhuǎn)條件時(shí)的處理
  • @Testpublic void testConditionNotMeet(){ StateMachineBuilder builder = StateMachineBuilderFactory.create(); builder.externalTransition() .from(StateMachineTest.States.STATE1) .to(StateMachineTest.States.STATE2) .on(StateMachineTest.Events.EVENT1) .when(checkConditionFalse()) .perform(doAction()); StateMachine stateMachine = builder.build(“NotMeetConditionMachine”); StateMachineTest.States target = stateMachine.fireEvent(StateMachineTest.States.STATE1, StateMachineTest.Events.EVENT1, new StateMachineTest.Context()); Assert.assertEquals(StateMachineTest.States.STATE1,target);}

    可以看到,當(dāng)checkConditionFalse()執(zhí)行時(shí),永遠(yuǎn)不會(huì)滿足狀態(tài)流轉(zhuǎn)的條件,則狀態(tài)不會(huì)變化,會(huì)直接返回原來的STATE1。相關(guān)源碼在這里:

  • 重復(fù)定義相同的狀態(tài)流轉(zhuǎn)
  • @Test(expected = StateMachineException.class)public void testDuplicatedTransition(){ StateMachineBuilder builder = StateMachineBuilderFactory.create(); builder.externalTransition() .from(StateMachineTest.States.STATE1) .to(StateMachineTest.States.STATE2) .on(StateMachineTest.Events.EVENT1) .when(checkCondition()) .perform(doAction()); builder.externalTransition() .from(StateMachineTest.States.STATE1) .to(StateMachineTest.States.STATE2) .on(StateMachineTest.Events.EVENT1) .when(checkCondition()) .perform(doAction());}

    會(huì)在第二次builder執(zhí)行到on(StateMachineTest.Events.EVENT1)函數(shù)時(shí),拋出StateMachineException異常。拋出異常在on()的verify檢查這里,如下:

  • 重復(fù)定義狀態(tài)機(jī)
  • @Test(expected = StateMachineException.class)public void testDuplicateMachine(){ StateMachineBuilder builder = StateMachineBuilderFactory.create(); builder.externalTransition() .from(StateMachineTest.States.STATE1) .to(StateMachineTest.States.STATE2) .on(StateMachineTest.Events.EVENT1) .when(checkCondition()) .perform(doAction()); builder.build(“DuplicatedMachine”); builder.build(“DuplicatedMachine”);}

    會(huì)在第二次build同名狀態(tài)機(jī)時(shí)拋出StateMachineException異常。拋出異常的源碼在狀態(tài)機(jī)的注冊函數(shù)中,如下:

    結(jié)語

    為了不把篇幅拉得過長,在這里無法詳細(xì)地橫向?qū)Ρ葞状笾髁鳡顟B(tài)機(jī)(Spring Statemachine,Squirrel statemachine等)和COLA的區(qū)別,不過基于筆者在Spring Statemachine踩過的深坑,目前來看,COLA狀態(tài)機(jī)的簡潔設(shè)計(jì)適合用在訂單管理等小型狀態(tài)機(jī)的維護(hù),如果你想要在你的項(xiàng)目中接入狀態(tài)機(jī),又不需要嵌套、并行等高級(jí)玩法,那么COLA是個(gè)十分合適的選擇。

    我是后端工程師,蠻三刀醬。

    持續(xù)的更新原創(chuàng)優(yōu)質(zhì)文章,離不開你的點(diǎn)贊,轉(zhuǎn)發(fā)和分享!

    我的唯一技術(shù)公眾號(hào):后端技術(shù)漫談

    – END –

    鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權(quán)歸原作者所有,如有侵權(quán)請聯(lián)系管理員(admin#wlmqw.com)刪除。
    用戶投稿
    上一篇 2022年7月1日 02:44
    下一篇 2022年7月1日 02:45

    相關(guān)推薦

    • 分享4條發(fā)微商朋友圈的方法(微商朋友圈應(yīng)該怎么發(fā))

      對(duì)于微商朋友來說,朋友圈的重要性不言而喻了。 那么微商的朋友圈到底該怎么發(fā)呢? 為什么同樣是經(jīng)營一個(gè)朋友圈,有的微商看起來逼格滿滿,實(shí)際效果也不錯(cuò);而有的卻動(dòng)都不動(dòng)就被屏蔽甚至拉黑…

      2022年11月27日
    • 30個(gè)無加盟費(fèi)的項(xiàng)目(茶顏悅色奶茶店加盟費(fèi)多少)

      茶顏悅色又爆了,8月18日,茶顏悅色南京門店正式開業(yè),開張不到半小時(shí),門店就人滿為患,消費(fèi)者的購買熱情十分高漲,而由于人流量過大造成擁堵,茶顏悅色也不得不暫停營業(yè)。 當(dāng)然,這里面排…

      2022年11月27日
    • 淘寶工廠店的東西是正品嗎?淘寶工廠店為什么便宜

      淘工廠直營店其實(shí)就是鏈接淘寶賣家與工廠的平臺(tái),直接對(duì)接工廠型的商家,店鋪里的東西大部分價(jià)格都會(huì)很低。那么,淘工廠直營店靠譜嗎? 淘工廠直營店是靠譜的,但售后問題可能得不到很好的保障…

      2022年11月27日
    • 凈利潤率越高越好嗎(凈利潤率多少合適)

      一、持續(xù)增收不增利,平均凈利潤率首次跌入個(gè)位數(shù) 2021年,增收不增利依舊是行業(yè)主流。具體來看,大部分企業(yè)營業(yè)收入呈增長態(tài)勢,E50企業(yè)平均同比增速達(dá)到17.3%,但是利潤增速則明…

      2022年11月26日
    • 《寶可夢朱紫》夢特性怎么獲得?隱藏特性獲取方法推薦

      寶可夢朱紫里有很多寶可夢都是擁有夢特性會(huì)變強(qiáng)的寶可夢,很多玩家不知道夢特性怎么獲得,下面就給大家?guī)韺毧蓧糁熳想[藏特性獲取方法推薦,感興趣的小伙伴一起來看看吧,希望能幫助到大家。 …

      2022年11月25日
    • 《寶可夢朱紫》奇魯莉安怎么進(jìn)化?奇魯莉安進(jìn)化方法分享

      寶可夢朱紫中的奇魯莉安要怎么進(jìn)化呢?很多玩家都不知道,下面就給大家?guī)韺毧蓧糁熳掀骠斃虬策M(jìn)化方法分享,感興趣的小伙伴一起來看看吧,希望能幫助到大家。 奇魯莉安進(jìn)化方法分享 奇魯莉安…

      2022年11月25日
    • 數(shù)字看亮點(diǎn)!前十月我國造船三大指標(biāo)繼續(xù)全球領(lǐng)先

      央視網(wǎng)消息:工業(yè)和信息化部最新數(shù)據(jù)顯示,今年1—10月,我國造船三大指標(biāo)繼續(xù)保持全球領(lǐng)先。隨著生產(chǎn)節(jié)奏加快,船企產(chǎn)業(yè)集中度進(jìn)一步提升。 2022年1—10月,全國造船完工量、新接訂…

      2022年11月25日
    • 前十個(gè)月我國造船業(yè)三大指標(biāo)穩(wěn)居世界第一

      今年1—10月,我國造船業(yè)在國際市場的份額繼續(xù)穩(wěn)居世界第一。一批高技術(shù)高附加值船舶實(shí)現(xiàn)了批量接單、批量生產(chǎn)。 近日,中國船舶上海船舶研究設(shè)計(jì)院又新接了韓國船東三艘汽車運(yùn)輸船的設(shè)計(jì)追…

      2022年11月25日
    • 規(guī)范透明促PPP高質(zhì)量發(fā)展——16萬億元大市場迎來新規(guī)

      近日,財(cái)政部印發(fā)《關(guān)于進(jìn)一步推動(dòng)政府和社會(huì)資本合作(PPP)規(guī)范發(fā)展、陽光運(yùn)行的通知》,從做好項(xiàng)目前期論證、推動(dòng)項(xiàng)目規(guī)范運(yùn)作、嚴(yán)防隱性債務(wù)風(fēng)險(xiǎn)、保障項(xiàng)目陽光運(yùn)行四個(gè)方面進(jìn)一步規(guī)范P…

      2022年11月25日
    • 客服的崗位職責(zé)怎么寫(客服工作內(nèi)容及職責(zé))

      各位小伙伴們大家周一好,又到了每周一給大家分享干貨內(nèi)容的時(shí)候啦~ 本期來跟大家分享一下客服工作管理流程以及客服崗位里面的每項(xiàng)職能崗位的核心細(xì)則,也是干貨滿滿推薦收藏~ 一.補(bǔ)償流程…

      2022年11月25日

    聯(lián)系我們

    聯(lián)系郵箱:admin#wlmqw.com
    工作時(shí)間:周一至周五,10:30-18:30,節(jié)假日休息