91网首页-91网页版-91网在线观看-91网站免费观看-91网站永久视频-91网站在线播放

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

Fabric.js介紹

admin
2023年5月23日 10:1 本文熱度 1790

Fabric.js是什么

Fabric.js 是一個(gè)簡化HTML5 Canvas開發(fā)的Javascript庫,F(xiàn)abric.js提供了HTML5 Canvas本身缺失的對(duì)象模型、交互層、SVG解析器以及其他一整套工具。它是一個(gè)完全開源的項(xiàng)目,在MIT下獲得授權(quán),多年來一直在維護(hù),近期要發(fā)布4.0版本,支持自定義controls。

Fabric.js能做什么

在Canvas畫布上創(chuàng)建、填充圖形(包括圖片、文字、規(guī)則圖形和復(fù)雜路徑組成圖形)。
給圖形填充漸變顏色。
組合圖形(包括組合圖形、圖形文字、圖片等)。
設(shè)置圖形動(dòng)畫及用戶交互,生成的對(duì)象自帶拖拉拽功能。
JSON, SVG數(shù)據(jù)的序列化和反序列化。

為什么使用Fabric.js

HTML5 Canvas提供了完整的畫布,可以輕松的在畫布上繪制簡單的圖形、制作簡單的動(dòng)畫,但是HTML5 Canvas提供的API過于低級(jí),且操作基于上下文,因此在繪制復(fù)雜圖形或者需要實(shí)現(xiàn)用戶交互時(shí),就顯得不是那么方便了。Fabric.js在HTML5 Canvas原生API之上,提供完整的對(duì)象模型,由Fabric.js來管理HTML5 Canvas畫布的狀態(tài)和渲染,用戶基于具體的對(duì)象,來編寫代碼,完成所需功能的開發(fā)(類似于面向過程和面向?qū)ο螅!癟alk is cheap. Show me the code”,下面通過代碼來看看用HTML5 Canvas原生方法和用Fabric.js分別實(shí)現(xiàn)在畫布上畫一個(gè)矩形這一功能。

用HTML5 Canvas的原生方法實(shí)現(xiàn)

// 獲取canvas元素

var canvasEl = document.getElementById('c');

// 獲取上下文

var ctx = canvasEl.getContext('2d');

// 設(shè)置填充顏色

ctx.fillStyle = 'red';

// 在100,100點(diǎn)創(chuàng)建20x20的矩形

ctx.fillRect(100, 100, 20, 20);

在線演示地址:https://codepen.io/liblack/pen/LYpaMwa

用Fabric.js實(shí)現(xiàn)相同的功能:

// 創(chuàng)建原生canvas元素的包裝類(‘c’canvas元素的id)

var canvas = new fabric.Canvas('c');

// 創(chuàng)建一個(gè)矩形對(duì)象

var rect = new fabric.Rect({

  left: 100,

  top: 100,

  fill: 'red',

  width: 20,

  height: 20

});

// 添加矩形到畫布上

canvas.add(rect);

在線演示地址:https://codepen.io/liblack/pen/PoPLVwZ

由上面例子,可以看到使用HTML5 Canvas原生方法是對(duì)context(代表整個(gè)畫布位圖的對(duì)象)進(jìn)行操作,而使用Fabric.js,我們是對(duì)對(duì)象操作,只需要去實(shí)例化對(duì)象,設(shè)置對(duì)象的屬性,然后將它們添加到canvas中。到這里,可能還感受不到Fabric對(duì)比原生Canvas方法的優(yōu)勢(shì),下面可以完成這樣的功能,即在剛才繪制的矩形的基礎(chǔ)上,將矩形位置移動(dòng)到(10,10)點(diǎn)上。
這樣的功能,在Canvas原生方法上實(shí)現(xiàn),需要先把原來的矩形從畫布上清除,然后在(10,10)位置重新繪制一個(gè)矩形,以此來實(shí)現(xiàn)矩形移動(dòng)這樣的功能。

// 擦除之前的矩形(這里是擦除了整個(gè)canvas區(qū)域)

ctx.clearRect(0, 0, canvasEl.width, canvasEl.height);

// 重新繪制矩形

ctx.fillRect(20, 50, 20, 20);

