Bläddra i källkod

Read from excel

NaiboWang-Alienware 2 år sedan
förälder
incheckning
bb1f25e9ca

+ 8 - 1
ElectronJS/config.json

@@ -1 +1,8 @@
-{"webserver_address":"http://localhost","webserver_port":8074,"user_data_folder":"./user_data","debug":true,"absolute_user_data_folder":"D:\\Document\\Projects\\EasySpider\\ElectronJS\\user_data"}
+{
+  "webserver_address": "http://localhost",
+  "webserver_port": 8074,
+  "user_data_folder": "./user_data",
+  "debug": false,
+  "mysql_config_path": "./mysql_config.json",
+  "absolute_user_data_folder": "D:\\Document\\Projects\\EasySpider\\ElectronJS\\user_data"
+}

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 597 - 22
ElectronJS/package-lock.json


+ 3 - 0
ElectronJS/package.json

@@ -31,7 +31,10 @@
     },
     "repository": "https://github.com/NaiboWang/EasySpider",
     "dependencies": {
+        "cors": "^2.8.5",
         "electron-squirrel-startup": "^1.0.0",
+        "express": "^4.18.2",
+        "formidable": "^3.5.0",
         "http": "^0.0.1-security",
         "multer": "^1.4.5-lts.1",
         "node-window-manager": "^2.2.4",

+ 56 - 3
ElectronJS/server.js

@@ -5,7 +5,11 @@ const fs = require('fs');
 const path=require('path');
 const {app, dialog} = require('electron');
 const XLSX = require('xlsx');
+const formidable = require('formidable');
+const express = require('express');
 const multer  = require('multer');
+const cors = require('cors');
+
 function travel(dir,callback){
     fs.readdirSync(dir).forEach((file)=>{
         const pathname=path.join(dir,file)
@@ -59,13 +63,63 @@ if(!fs.existsSync(path.join(getDir(), "config.json"))){
 exports.getDir = getDir;
 exports.getEasySpiderLocation = getEasySpiderLocation;
 FileMimes = JSON.parse(fs.readFileSync(path.join(__dirname,'mime.json')).toString());
+
+const fileServer = express();
+const upload = multer({ dest: 'Data/' });
+
+fileServer.use(cors());
+fileServer.post('/excelUpload', upload.single('file'), (req, res) => {
+    let workbook = XLSX.readFile(req.file.path);
+    let sheet_name_list = workbook.SheetNames;
+    let data = XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]]);
+    let result = data.reduce((acc, obj) => {
+        Object.keys(obj).forEach(key => {
+            if(!acc[key]) {
+                acc[key] = [];
+            }
+            acc[key].push(obj[key]);
+        });
+        return acc;
+    }, {});
+    // console.log(data);
+    // delete file after reading
+    fs.unlink(req.file.path, (err) => {
+        if (err) {
+            console.error(err);
+            return;
+        }
+        // file removed
+    });
+    res.send(JSON.stringify(result));
+});
+
+fileServer.listen(8075, () => {
+    console.log('Server listening on http://localhost:8075');
+});
+
+
 exports.start = function(port = 8074) {
     http.createServer(function(req, res) {
         let body = "";
         res.setHeader("Access-Control-Allow-Origin", "*"); // 设置可访问的源
         // 解析参数
         const pathName = url.parse(req.url).pathname;
-        if(pathName.indexOf(".") < 0) { //如果没有后缀名, 则为后台请求
+        if(pathName == "/excelUpload" && req.method.toLowerCase() === 'post'){
+            // // parse a file upload
+            // let form = new formidable.IncomingForm();
+            // // Set the max file size
+            // form.maxFileSize = 200 * 1024 * 1024; // 200MB
+            // form.parse(req, function (err, fields, files) {
+            //     console.log("excelUpload")
+            //     console.log(err, fields, files);
+            //     let oldpath = files.file.path;
+            //     let workbook = XLSX.readFile(oldpath);
+            //     let sheet_name_list = workbook.SheetNames;
+            //     let data = XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]]);
+            //     console.log(data);
+            //     res.end('File uploaded and read successfully.');
+            // });
+        } else if(pathName.indexOf(".") < 0) { //如果没有后缀名, 则为后台请求
             res.writeHead(200, { 'Content-Type': 'application/json' });
         }
         // else if(pathName.indexOf("index.html") >= 0) {
@@ -133,8 +187,7 @@ exports.start = function(port = 8074) {
             } else if(pathName == "/queryOSVersion") {
                 res.write(JSON.stringify({"version":process.platform, "bit":process.arch}));
                 res.end();
-            }
-            else if (pathName == "/queryExecutionInstances") { //查询所有服务信息,只包括id和服务名称
+            } else if (pathName == "/queryExecutionInstances") { //查询所有服务信息,只包括id和服务名称
                 output = [];
                 travel(path.join(getDir(), "execution_instances"),function(pathname){
                     const data = fs.readFileSync(pathname, 'utf8');

+ 131 - 8
ElectronJS/src/taskGrid/invokeTask.html

@@ -31,6 +31,12 @@
         .ID {
             width: 10%;
         }
+        .excel th,.excel td{
+            text-align: center;
+            font-size: 13px;
+            padding: 10px;
+            max-width: 200px!important;
+        }
     </style>
 </head>
 
@@ -43,7 +49,7 @@
 </div>
 
 <div class="row" style="margin-top: 40px;">
-    
+
     <div class="col-md-7" id="taskInfo" style="margin:0 auto" v-if="show">
 
 
@@ -70,7 +76,80 @@
                 <!-- /.modal-content -->
             </div>
         </div>
-        
+
+        <div class="modal fade" id="excelModal" tabindex="-1" role="dialog" aria-labelledby="excelModalLabel" aria-hidden="true">
+            <div class="modal-dialog modal-lg">
+                <div class="modal-content">
+                    <div class="modal-header">
+                        <h4 class="modal-title" id="excelModalLabel">{{"Read from Excel~从Excel文件读取输入参数" | lang}}</h4>
+                        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
+                    </div>
+                    <div class="modal-body">
+<!--                        <form action="/upload" method="post" enctype="multipart/form-data">-->
+                        <div>
+                        <div class="form-group" style="margin-bottom: 10px">
+                            <label>{{"Please select an Excel file (.xlsx)~请选择一个Excel文件(.xlsx)" | lang}}</label>
+                            <input type="file" class="form-control-file" id="excelFile" name="file">
+                            <label style="display: block; margin-top:10px;margin-bottom: 0">{{fileUploadStatus | lang}}</label>
+                        </div>
+
+                            <button @click="submitFile" class="btn btn-primary" style="min-width: 100px;margin-bottom:10px">{{"Upload~上传" | lang}}</button>
+
+<!--                        </form>-->
+                        </div>
+                        <label style="margin:10px 0">{{"Please design an Excel file (.xlsx) according to the following format and upload it above.~请按照以下格式设计一个Excel文件(.xlsx),并在上方上传:"  | lang}}</label>
+                        <table class="table table-bordered excel" style="text-align: center; font-size: 13px">
+                            <thead>
+                                <tr>
+                                    <th scope="col">{{"Invoke Name 1~调用名称1" | lang}}</th>
+                                    <th scope="col">{{"Invoke Name 2~调用名称2" | lang}}</th>
+                                    <th scope="col">...</th>
+                                </tr>
+                            </thead>
+                            <tbody>
+                            <tr>
+                                <td>{{"Argument Value 1_1~参数值1_1" | lang}}</td>
+                                <td>{{"Argument Value 2_1~参数值2_1" | lang}}</td>
+                                <td>...</td>
+                            </tr>
+                            <tr>
+                                <td>{{"Argument Value 1_1~参数值1_2" | lang}}</td>
+                                <td>{{"Argument Value 2_1~参数值2_2" | lang}}</td>
+                                <td>...</td>
+                            </tr>
+                            </tbody>
+                        </table>
+                        <label>{{"The 'Invoke Name' is shown at the main table of this page, such as 'urlList_0' is the invoke name of the open page operation.~“调用名称”在本页面的主表格中显示,例如“urlList_0”是“打开网页“操作的调用名称。" | lang}}</label>
+                        <label>{{"You can just put part of the arguments in the Excel file, and the values of the rest of the arguments will be set to default. Example table for this task is:~您可以只在Excel文件中放入部分参数,其余参数值将被设置为默认值。一个针对此任务的表格示例为:" | lang}}</label>
+                        <table class="table table-bordered excel">
+                            <tbody>
+                            <tr>
+                                <td v-for="i in Math.min(3, task.inputParameters.length)" v-if="task.inputParameters.length>0">
+                                    {{task.inputParameters[i-1]["name"]}}
+                                </td>
+                            </tr>
+                            <tr>
+                                <td v-for="i in Math.min(3, task.inputParameters.length)" v-if="task.inputParameters.length>0">
+                                    {{task.inputParameters[i-1]['value']}}
+                                </td>
+                            <tr>
+                            <tr>
+                                <td v-for="i in Math.min(3, task.inputParameters.length)">
+                                    <div v-if="task.inputParameters[i-1]['name'].indexOf('url') >=0">
+                                        {{task.inputParameters[i-1]['value']}}
+                                    </div>
+                                </td>
+                            <tr>
+                            </tbody>
+                        </table>
+
+                    </div>
+                </div>
+                <!-- /.modal-content -->
+            </div>
+        </div>
+
+
         <nav aria-label="breadcrumb">
             <ol class="breadcrumb" style="padding-left:0;background-color: white">
                 <li @click="gotoHome" class="breadcrumb-item"><a href="#">{{"Home~首页" | lang}}</a></li>
@@ -86,7 +165,10 @@
         <p style="word-wrap: break-word;word-break: break-all;overflow: hidden;max-height: 100px;">{{"API URL (POST):~API 调用网址(POST):" |
             lang}} {{backEndAddressServiceWrapper}}/invokeTask?id={{task["id"]}}</p>
         <p style="word-wrap: break-word;word-break: break-all;overflow: hidden;max-height: 100px;">{{"Click here to see how to invoke task by API via POST request: ~点此查看通过POST方式进行API调用的示例代码:" | lang}}<a target="_blank" href="https://github.com/NaiboWang/EasySpider/wiki/API-Invoke-Example">https://github.com/NaiboWang/EasySpider/wiki/API-Invoke-Example</a></p>
-        <p>{{"Please Input Parameters:~请输入参数值:" | lang}} </p>
+        <p><button class="btn btn-primary" @click="readFromExcel">{{"Read parameters from Excel file~从Excel文件读取输入参数"
+            | lang}}
+        </button></p>
+        <p>{{"Please Input Parameters:~请输入参数值:" | lang}}</p>
         <form id="form">
             <table class="table table-bordered">
                 <tbody>
@@ -161,7 +243,9 @@
             task: {},
             show: false, //是否渲染
             ID: "",
+            file:null,
             user_data_folder:"",
+            fileUploadStatus: "Status: Waiting for upload~状态:等待上传",
             with_user_data: true,
             backEndAddressServiceWrapper: getUrlParam("backEndAddressServiceWrapper"),
             command: "./easyspider_executestage ",
@@ -190,7 +274,46 @@
                     url = "taskInfo.html?id="+getUrlParam("id")+"&lang=en&type="+getUrlParam("type")+"&wsport="+getUrlParam("wsport")+"&backEndAddressServiceWrapper=" + app.$data.backEndAddressServiceWrapper
                 }
                 window.location.href = url;
-            }, invokeTask: function () {
+            }, readFromExcel: function(){
+                $('#excelModal').modal('show');
+            }, submitFile: function() {
+                let form_data = new FormData();
+                this.file = $('#excelFile').prop('files')[0];
+                if(this.file == null || $('#excelFile').val() == ""){
+                    this.fileUploadStatus = "Status: Please select a file~状态:请选择文件";
+                    return;
+                }
+                if (this.file.name.split('.').pop() !== 'xlsx' ) {
+                    this.fileUploadStatus = "Status: Only xlsx files are allowed!~状态:只允许上传xlsx文件!";
+                    return;
+                }
+                // form_data.append('file', this.file);
+                form_data.append('file', $('#excelFile').prop('files')[0]);
+                // console.log(app.$data.backEndAddressServiceWrapper + "/excelUpload",)
+                $.ajax({
+                    url: app.$data.backEndAddressServiceWrapper.replace("8074","8075") + "/excelUpload",
+                    type: 'POST',
+                    data: form_data,
+                    processData: false,
+                    contentType: false,
+                    success: function(response) {
+                        response = JSON.parse(response);
+                        $('#excelModal').modal('hide');
+                        app.$data.fileUploadStatus = "Status: Upload successfully~状态:上传成功";
+                        $('#excelFile').val("");
+                        let inputParameters = app.$data.task.inputParameters;
+                        inputParameters.forEach(function (item, index) {
+                            if(Object.keys(response).includes(item.name)){
+                                item.value = "\r\n".join(response[item.name]);
+                            }
+                        });
+                    },
+                    error: function(err) {
+                        app.$data.fileUploadStatus = "Status: Upload failed~状态:上传失败";
+                    }
+                });
+            },
+            invokeTask: function () {
                 let text = "";
                 // if (getUrlParam("lang") == "en" || getUrlParam("lang") == "") {
                 //     text = "Are you sure to get the Execution ID (EID) of current running task?";
@@ -257,7 +380,7 @@
                 // } else {
                 //     text = "确定要立即在本地运行此任务吗?";
                 // }
-                
+
                 this.with_user_data = with_user_data;
                 // if (confirm(text)) {
                     let para = {};
@@ -292,7 +415,7 @@
             },
         }
     });
-    
+
     function changeCommand() {
         $.get(app.$data.backEndAddressServiceWrapper + "/queryOSVersion", function (OSInfo) {
             if(OSInfo.version == 'win32' && OSInfo.bit == 'x64'){
@@ -316,7 +439,7 @@
         app.$data.task = result;
         app.$data.show = true;
     });
-    
+
     ws = new WebSocket("ws://localhost:"+getUrlParam("wsport"));
     ws.onopen = function () {
         // Web Socket 已连接上,使用 send() 方法发送数据
@@ -338,4 +461,4 @@
         // 关闭 websocket
         console.log("连接已关闭...");
     };
-</script>
+</script>

+ 4 - 4
ElectronJS/src/taskGrid/taskInfo.html

@@ -13,7 +13,7 @@
         table {
             table-layout: auto;
         }
-        
+
         table,
         td,
         th,
@@ -25,7 +25,7 @@
             max-width: 400px;
             min-width: 150px;
         }
-        
+
         .ID {
             width: 10%;
         }
@@ -56,7 +56,7 @@
                     <tr>
                         <th style="min-width: 50px;">ID</th>
                         <th>{{"Parameter Name~参数名称" | lang}}</th>
-                        <th>{{"Invoke Name~调用名" | lang}}</th>
+                        <th>{{"Invoke Name~调用名" | lang}}</th>
                         <th>{{"Parameter Type~参数类型" | lang}}</th>
                         <th>{{"Example Value~示例值" | lang}}</th>
                         <th>{{"Parameter Description~参数描述" | lang}}</th>
@@ -156,4 +156,4 @@
         app.$data.task = result;
         app.$data.show = true;
     });
-</script>
+</script>

Vissa filer visades inte eftersom för många filer har ändrats