官方文檔:http://www.dropzonejs.com/
Github: https://github.com/enyo/dropzonejavascript
DropzoneJS is an open source library that provides drag’n’drop file uploads with image previews.php
It’s lightweight, doesn’t depend on any other library (like jQuery) and is highly customizable.css
你可能只須要看看簡單的例子( 源代碼 )就能開始了。而後繼續閱讀下面的一步步的指示和不一樣的安裝方法。html
下載獨立的dropzone.js文件。而後這樣引入到html中:html5
<script src="./path/to/dropzone.js"></script>
Dropzone 如今激活和可用,經過window.Dropzone
就可使用了。java
Dropzone不處理你的文件上傳在服務器上。你必須本身實現代碼接收和存儲文件。有關更多信息,請參見部分服務器端實現。node
完成上面的操做就可使用 Dropzone ,可是若是你想讓它你上傳的樣式看起來像官方頁面那樣,你須要將下載的dropzones裏面的cs發到你的文件夾中並引入。laravel
若是你使用component,你只需添加dropzone依賴:git
"enyo/dropzone": "*"
而後這樣引入:github
var Dropzone = require("dropzone");
如今它已激活,並能夠在頁面中使用。
基本的CSS樣式也包含在組件中,若是你想讓它你上傳的樣式看起來像官方頁面那樣,你須要將下載的dropzones裏面的cs發到你的文件夾中並引入。
Dropzone 一樣爲RequireJS提供了AMD模塊。
你能夠在下載的文件夾中找到dropzone-amd-module。
使用 dropzone 的典型的方式是經過建立一個表單包含與class="dropzone"
:
<form action="/file-upload" class="dropzone" id="my-awesome-dropzone"> <input type="file" name="file" /> </form>
就像這樣。dropzone 會經過class
爲dropzone
找到全部的表單元素,並自動將這些元素初始化,而後點擊input
選擇文件(或拖拽)以後會根據action
指定的地址上傳文件。(其實就和普通的文件上傳沒什麼區別,只不過多了個拖拽)
若是你想在後端接受文件的時候用其餘的name
而不是上面指定的file
,您能夠配置dropzone的paramName的選項。
若是你是使用component
形式,別忘了require("dropzone");
,不然是不會生效的。
若是是使用form表單,完成上面的設置以後,就已經能夠拖拽上傳了,因此若是你不想在寫一些js去控制上傳中的其餘東西,好比進度條、預覽區域等,能夠在form內加一個包含fallback
類的標籤,dropzone 會本身處理fallback
類的標籤區域,固然這是須要瀏覽器支持。若是瀏覽器不支持,那麼那就將其做爲普通的文件上傳。
這一般是這樣的:
<form action="/file-upload" class="dropzone"> <div class="fallback"> <input name="file" type="file" multiple /> </div> </form>
除了直接在form表單中添加class
爲dropzone
讓其自動建立外,還能夠在非表單元素上面經過實例化Dropzone類實現。
<div id="myId" style="width: 800px; height: 300px;"></div> // Dropzone class: var myDropzone = new Dropzone("div#myId", { url: "/file/post"});
或若是您使用jQuery,您可使用jQuery插件Dropzone形式:
// jQuery $("div#myId").dropzone({ url: "/file/post" });
注意:若是你不是使用一個表單元素,別忘了指定一個url選項,由於Dropzone不知道上傳到那裏。
Dropzone 不提供的服務器端文件處理的代碼,可是文件上傳的方式是和簡單的表單文件上傳是相同的。好比普通的表單上傳是這樣:
<form action="" method="post" enctype="multipart/form-data"> <input type="file" name="file" /> </form>
掌握基本的服務器上的文件上傳,請查看各類語言相應的文檔。這裏有一些基本的實現文件:
Complete PHP tutorial by startutorial.com
Tutorial for Dropzone and Lavarel (PHP) written by Maksim Surguy
付費的文檔:
eBook for Dropzone with PHP by startutorial.com.
若是你須要更多的信息,請看看Dropzone FAQ。
有兩種方式配置 dropzone:
在html元素上添加dropzone
樣式類,而後就不須要手動使用js去實例化了,可是你的一些配置Dropzone.options
對象去配置:
// "myAwesomeDropzone" 是那個 HTML 元素的 ID // 這裏的id不是駝峯格式,是以`-`爲分隔,如 id="my-awesome-dropzone" Dropzone.options.myAwesomeDropzone = { paramName: "file", // The name that will be used to transfer the file maxFilesize: 2, // MB accept: function(file, done) { if (file.name == "justinbieber.jpg") { done("Naha, you don't."); } else { done(); } } };
最明顯的方式是經過一個選擇對象時實例化一個dropzone,之前面手動建立dropzones的方式。
由於咱們須要使用dropzone提供的一些樣式,好比預覽時圖片樣式等,這樣就算手動建立,但也須要使用到dropzone
樣式類,那這樣就會致使初始化兩次,在控制檯就會報錯,這時候就須要在手動初始化以前設置以下代碼:
// Prevent Dropzone from auto discovering this element: Dropzone.options.myAwesomeDropzone = false; // This is useful when you want to create the // Dropzone programmatically later // Disable auto discover for all elements: Dropzone.autoDiscover = false;
例子:
<div class="dropzone" id="myDropzone"> <div class="am-text-success dz-message"> 將文件拖拽到此處<br>或點此打開文件管理器選擇文件 </div> </div> <script type="text/javascript"> Dropzone.autoDiscover = false; var myDropzone = new Dropzone("#myDropzone", { url: "/file/upload", addRemoveLinks: true, method: 'post', filesizeBase: 1024, sending: function(file, xhr, formData) { formData.append("filesize", file.size); }, success: function (file, response, e) { var res = JSON.parse(response); if (res.error) { $(file.previewTemplate).children('.dz-error-mark').css('opacity', '1') } } }); </script>
像上面這樣,既能使用 dropzone 的樣式,也能本身手動初始化上傳。
參數 | 描述 |
---|---|
url | 除了form元素之外的其餘元素必須指定該參數(或當form元素沒有操做屬性)。您還能夠提供一個函數,參數爲files 以及必須返回url(since v3.12.0) |
method | 默認爲"post",必要的時候你也能夠設置爲"put"。 您還能夠提供一個函數,參數爲files 以及必須返回這個method(since v3.12.0) |
parallelUploads | 同時上傳多少個文件。(更多信息參見隊列文件上傳部分) |
maxFilesize | 單位 MB |
filesizeBase | 默認1000。這個定義的基礎是否應該使用1000或1024來計算文件大小。1000是有效的,由於1000個字節等於1千字節,1024字節= 1 Kibibyte。你能夠改變爲1024,若是你不在意的有效性。 |
paramName | 文件上傳後端接收的參數名。默認file 。注意:若是你設置uploadMultiple爲true,那麼Dropzone會將[]附加到這個名字,也就是後端接收的是一個file[]數組。 |
uploadMultiple | Dropzone是否在一個請求中發送多個文件。若是它設置爲true,而後fallback 部分的input 元素須有multiple 屬性。這個選項也會觸發其餘事件(如processingmultiple )。有關更多信息,請參見事件部分。 |
headers | 一個向服務器發送附加頭的對象。如:headers: { "My-Awesome-Header": "header value" } |
addRemoveLinks | 這將添加一個連接到每一個文件,刪除或取消預覽文件(若是已經上傳)。dictCancelUpload , dictCancelUploadConfirmation and dictRemoveFile 三個參數可選。 |
previewsContainer | 定義文件預覽顯示。若是爲null 就使用 Dropzone 默認的。可使用一段普通的html元素或css選擇器。被選擇的html元素必須包含dropzone-previews 樣式類確保預覽顯示正常。 |
clickable | 若是爲true ,dropzone元素自己將是可點擊的,若是false 將不可被點擊。此外,還能夠是一段普通的html或者css選擇器,表示點擊該元素觸發資源管理器。 |
createImageThumbnails | |
maxThumbnailFilesize | 單位 MB。文件名超過這個極限時,縮略圖將不會生成。 |
thumbnailWidth | 若是爲null ,將使用圖像的比例來計算它。 |
thumbnailHeight | 與thumbnailWidth 同樣。若是二者都是null,圖像將不會調整。 |
maxFiles | 若是不爲null ,定義多少個文件將被處理。若是超過,事件maxfilesexceeded 將被調用。相應地dropzone元素獲得了類dz-max—files-reached ,所以你能夠提供視覺反饋。 |
resize | 建立調整信息時被調用的函數。file 做爲函數第一個參數,同時必須返回一個對象包含srcX , srcY , srcWidth 、srcHeight 和相同的 trg* 。這些值將被用於ctx.drawImage() 函數。 |
init | Dropzone初始化時調用的函數。你能在這個函數中設置事件偵聽器。 |
acceptedFiles | accept 函數默認的實現函數,用於檢查文件的mime類型或擴展。這是一個逗號分隔的mime類型和文件擴展名的數組。如。image/*,application/pdf,.psd 。若是Dropzone是clickable ,此選項將被用做accept 函數的參數輸入。 |
accept | 一個接收file 和done 函數做爲參數輸入的函數。若是done 函數調用無參數,文件會被處理。若是你在done 函數中傳入了參數(好比錯誤信息)文件將不會被上傳。若是文件太大或不匹配的mime類型這個函數不會調用。 |
autoProcessQueue | 當設置爲false,你必須自身調用myDropzone.processQueue() 上傳文件。有關更多信息,請參見下面有關處理隊列。 |
previewTemplate | 一個字符串,其中包含模板用於每個圖像。改變它知足你的需求,但確保正確地提供全部元素。你能夠在頁面中創建這樣一個容器:id="preview-template" (設置style="display: none;"),而後這樣設置:previewTemplate: document.querySelector('preview-template').innerHTML 。 |
forceFallback | 默認值爲false。若是爲true,fallback 將被強行使用。這是很是有用的測試服務器實現首要方式,確保一切如預期所想,並測試你的fallback 顯示如何。 |
fallback | 當瀏覽器不支持時調用的函數。默認實現顯示了fallback 內的input 域並添加一個文本。 |
爲自定義的 dropzone,你也可使用以下這些選項 | |
dictDefaultMessage | 任何文件被拖拽進區域以前顯示的信息。這一般是被一個圖像,但默認爲「Drop files here to upload」。 |
dictFallbackMessage | 若是瀏覽器不支持,默認消息將被替換爲這個文本。默認爲「Your browser does not support drag'n'drop file uploads.」。 |
dictFallbackText | 這將被添加在input file 以前。若是你提供一個fallback 元素,或者該選項爲空該選項將被忽略。默認爲「Please use the fallback form below to upload your files like in the olden days.」。 |
dictInvalidFileType | 若是文件類型不匹配時顯示的錯誤消息。 |
dictFileTooBig | 當文件太大時顯示。{{filesize}} ` 和 {{maxFilesize}} ` 將被替換。 |
dictResponseError | 若是服務器響應是無效的時顯示的錯誤消息。{{statusCode}} ` 將被替換爲服務器端返回的狀態碼。 |
dictCancelUpload | 若是addRemoveLinks 爲true,文本用於取消上傳連接的文字。 |
dictCancelUploadConfirmation | 若是addRemoveLinks 爲true,文本用於取消上傳的文字。 |
dictRemoveFile | 若是addRemoveLinks 爲true,用於刪除一個文件的文本。 |
dictMaxFilesExceeded | 若是設置了maxFiles ,這將是超過了設置的時候的錯誤消息。 |
你也能夠覆蓋全部違約事件動做選項。若是你提供的drop
選項能夠覆蓋默認的事件處理程序。你應該熟悉代碼,由於您能夠輕鬆掌握這樣的上傳。若是你只是想作額外修改,好比添加一些過濾什麼的,能夠監聽事件。
當一個文件被添加到dropzone,其status
被設置到Dropzone.QUEUED
(accept
函數檢查經過後),這意味着該文件如今在隊列中。
若是你能夠選擇autoProcessQueue
設置爲true
,那麼隊列是當即處理,文件被刪除或一個上傳完成後,經過調用.processQueue()
,檢查有多少文件正在上傳,若是它少於option.parallelUploads
,.processFile
將被調用。
若是你autoProcessQueue
設置爲false
,那麼.processQueue()
不會被隱式地調用。這意味着當你想上傳目前隊列中全部文件時你必須本身調用它。
爲每一個文件生成預覽HTML,設置dropzone定義的選項previewTemplate
,默認爲:
<div class="dz-preview dz-file-preview"> <div class="dz-details"> <div class="dz-filename"><span data-dz-name></span></div> <div class="dz-size" data-dz-size></div> <img data-dz-thumbnail /> </div> <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div> <div class="dz-success-mark"><span>✔</span></div> <div class="dz-error-mark"><span>✘</span></div> <div class="dz-error-message"><span data-dz-errormessage></span></div> </div>
當文件在上傳過程當中的時候,dz-preview
中的dz-processing
將被顯示;當文件上傳以後dz-success
將被顯示;若是文件上傳錯誤或沒網dz-error
將被顯示,此時data-dz-errormessage
的內容將是服務器端返回的信息。
重寫默認的模板,就可使用配置中的previewTemplate
選項。
您能夠經過file.previewElement
訪問文件的HTML預覽,而且設置任何事件。如:
success: function (file, response, e) { var res = JSON.parse(response); if (res.error) { $(file.previewTemplate).children('.dz-error-mark').css('opacity', '1') } }
若是你想打破常規重寫previewElement
,能夠在你想要的元素上添加data-dz-*
屬性:
data-dz-name
data-dz-size
data-dz-thumbnail (這個必須是 <img />
元素,而後該元素的 alt
和 src
屬性會被 Dropzone 自動改變爲相應的值)
data-dz-uploadprogress (當文件處於上傳過程當中的時候Dropzone 將改變此元素的 style.width
的值,從 0% 到 100%)
data-dz-errormessage
Dropzone將尋找這些元素,並改變默認選項和更新它的內容。
若是你想要一些特定連接刪除一個文件(而不是建於addRemoveLinks配置),您能夠簡單地插入元素的模板data-dz-remove屬性。
<img src="removebutton.png" alt="Click me to remove the file." data-dz-remove />
你也不用被這些使用慣例所強迫。若是你徹底覆蓋全部默認事件監聽器能夠從頭開始重建你的佈局。
若是你想讓你的dropzone看起來像官方頁面那樣,使用安裝部分提供的添加樣式表和spritemaps便可。
看到主題部分,看看如何改變Dropzone 的UI。
官方建立了一個例子,配置幾行代碼,讓Dropzone看起來和感受徹底和jQuery文件上傳差很少。Check it out!
若是你想刪除已添加的文件,你能夠調用.removeFile(file)
。這種方法也觸發removedfile
事件。
下面是一個示例,文件上傳完成後將自動刪除:
myDropzone.on("complete", function(file) { myDropzone.removeFile(file); });
若是你想刪除因此的文件,簡單地使用.removeAllFiles()
。正在上傳中的文件不會被刪除。若是你想取消正在上傳的文件,調用.removeAllFiles(true)
將取消上傳。
若是你設置了autoProcessQueue
爲false
,你必須調用.processQueue()實現上傳。
訪問dropzone中的全部文件,使用myDropzone.files
。
全部可接受的文件:.getAcceptedFiles()
因此被拒絕的文件:.getRejectedFiles()
隊列中的全部文件:.getQueuedFiles()
上傳中的全部文件:.getUploadingFiles()
若是不在須要一個dropzone,使用當前示例調用.disable()
,這將移除該元素上的事件、文件。從新激活使用.enable()
。`
若是你不喜歡瀏覽器默認的confirm
,您能夠經過覆蓋Dropzone.confirm
處理它們:
Dropzone.confirm = function(question, accepted, rejected) { // Ask the question, and call accepted() or rejected() accordingly. // CAREFUL: rejected might not be defined. Do nothing in that case. };
Dropzone觸發事件在處理文件時,你能夠經過當前實例調用.on(eventName, callbackFunction)
監聽事件。
由於聽事件只能是Dropzone實例,設置你的事件偵聽器,最好的地方是在init函數。
Dropzone.options.myAwesomeDropzone = { init: function() { this.on("addedfile", function(file) { alert("Added file."); }); } };
若是你手動建立dropzones,你能夠設置實例的事件監聽器,就像這樣:
// This example uses jQuery so it creates the Dropzone, only when the DOM has // loaded. // Disabling autoDiscover, otherwise Dropzone will try to attach twice. Dropzone.autoDiscover = false; // or disable for specific dropzone: // Dropzone.options.myDropzone = false; $(function() { // Now that the DOM is fully loaded, create the dropzone, and setup the // event listeners var myDropzone = new Dropzone("#my-dropzone"); myDropzone.on("addedfile", function(file) { /* Maybe display some more file information on your page */ }); })
這是更復雜的,沒有必要的,除非你有一個很好的理由來管理實例化Dropzones。
Dropzone自己嚴重依賴事件,視覺上的展現都是經過監聽去作的。這些事件監聽器設置在每一個Dropzone的默認配置,能夠覆蓋,從而取代默認的行爲實現本身的事件回調。
不覆蓋這些配置選項,除非你知道你在作什麼。 | |
事件 | 描述 |
---|---|
全部這些接收event 做爲第一個參數 |
|
drop | 用戶鬆放文件到到dropzone |
dragstart | 用戶開始拖動文件到任何地方 |
dragend | 拖動結束 |
dragenter | 用戶拖拽文件到Dropzone |
dragover | 用戶拖動一個文件通過Dropzone |
dragleave | 用戶拖動一個文件離開Dropzone |
全部這些接收file 做爲第一個參數 |
|
addedfile | 當一個文件被添加到列表中 |
removedfile | 從列表中刪除一個文件。你能夠監聽該事件而後從您的服務器刪除文件 |
thumbnail | 生成縮略圖。接收dataUrl 做爲第二個參數 |
error | 發生一個錯誤。接收errorMessage 做爲第二個參數,若是錯誤是因爲XMLHttpRequest xhr 對象爲第三個參數。 |
processing | 當一個文件被處理(由於隊列不會當即處理全部文件)。這個事件在processingfile 以前被觸發。 |
uploadprogress | 每當文件上載過程變化是觸發。得到progress 做爲第二個參數,是一個百分比(0 - 100)和bytesSent 做爲第三個參數,是已經發送到服務器的字節數量。當上傳完成dropzone 確保uploadprogress 爲100%並被調用一次。Warning:這個函數能夠調用屢次使用相同的progress 。 |
sending | 在每一個文件發送是觸發。file 爲第一個參數,xhr 對象和formData 對象做爲第二個和第三個參數,你能夠修改它們(例如添加CSRF令牌)或添加額外的數據。 |
success | 文件已經成功上傳觸發。file 爲第一個參數,獲取服務器響應做爲第二個參數。(這一事件在finished 以前觸發。 |
complete | 上傳成功或錯誤時。 |
canceled | 當一個文件上傳被取消時。 |
maxfilesreached | 文件數量接受到達maxFiles極限時 |
maxfilesexceeded | 每一個文件被拒絕了,由於文件的數量超過了maxFiles極限時觸發 |
全部這些收到的files 做爲第一個參數,而且就當uploadMultiple 爲true 時觸發 |
|
processingmultiple | 見processing 的描述。 |
sendingmultiple | 見sending 的描述。 |
successmultiple | 見success 的描述。 |
completemultiple | 見complete 的描述。 |
canceledmultiple | 見canceled 的描述。 |
特殊事件 | |
totaluploadprogress | 觸發時包含參數total uploadProgress(0 - 100) ,totalBytes 和totalBytesSent 。這個事件能夠用來顯示全部文件的總體上載進度 |
reset | 調用時列表中的全部文件被刪除,dropzone重置爲初始狀態。 |
queuecomplete | 當隊列中的全部文件上傳完成時。 |
若是你想對Dropzone的主題徹底自定義,在大多數狀況下,您能夠簡單地取代HTML模板預覽,調整CSS,也能夠建立一些額外的事件監聽器。
官方建立了一個例子,配置幾行代碼,讓Dropzone看起來和感受徹底和jQuery文件上傳差很少。Check it out!。正如您能夠看到的,最大的變化就是previewTemplate。而後添加了一些額外的事件監聽器來讓它看起來符合本身的要求。
然而,您能夠徹底從頭開始實現您的UI。
覆蓋默認的事件監聽器,建立您本身的自定義Dropzone,能夠這樣:
// This is an example of completely disabling Dropzone's default behavior. // Do *not* use this unless you really know what you are doing. Dropzone.myDropzone.options = { previewTemplate: document.querySelector('#template-container').innerHTML, // Specifing an event as an configuration option overwrites the default // `addedfile` event handler. addedfile: function(file) { file.previewElement = Dropzone.createElement(this.options.previewTemplate); // Now attach this new element some where in your page }, thumbnail: function(file, dataUrl) { // Display the image in your file.previewElement }, uploadprogress: function(file, progress, bytesSent) { // Display the progress } // etc... };
上面的這些代碼顯然缺少實際的實現。看源代碼,看看Dropzone內部的實現。
若是你不須要任何默認Dropzone UI,只對Dropzone的事件處理程序、文件上傳和拖拽功能感興趣,那你應該使用以上選項事件處理。
若是你不想要默認消息提示(拖拽文件上傳(或單擊)),您能夠在你dropzone
元素內添加一個元素包含類dz-message
,這樣dropzone
就不會爲您建立的消息。
Dropzone 或提交你設置的form
內的全部隱藏的表單域信息。因此當你是使用form
元素的形式的話,這是一個簡單的方法來提交額外的數據,至因而get
仍是post
取決於你form
的method
。固然也能夠在js配置中添加其餘的參數。
當事件綁定完成以後,Dropzone 會添加數據到file
對象。若是是image
的話,你能夠經過file.width
和 file.height
訪問到圖片的寬度和高度。並且file.upload
對象會包含以下信息:progress
(0-100), total
(總字節) and bytesSent
(已上傳字節)。這樣你能夠經過這寫信息自定義上傳進度條等。
若是你想給上傳的文件添加額外(多個文件時會具體到每一個文件),您能夠註冊發送事件:
myDropzone.on("sending", function(file, xhr, formData) { // Will send the filesize along with the file as POST data. formData.append("filesize", file.size); });
文件上傳以後,能夠經過file.previewElement
訪問上傳後文件的預覽html。例如:
myDropzone.on("addedfile", function(file) { file.previewElement.addEventListener("click", function() { myDropzone.removeFile(file); }); });
若是你想整個的body
都是一個Dropzone
實例並且在某個地方顯示文件預覽,那你能夠簡單地爲body
實例化一個Dropzone對象,提示定義previewsContainer
選項。這個previewsContainer
能夠是dropzone-previews
或dropzone
類,以便正確顯示文件預覽:
new Dropzone(document.body, { previewsContainer: ".dropzone-previews", // You probably don't want the whole body // to be clickable to select files clickable: false });
能夠在github wiki尋找更多的例子。
本節描述Dropzone兼容瀏覽器和舊版本。
Chrome 7+
Firefox 4+
IE 10+
Opera 12+ (MacOS V12版本沒法使用,由於它的API有問題)
Safari 6+
對於全部其餘瀏覽器,dropzone提供一個版的文件輸入回退。
在老式瀏覽器中拖放
是沒有解決方案,畢竟它不支持嘛~~,其次dropzone的圖片預覽也是一樣的道理。
可是,用戶使用老式瀏覽器仍是能夠上傳文件滴,只是看起來和感受起來都不是很棒。
哎,年代已經不屬於它們了。
這不是一個更新日誌。只列出兼容性問題。
改變默認previewTemplate。佈局作了新調整layout sectin.
使用SVG代替PNG spritemap(CSS文件如今惟一須要包括的附加文件)
這不是一個更新日誌。只列出兼容性問題。
這不是一個更新日誌。只列出兼容性問題。
從2.0版本開始,Dropzone再也不依賴jQuery,若是使用了jQuery,Dropzone 經過jQuery模塊的形式加載自身。
這意味着建立Dropzones這樣仍能工做:
$("#my-dropzone").dropzone({ /* options */ });
若是你經過普通構造函數的形式建立Dropzones,你必須經過原始HTMLElement,或者一個選擇器字符串選擇相應的元素,這樣該版本才能運行:
// With jQuery new Dropzone($("#my-dropzone").get(0)); // Without jQuery new Dropzone("#my-dropzone"); new Dropzone(document.querySelector("#my-dropzone"));
另一個改變就是,Dropzone再也不存儲實例內部元素的數據屬性。爲了獲得一個dropzone元素這樣作:
// DEPRECATED, do not use: $("#my-dropzone").data("dropzone"); // won't work anymore // Do this now: Dropzone.forElement(element); // Providing a raw HTMLElement // or Dropzone.forElement("#my-dropzone"); // Providing a selector string.
博客: http://blog.helloarron.com
Github: https://github.com/ArronYR
Email: yangyun4814@gmail.com
由於英語很差,花了一天的時間才完成,讓你們見笑了。有不少地方都不完善,還望你們指出修正,若是你以爲這個對你有用,還請點個「推薦」,謝謝!