聽起來是不是很蹩腳?是的,使用Canvas原生方法時(shí),就像是個(gè)帶橡皮檫的筆刷,在畫布上繪制圖形時(shí),是筆刷在畫布上移動(dòng),繪制出的圖形就是筆刷移動(dòng)的整個(gè)痕跡,而想把繪制好的圖形移動(dòng)到其他地方,只好用橡皮檫擦掉,然后在新位置重新繪制。

相應(yīng)的,使用Fabric.js實(shí)現(xiàn)該功能時(shí),只需要改變矩形對(duì)象的屬性,然后重新刷新(渲染)畫布即可。

rect.set({ left: 20, top: 50 });

canvas.renderAll();


Canvas對(duì)象

fabric.Canvas作為元素的包裝器,創(chuàng)建fabric.Canvas對(duì)象如下:

var canvas = new fabric.Canvas('...')


它接收一個(gè)元素的id,并返回一個(gè)fabric.Canvas 的實(shí)例。fabric.Canvas對(duì)象,并不是DOM里的元素,如果需要直接控制DOM,或者對(duì)應(yīng)的context,需要通過相應(yīng)API去獲取。

var canvasElement = document.getElementById(canvasEle);

var ctx = canvasElement.getContext("2d");

fabric.Canvas對(duì)象負(fù)責(zé)管理畫布上繪制的所有對(duì)象,可以將對(duì)象添加到fabric.Canvas對(duì)象,也可以從fabric.Canvas獲取或刪除對(duì)象。

var canvas = new fabric.Canvas('c');

var rect = new fabric.Rect();

canvas.add(rect); // 添加對(duì)象

canvas.item(0); ///獲取之前添加的fabric.Rect(第一個(gè)對(duì)象)

canvas.getObjects(); ///獲取畫布上的所有對(duì)象(rect將是第一個(gè)也是唯一一個(gè))

canvas.remove(rect); ///刪除之前添加的對(duì)象刪除


fabric.Canvas對(duì)象可以對(duì)畫布進(jìn)行配置。比如需要為整個(gè)畫布設(shè)置背景顏色或圖像?需要將所有內(nèi)容剪裁到特定區(qū)域?設(shè)置不同的寬度/高度?指定畫布是否是交互式的?所有這些選項(xiàng)(及其他)都可以在fabric.Canvas對(duì)象上進(jìn)行設(shè)置,可以在創(chuàng)建時(shí)或之后進(jìn)行設(shè)置。

var canvas = new fabric.Canvas('c', {

  backgroundColor: 'rgb(100,100,100,200)',

  selectionColor:'blue',

  selectLineWidth: 2

  // ...

});

// 或

var canvas = new fabric.Canvas('c');

canvas.setBackgroundImage('http://...');

canvas.onFpsupdate = function(){ /* ...... */ };

// ...


注意這種創(chuàng)建對(duì)象的形式,F(xiàn)abric.js里基本上都是類似的,類名表示要?jiǎng)?chuàng)建的對(duì)象類型,第一個(gè)參數(shù)是必要的數(shù)據(jù),第二個(gè)參數(shù)是各種選項(xiàng)。

所有對(duì)canvas的修改,包括在其中添加刪除對(duì)象,以及對(duì)象參數(shù)的修改,都需要調(diào)用渲染方法才能顯示出來:

canvas.renderAll();


Objects基本圖形
Fabric.js提供了7種基本圖形,下面是圖形對(duì)應(yīng)的類:

fabric.Circle

fabric.Ellipse

fabric.Line

fabric.Polygon

fabric.Polyline

fabric.Rect

fabric.Triangle


所有基本形狀,都可以通過類實(shí)例的屬性頭椒ɡ純刂撲塹奈恢謾⒀丈⒋笮〉妊健K欣嘍技?jí)瘍丛fabric.Object類,有一些公共的屬性和方法。

創(chuàng)建

下面是畫線的例子(給出兩個(gè)頂點(diǎn)坐標(biāo)):

var line =  new fabric.Line([x1, y1, x2, y2], {

    strokeWidth: 2, //線寬

    stroke: rgba(255,0,0,0.8), //線的顏色

    selectable: false

});

canvas.add(line);


畫圓的例子(頂點(diǎn)和半徑是在選項(xiàng)里的),這里left和top其實(shí)就是(x,y),應(yīng)該是借用了css里的命名。

var circle =  new fabric.Circle({

    radius: 2,

    left: left,

    top: top,

    originX: 'center',

    originY: 'center',

    fill: rgba(0,200,0,0.8), 

    strokeWidth: 1,

    stroke: rgba(255,0,0,0.8),

    selectable: false

});

canvas.add(circle);


從這里可以看出,和創(chuàng)建canvas類似,第一個(gè)參數(shù)是這個(gè)類專用的(比如畫直線的時(shí)候傳的起止點(diǎn)坐標(biāo)),第二個(gè)參數(shù)是通用選項(xiàng),如果沒有專用參數(shù),那么第一個(gè)參數(shù)就直接是通用選項(xiàng)。所有創(chuàng)建完的形狀,只有通過canvas.add方法加入,才能顯示出來。

控制

left和top是每種Object都有的屬性,至于它到底指圖形中哪一個(gè)點(diǎn)的坐標(biāo),由originX和originY這組參數(shù)決定,它們相當(dāng)于文本編輯軟件里的對(duì)齊方式,originX有三種可選值:left,center, right;originY也有三種可選值:top, center, bottom。

它們的示意圖如下:
http://fabricjs.com/test/misc/origin.html

如果希望對(duì)象的默認(rèn)原點(diǎn)在中心,可以這樣設(shè)置:

fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center'


width和height也是可以直接存取的屬性,顧名思義,表示長和寬(所有形狀都是有外接矩形的,所以可以用長和寬來控制大小)。除了上面那幾個(gè)可以直接存取的屬性,大部分屬性需要使用get/set方法讀寫,比如:

line.left = pointer.x;

line.top = pointer.y;

line.set('stroke', startColor);

line.set('height', 20);


Image對(duì)象

Image跟其他形狀類似,都是fabric.Object的子類,最大的區(qū)別在于,圖像文件的加載是異步的,所以對(duì)Image的后續(xù)操作,都要在回調(diào)中完成。

fabric.Image.fromURL('my_image.png', function(oImg) {

  // scale image down, and flip it, before adding it onto canvas

  oImg.scale(0.5).set('flipX, true);

  canvas.add(oImg);

});


Path對(duì)象

在Fabric.js中的Path代表了一個(gè)形狀的輪廓,它可以被填充、描邊和修改。Path由一系列的命令組成,本質(zhì)上是模仿一支筆從一個(gè)點(diǎn)到另一個(gè)點(diǎn)。在“move”, “l(fā)ine”, “curve”, or “arc”等命令的幫助下,Path可以形成非常復(fù)雜的形狀。而在Paths(PathGroup’s)組的幫助下,Path的能實(shí)現(xiàn)更多的復(fù)雜圖形。
Fabric.js中的Path與SVG的 元素非常相似。它們使用相同的命令集,可以從 元素中創(chuàng)建,并將其序列化。我們稍后會(huì)更深入地研究序列化和SVG解析,但現(xiàn)在值得一提的是,實(shí)踐中很少會(huì)手動(dòng)創(chuàng)建Path實(shí)例。相反,更多的是使用Fabric.js的內(nèi)置SVG解析器。
手工創(chuàng)建一個(gè)簡單的Path對(duì)象。

var path = new fabric.Path('M 0 0 L 200 100 L 170 200 z');

path.set({ left: 120, top: 120 });

canvas.add(path);


實(shí)例化 fabric.Path 對(duì)象,傳遞給它一串路徑指令。雖然看起來很隱蔽,但實(shí)際上很容易理解。”M “代表 “移動(dòng) “指令,告訴隱形筆要移動(dòng)到0,0點(diǎn)。”L “代表 “線”,讓筆畫一條線到200,100點(diǎn)。然后,另一個(gè) “L “代表 “線”,讓筆畫一條線到170,200點(diǎn)。最后,”z “告訴畫筆關(guān)閉當(dāng)前路徑并最終確定形狀。結(jié)果,得到的是一個(gè)三角形的形狀。

由于 fabric.Path 就像 Fabric 中的其他對(duì)象一樣,我們還可以改變它的一些屬性。但我們還可以對(duì)它進(jìn)行更多的修改。

...

var path = new fabric.Path('M 0 0 L 300 100 L 200 300 z');

...

path.set({ fill: 'red', stroke: 'green', opacity: 0.5 });

canvas.add(path);


實(shí)踐中,更多是直接使用fabric.loadSVGfromString 或 fabric.loadSVGfromURL 方法來加載整個(gè) SVG 文件,然后讓 Fabric 的 SVG 解析器來完成所有 SVG 元素的解析工作,并創(chuàng)建相應(yīng)的 Path 對(duì)象。

Events事件

事件驅(qū)動(dòng)的架構(gòu)是一個(gè)框架靈活性和可擴(kuò)展性的基礎(chǔ)。Fabric.js提供了一個(gè)廣泛的事件系統(tǒng),覆蓋了低級(jí)的 “鼠標(biāo)”事件到高級(jí)的對(duì)象事件。
這些事件使我們能夠監(jiān)控到到畫布上發(fā)生的各種動(dòng)作的不同時(shí)刻。比如想知道鼠標(biāo)被按下的時(shí)間,只需監(jiān)聽”mouse:down”事件就可以了。想知道對(duì)象何時(shí)被添加到畫布上,只需要監(jiān)聽”object:added “事件就在那里。

事件API非常簡單,類似于jQuery、Underscore.js或其他流行的JS庫。有on方法來初始化事件監(jiān)聽器,有off方法來移除事件監(jiān)聽器。

下面一個(gè)實(shí)際的例子。

var canvas = new fabric.Canvas('...');

canvas.on('mouse:down', function(options) {

  console.log(options.e.clientX, options.e.clientY);

});


上面例子演示了在canvas上添加”mouse:down”事件監(jiān)聽器,并給它設(shè)置事件處理程序,它將記錄事件發(fā)生的坐標(biāo)。事件處理程序會(huì)接收一個(gè)選項(xiàng)對(duì)象,它有兩個(gè)屬性:e—原始事件,和target—畫布上的點(diǎn)擊對(duì)象(如果有的話)。該事件在任何時(shí)候都是存在的,但目標(biāo)只有在實(shí)際點(diǎn)擊了畫布上的某個(gè)對(duì)象后才會(huì)存在。target也只有在有意義的情況下才會(huì)傳遞給事件的處理程序,例如,對(duì)于 “mouse:down”事件,但對(duì)于 “after:render”事件(表示整個(gè)畫布被重新繪制),target不會(huì)傳遞給事件處理程序。

canvas.on('mouse:down', function(options) {

  if (options.target) {

    console.log('一個(gè)對(duì)象被點(diǎn)擊了!', options.target.type);

  }

});


如果你點(diǎn)擊了一個(gè)對(duì)象,上面的例子會(huì)輸出 “一個(gè)對(duì)象被點(diǎn)擊了!”。還會(huì)顯示被點(diǎn)擊的對(duì)象類型。

那么,在Fabric.js中還有鼠標(biāo)級(jí)的事件:“mouse:down”, “mouse:move”, 和”mouse:up”。通用的事件: “after:render”。選擇相關(guān)的事件: “before:selection:cleared”,”selection:create”,”selection:cleared”。對(duì)象相關(guān)的事件: “object:moded”、”object:selected”、”object:moving”、”object:scaling”、”object:rotating”、”object:additional “和 “object:detter”。
注意,像”object:moving”(或”object:scaling”)這樣的事件在每次對(duì)象移動(dòng)(或縮放)時(shí),即使是一個(gè)像素點(diǎn)的移動(dòng),也會(huì)連續(xù)地被觸發(fā)。另一方面,像 “object:modified” 或 “selection:create”這樣的事件只在操作(對(duì)象修改或選區(qū)創(chuàng)建)結(jié)束時(shí)才會(huì)被觸發(fā)。如果將事件直接附加到畫布上的(canvas.on(‘mouse:down’, …)),這意味著事件被覆蓋到了canvas實(shí)例上。如果一個(gè)頁面上有多個(gè)畫布,可以給每個(gè)畫布附加不同的事件監(jiān)聽器。它們都是獨(dú)立互不影響的。
為了方便,F(xiàn)abric.js將事件系統(tǒng)做得更進(jìn)一步,允許直接將監(jiān)聽器附加到具體對(duì)象上。如下例子。

var rect = new fabric.Rect({ width: 100, height: 50, fill: 'green' });

rect.on('elected', function() {

  console.log('選擇了一個(gè)矩形');

});

var circle = new fabric.Circle({ radius: 75, fill: 'blue' });

circle.on('selected', function() {

  console.log('選擇了一個(gè)圓圈');

});


上述例子直接給矩形和圓的實(shí)例附加事件監(jiān)聽器,使用的是 “selected “事件,而不是 “object:selected”。同樣的,可以在對(duì)象上使用 “modified”事件(當(dāng)附加到canvas上時(shí)使用 “object:modified”)、”rotating”事件(當(dāng)附加到canvas時(shí)使用 “object:rotating”)等等。

Groups組

fabric.Group是Fabric.js提供的強(qiáng)大的功能之一。使用Groups可以將任何Fabric對(duì)象組合成一個(gè)單一實(shí)體,這樣就能夠?qū)⑦@些對(duì)象作為一個(gè)單一的單元來處理。用鼠標(biāo)將畫布上的任意數(shù)量的Fabric對(duì)象進(jìn)行組合,一旦組合后,這些對(duì)象都可以一起移動(dòng)甚至修改。它們組成了一個(gè)組。我們可以對(duì)該組進(jìn)行縮放、旋轉(zhuǎn),甚至改變其呈現(xiàn)屬性—顏色、透明度、邊框等。

下面創(chuàng)建一個(gè)由2個(gè)對(duì)象組成的組,即圓圈和文本。

var circle = new fabric.Circle({

  radius: 100,

  fill: '#eef',

  scaleY: 0.5,

  originX: 'center',

  originY: 'center'

});

var text = new fabric.Text('hello world', {

  fontSize: 30,

  originX: 'center',

  originY: 'center'

});

var group = new fabric.Group([ circle, text ], {

  left: 150,

  top: 100,

  angle: -10

});

canvas.add(group);


組成組以后,依舊可以對(duì)每個(gè)對(duì)象操作,改變對(duì)象的屬性和狀態(tài)。

group.item(0).set('fill', 'red');

group.item(1).set({

  text: 'trololo',

  fill: 'white'

});


Serialization序列化

為構(gòu)建某種有狀態(tài)的應(yīng)用程序,允許用戶將canvas內(nèi)容的結(jié)果保存在服務(wù)器上,或者將內(nèi)容流媒體化到不同的客戶端。Fabric.js提供了canvas序列化/解序列化支持。

toObject, toJSON

Fabric中序列化的主要方法是 fabric.Canvas#toObject()和 fabric.Canvas#toJSON()方法。讓我們來看一個(gè)簡單的例子,首先對(duì)一個(gè)空畫布進(jìn)行序列化。

var canvas = new fabric.Canvas('c');

JSON.stringify(canvas); // '{"objects":[], "background": "rgba(0,0,0,0,0)"}'


使用的是ES5 JSON.stringify()方法,如果傳入的對(duì)象存在toJSON方法,那么這個(gè)方法就會(huì)隱含地調(diào)用toJSON方法。由于Fabric中的canvas實(shí)例有toJSON方法,所以調(diào)用JSON.stringify(canvas)方法和調(diào)用JSON.stringify(canvas.toJSON())一樣。

注意,返回的字符串表示空的canvas。它是JSON格式的,本質(zhì)上由 “objects”和”background”屬性組成。”objects”目前是空的,因?yàn)閏anvas上沒有任何東西,而 background 有一個(gè)默認(rèn)的透明值(“rgba(0,0,0,0,0)”)。
當(dāng)在canvas上添加了具體對(duì)象后:

canvas.add(new fabric.Circle({

  left: 100,

  top: 100,

  radius: 50,

  fill: 'red'

}));

console.log(JSON.stringify(canvas));


序列化后結(jié)果如下:

'{"objects":[{"type":"rect","left":50,"top":50,"width":20,"height":20,"fill":"green","overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":null,

"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"selectable":true,"hasControls":true,"hasBorders":true,"hasRotatingPoint":false,

"transparentCorners":true,"perPixelTargetFind":false,"rx":0,"ry":0},{"type":"circle","left":100,"top":100,"width":100,"height":100,"fill":"red",

"overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":null,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,

"selectable":true,"hasControls":true,"hasBorders":true,"hasRotatingPoint":false,"transparentCorners":true,"perPixelTargetFind":false,"radius":50}],"background":"rgba(0, 0, 0, 0)"}'


toSvg

Fabric.js支持將canvas畫布序列化為SVG格式的文本。

canvas.add(new fabric.Rect({

  left: 50,

  top: 50,

  height: 20,

  width: 20,

  fill: 'green'

}));

console.log(canvas.toSVG());


序列化結(jié)果如下:

<?xml version="1.0" standalone="no" ?>

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="800" height="700" xml:space="preserve">

<desc>created with Fabric.js 0.9.21</desc>

<rect x="-10" y="-10" rx="0" ry="0" width="20" height="20" style="stroke: none; stroke-width: 1; stroke-dasharray: ; fill: green; opacity: 1;" transform="translate(50 50)" />

</svg>


Deserialization反序列化, SVG Parser SVG解析器

與序列化類似,反序列化是從字符串中加載canvas,與序列化時(shí)相對(duì)應(yīng)的,也有兩種方法:從JSON文本反序列和從SVG文本反序列化。當(dāng)使用JSON表示時(shí),有 fabric.Canvas#loadfromJSON和 fabric.Canvas#loadfromDatalessJSON方法。當(dāng)使用SVG時(shí),

有 fabric.loadSVGfromURL和 fabric.loadSVGfromString兩個(gè)方法。

var canvas = new fabric.Canvas();

canvas.loadfromJSON('{"objects":[{"type":"rect","left":50,"top":50,"width":20,"height":20,"fill":"green","overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":null,

"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"selectable":true,"hasControls":true,"hasBorders":true,"hasRotatingPoint":false,"transparentCorners":true,

"perPixelTargetFind":false,"rx":0,"ry":0},{"type":"circle","left":100,"top":100,"width":100,"height":100,"fill":"red","overlayFill":null,"stroke":null,"strokeWidth":1,

"strokeDashArray":null,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"selectable":true,"hasControls":true,"hasBorders":true,

"hasRotatingPoint":false,"transparentCorners":true,"perPixelTargetFind":false,"radius":50}],"background":"rgba(0, 0, 0, 0)"}');

下移:canvas.sendBackwards(obj)

上移:canvas.bringForward(obj)

置頂:canvas.bringToFront(obj)

置底:canvas.sendToBack(obj)

更多資源

fabric.js官網(wǎng):http://fabricjs.com/
fabric.js源碼:https://github.com/fabricjs/fabric.js
fabric.js應(yīng)用案例:https://printio.ru/tees/new_v2
HTML5 Canvas資料:https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial



該文章在 2023/5/23 11:21:46 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲(chǔ)管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 国产激情国语对白 | 动漫国产在线精品一 | 欧洲国产日产综合 | 欧美在线观看二区 | 日韩精品国产欧美 | 九九九在线视频 | 国内高清久 | 国产自产在线观看 | 欧美日韩在线第一页 | 三级网站国产 | 蜜臀国产在线视频 | 日韩一卡2 | 成人午夜亚洲精品无 | 99热精品免费观看 | AⅤ三区 | 91精品一区二区 | 无码精品人妻一区二区三区中 | 九九九热在线精品免 | 日韩欧美一二区 | 国产自产精品一区 | 日本系列亚洲第一页 | www.成人影片 | 99国产热播| 午夜福利写真片精品 | 国产欧美自拍日韩 | 91蝌蚪在线视频 | 成人动漫视频二区 | 国内在线第一区 | 欧亚天堂在线播放 | 欧美日韩精品一区 | 国产精品美女在线 | 国产精品美乳免费看 | 欧美亚洲性爱电影 | 国产传媒一区 | 尤物精品 | 99在线视频免费观 | 国产老熟女精品一区 | 国产在线看片导航 | 国产精品激情自拍 | 欧美专区中文字幕 | 精品一区二区视频在 |