/* NAME: DESCRIPTION: ; PARAMETER: [ { name : 'path', title : '资料路径', type : 'LineEdit', property : {tool_tip : '资料路径,必填'}, }, { name : 'db', title : '料号db', type : 'LineEdit', property : {tool_tip : '料号db,默认是genesis'}, }, { name : 'config_path', title : '配置地址', type : 'LineEdit', property : {tool_tip : '配置的路径'}, } ] VERSION_HISTORY: V1.01 2020-04-20 Scott Sun 1.新版本 HELP: <html><body bgcolor="#DDECFE"> <font size="3" color="#003DB2"><p>功能简介</p></font> <p> 客户数据导入 </p> <br> <font size="3" color="#003DB2"><p>参数配置</p></font> <p> 料号 和 客户配置 </p> <br> <font size="3" color="#003DB2"><p>注意事项</p></font> <p> 无 </p> <br> </body></html> */ ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// // 引入模块 包 console.log("=============================================>input_start"); console.log("=============================================>input_start"); console.log("=============================================>input_start"); console.log("=============================================>input_start"); var $ = require('topcam.scriptfunc').argv(); var fs = require('fs'); var _ = require('lodash'); var zip = require('topsin.zip'); var process = require('process'); var mode = $.ikm ? "topcam" : "aimdfm"; var IKM = $.ikm; if (IKM==undefined ) { IKM = require('topcam.ikm6')($) } var GEN = $.gen; var GUI = $.gui || {}; var Job = $.job || $.job_name; var JobId = $.job_id; var db = $.db || IKM.db var PAR = {} if ($.par) { PAR = $.par } else if ($.hasOwnProperty('script_parameter')){ PAR = JSON.parse($.script_parameter); } if (mode === "aimdfm") { var database = require("topsin.database"); database.addConnection($.conf.database_conf, "DFM"); var QDfm = database.query("DFM"); $.QDfm = QDfm; if ($.conf.product_type == "aimdfm") { QDfm.updateRow({ table: "pdm_aimdfm_task", data: { current_process_title: $.process_title, progress: 0 }, where: { id: $.task_id } }); } } var Status = 'ok'; var resultData = []; var import_info = []; var inputState = []; var cam_workflow_info = IKM.get_jobinfo({jobid:JobId, jobinfo:"cam_workflow_info"}); if(cam_workflow_info){ IKM.crud("deleteRow", { table: "pdm_job_jobattr", where:{job_id:JobId, attr_name:"cam_workflow_info"}, }) IKM.save_job_info({jobid:JobId, jobinfohash:{cam_workflow_info:""}}) } try { global._ERRORMAG = null; var par = PAR; // var db_path = db.query("",function(q){ // return q.selectValue({ // table:'pub_conf', // field:'text_data', // where:{path : "quote-data-upload"} // }) // }); // if(_.isEmpty(db_path)){throw "quote-data-upload error"} if(!par.path || par.path == "") { script_info({ msg: "Find data path", result_severity:"error" }); global._ERRORMAG = "The data path does not exist"; throw "path error"} if(!par.hasOwnProperty("config_path") || par.config_path==""){ console.log("===================cfg"); par.config_path = "cam/input_data" }; if(!par.hasOwnProperty("db") || par.db==""){ console.log("========================db"); par.db = "genesis" }; var db_customer = db.query("",function(q){ return q.selectValue({ table:'pdm_job', field:'customer_code', where:{id : JobId} }) }); if(_.isEmpty(db_customer)){ script_info({ msg: "Find customer", result_severity:"error" }); global._ERRORMAG = "No customer was found"; throw "customer error"} if(db_customer && !(/^done$/ig.test(db_customer)) && db_customer != "" ){ par.customer = db_customer } par.customer = par.customer[0].toUpperCase()+par.customer.slice(1).toLowerCase() var cfg = db.query("",function(q){ return q.selectValue({ table:'pub_conf', field:'text_data', where:{path : par.config_path} }) }); if (!cfg || cfg == ""){ script_info({ msg: "Find customer config", result_severity:"error" }); global._ERRORMAG = "No customer config was found"; throw "cfg can not find"} var config = eval(cfg); if(!config.hasOwnProperty("customer")){ script_info({ msg: "Find customer config", result_severity:"error" }); global._ERRORMAG = "No customer config was found"; throw "config error"} var job = Job; if(_.isEmpty(job)) throw "没有传入料号名!"; job = job.toLowerCase() // 如果genesis已经存在这个料号 err = delSameJob({job:job,delSame:config.delSameJob}); if(err){throw err}; var custCfg = config.customer[par.customer] if(!custCfg){throw "customer config error:"+par.customer} custCfg.db = par.db || custCfg.db var step = custCfg.step.toLowerCase() || "cad"; // 获取路径下文件信息 var path = par.path if(!fs.exists(path)){ script_info({ msg: "Find PN folder", result_severity:"error" }); global._ERRORMAG = "No PN file was found in folder"; throw "path error"} var pathInfo = fs.listDir(path + "/" + db_customer.toLowerCase(), 1) // 判断存不存在料号文件 // var vc_position = db.query("",function(q){ // return q.selectValue({ // table:'pdm_job', // field:'version', // where:{id : JobId} // }) // }); var job_file_baseName = job // if(vc_position && vc_position != "" && !(/null/ig.test(vc_position))){ // job_file_baseName = job_file_baseName + "_" + vc_position // } var jobFile = pathInfo.filter(function(v){return v.baseName.toLowerCase() == job_file_baseName}) if(jobFile.length == 0){ script_info({ msg: "Find PN folder", result_severity:"error" }); global._ERRORMAG = "No PN file was found in folder"; throw "job file is not exist"} var jobFiles = [] // 记录要分析的文件 if (!jobFile[0].isDir) { jobFiles.push(jobFile[0]) } else { jobFiles = fs.listDir(jobFile[0].path) } // GEN.COM("config_edit,name=iol_gbr_polygon_break,value=1,mode=user") // GEN.COM("config_edit,name=iol_fix_ill_polygon,value=yes,mode=user") // 将jobFile下的zip解压 script_info({ msg: "unzip the file", result_severity:"info" }) global._ERRORMAG = "Failed to unzip the file"; decompression(jobFile[0].path, []); changePath2(jobFile[0].path) var job_attrs = db.query("",function(q){ return q.selectValue({ table:'pdm_job', field_format:{job_attrs:'json'}, field:'job_attrs', where:{id : JobId} }) }); if (!job_attrs ) { job_attrs = {}} job_attrs.readin_result = "Readin" db.query("",function(q){ return q.updateRow({ table:'pdm_job', data:{job_attrs:job_attrs}, update_policy:{attr_data:'json_merge'}, where:{id : JobId} }) }); jobFiles = fs.listDir(jobFile[0].path) // 分析料号文件 得到料号导入信息 导入类型 var jobInfo = analyJobFiles({jobFiles:jobFiles.filter(function(v){return v.isFile}),custCfg:custCfg,config:config,job:job }) if(jobInfo.data.length == 0){ script_info({ msg: "Find PN folder", result_severity:"error" }); global._ERRORMAG = "No PN file was found in folder"; throw "file error"} var importOk = false; // 是否成功导入 script_info({ progress: 10 }) if(/odb/ig.test(jobInfo.type)){ // odb导入 script_info({ msg: "Import odb++", result_severity:"error" }); global._ERRORMAG = "Fail to import odb++"; if(jobInfo.data.length == 1){ // 只分析到一个tgz文件 直接导入 IKM.msg("只分析到一个tgz文件 直接导入"); import_info.push({name:jobInfo.data[0].file.name, type:"odb++", date:now(),user:$.user_name}); var err = importJob({name:job,db:custCfg.db,path:jobInfo.data[0].file.path},config.delSameJob); // 将step改名cad var step_tmp = GEN.getStepList({job:job})[0]; if(step_tmp != "cad"){ GEN.renameStep({job:job,name:step_tmp,new_name:'cad'}) } if(err){throw err} } else { // 多个tgz文件 说明需要合并 console.log("==========合并的情况"); var jobs = jobInfo.data.map(function(item, i){ var path = item.file.path var tmp_job_name = job + "_tmp_" + i var err = importJob({name:tmp_job_name,db:custCfg.db,path:path},config.delSameJob) import_info.push({name:item.file.name, type:"odb++", date:now(),user:$.user_name}) if(err){throw err} return { name:tmp_job_name, path: path } }) var step_all = []; // 分析arr_job 和 pcs_job jobs.forEach(function(item){ var jobname = item.name GEN.openJob({job:jobname}); var steps = GEN.getStepList({job:jobname}) steps.forEach(function(stepname){ var type = getStepType(stepname) // pcs arr if(type == "pcs"){ step_all.unshift({ jobname: jobname, stepname: stepname, type: type }) } if(type == "arr"){ step_all.push({ jobname: jobname, stepname: stepname, type: type }) } }) }) var pcs_job_name_tmp = step_all[0].jobname step_all = step_all.filter(function(item){ return item.jobname != pcs_job_name_tmp }) var pcs_job = jobs.filter(function(item){ return item.name == pcs_job_name_tmp })[0] importJob({name:job,db:custCfg.db,path:pcs_job.path},config.delSameJob) GEN.openJob({job:job}); step_all.forEach(function(item){ if(!GEN.isJobOpen({job:item.jobname})){ GEN.openJob({job:item.jobname})}; GEN.copyStep({ // 合并 source_job:item.jobname, source_name:item.stepname, dest_job:job, dest_name:item.stepname, }); }) jobs.forEach(function(item){ var v = item.name if(GEN.isJobOpen({ job: v })){ GEN.closeJob({ job: v }) } GEN.deleteJob({ job: v }); // 合并后 删除array的料号 }) } importOk = true } if(/gerber/ig.test(jobInfo.type)){ // gerber导入 script_info({ msg: "Import gerber", result_severity:"error" }); global._ERRORMAG = "Fail to import gerber"; GEN.createJob({name:job,db:custCfg.db}) GEN.createStep({job:job,name:step}) var gerberInfo = jobInfo.data.map(function(item){ var gerberCfg = JSON.parse(JSON.stringify(item.format)); var file = item.file gerberCfg.layer = file.name.toLowerCase().split(" ").join("-") gerberCfg.path = file.path gerberCfg.format = item.type gerberCfg.job = job gerberCfg.step = step return gerberCfg }) if(GEN.GEN_TYPE == "genesis"){ GEN.COM("input_manual_reset") gerberInfo.forEach(function(v){ import_info.push({name:v.layer, type:"gerber274x", date:now(),user:$.user_name}) GEN.COM("input_manual_set",v) GEN.COM("input_manual") }) } else { gerberInfo.forEach(function(v){ GEN.COM("input_result_reset,step=,category=warnings,close_tab=yes") GEN.COM("input_create,path="+v.path) GEN.COM("input_selected_reset") GEN.COM("input_selected_add,path="+v.path) GEN.COM("input_identify_selected,path=,job="+job+",script_path=,gbr_ext=no,drl_ext=no,gbr_units=auto,drl_units=auto,unify=yes,break_sr=yes,gbr_wtp_filter=*,drl_wtp_filter=*,gbr_wtp_units=auto,drl_wtp_units=auto,wtp_dir=,have_wheels=yes,wheel=,gbr_consider_headlines=yes,drl_consider_headlines=yes,board_size_x=0,board_size_y=0") GEN.COM("input_manual_reset") import_info.push({name:v.layer, type:"gerber274x", date:now(),user:$.user_name}) GEN.COM("input_manual_set",v) GEN.COM("input_manual") }) } importOk = true } if(!importOk){ throw "import error"} script_info({ progress: 20 }) global._ERRORMAG = null; reNameStep(job) if(/2171/.test(par.customer)){ // var matrix = GEN.getMatrix({job:job}); // comp = Object.keys(matrix).filter(function(v){ // 如果有comp层 删除 // return /^comp_\+_/ig.test(v) // }) // if (comp.length > 0){ // var tmp = GEN.getStepList({job:job}) // GEN.openStep({job:job,name:tmp[0]}) // GEN.COM("delete_comp") // GEN.closeStep() // } } else if ((/yucca/ig.test(par.customer))) { // var matrix = GEN.getMatrix({job:job,type:"array"}) // matrix.layer_type.forEach(function(v, i){ // if( v == "document") { // GEN.COM("matrix_layer_type,job="+job+",matrix=matrix,layer="+matrix.name[i]+",type=signal") // } // }) } var steplist = GEN.getStepList({job:job}) GEN.openStep({job:job,name:steplist[0]}) // 额外操作 if (custCfg.extra) { custCfg.extra.forEach(function(item){ var props = { type : jobInfo.type, fileInfo: jobInfo.data.filter(function(item2){return /Excellon/ig.test(item2.type) }), step:steplist[0] }; if(item.verification(props)){ item.fn(props); } }) } GEN.closeStep() GEN.checkInout({job:job,mode:"out"}) // 结束保存料号 关闭料号 GEN.saveJob({ job: job }); GEN.checkInout({job:job,mode:"in"}) GEN.closeJob({job:job}) var import_html = "<table border=1 align='center' cellpadding=5 cellspacing=0 style=\"text-align: center;\"><tr><th>导入状态/Import Status</th><th>文件/File</th><th>类型/Type</th><th>导入时间/Import Time</th><th>操作用户/User</th></tr>" import_info.forEach(function(item){ var name = item.name; var type = item.type; var date = item.date; var user = item.user; import_html += "<tr><td>Readin</td><td>"+name+"</td><td>"+type+"</td><td>"+date+"</td><td>"+user+"</td></tr>" }) import_html += "</table>" // name type date user resultData.push({type: "info",title:"导入资料列表",detail: [{ desc: import_html }] }) script_info({ msg: "Data Readin" }) if (mode === "aimdfm") { $.QDfm.updateRow({ table: "pdm_aimdfm_task", data: { progress: 30 }, where: { id: $.task_id } }); if (GEN.hasError()) { Status = 'error'; resultData.push({ type: "error", title: "GEN错误!", detail: [{ desc: _.join(GEN.STATUS, "\n") }] }); return { status: Status, result_data: resultData }; } else { resultData.push({ type: "info", title: "操作完成, 请注意检查!" }); return { status: Status, result_data: resultData }; } }else { return "Done" } } catch (e) { script_info({ result_severity: "error" }) if(global._ERRORMAG){ script_info({ msg: global._ERRORMAG }); var job_attrs = db.query("",function(q){ return q.selectValue({ table:'pdm_job', field_format:{job_attrs:'json'}, field:'job_attrs', where:{id : JobId} }) }); if (!job_attrs ) { job_attrs = {}} job_attrs.readin_result = global._ERRORMAG db.query("",function(q){ return q.updateRow({ table:'pdm_job', data:{job_attrs:job_attrs}, update_policy:{attr_data:'json_merge'}, where:{id : JobId} }) }); } IKM.crud("deleteRow", { table: "pdm_job_jobattr", where:{job_id:JobId, attr_name:"cam_workflow_info"}, }) IKM.save_job_info({jobid:JobId, jobinfohash:{cam_workflow_info:"err"}}) IKM.msg(_.join(GEN.STATUS, "\n")) IKM.msg(e) Status = 'error'; resultData.push({type: "error", title: "脚本执行出错!", detail: [{desc: _.toString(e)}]}); return (mode === "aimdfm") ? {status: Status, result_data: resultData} : "Error"; } function delSameJob(props){ var job = props.job var delSame = props.delSame console.log("======================>delsame:"+ delSame); if(GEN.isJobExists({job:job})){ if(/^yes$/ig.test(delSame)){ if(GEN.isJobOpen({job:job})){ GEN.closeJob({job:job}) } GEN.deleteJob({job:job}) } else { return "job "+ job+ " exist" } } } function analyJobFiles(props){ var files = props.jobFiles; var config = props.config; var job = props.job; var custCfg = props.custCfg; var rules = custCfg.rules; var paramsFile = files.filter(function(file){return /nc_param|ncdrill/ig.test(file.baseName)}) var tmp_hash = {} paramsFile.forEach(function(file){ tmp_hash[file.baseName] = (function(){ var tmparr = fs.readFile(file.path).split("\n").filter(function(v){return /^\s?\S+\s+\S/ig.test(v)}).filter(function(v){return !/\(/.test(v)}) var tmp = {} tmparr.map(function(v){ var arr = v.split(/\b\s+\b/) tmp[arr[0].replace(/-/ig,"_").trim()] = arr[1] }) return tmp })() }) var fileInfo = files.reduce(function(a,file){ try { rules.forEach(function(item){ if(item.valid({file:file, job:job})){ var format = config.formats[item.format] var format1; if(item.format_params){ format1 = item.format_params({params:tmp_hash}) } if(format1){ throw {file:file,type:item.type,format:format1} }else{ throw {file:file,type:item.type,format:format} } } }) } catch (info) { a.push(info) } return a },[]) var odbfiles = fileInfo.filter(function(item){return /odb/ig.test(item.type)}) if(odbfiles.length == 0){ return { type: "Gerber", data: fileInfo } } else { return { type: "ODB", data: odbfiles } } } function importJob(props,delSameJob){ var name = props.name if (GEN.isJobExists({ job: name })) { if (/^yes$/ig.test(delSameJob)) { if(GEN.isJobOpen({ job: name })){ GEN.closeJob({ job: name }); } GEN.deleteJob({ job: name }); } else { return "job "+name+" exist"; } } props.path = changePath(props.path) // 如果path的tgz不符合规范 纠正一下 GEN.importJob(props); } function getStepType(step){ if(/pcs|cad|orig|pcb/ig.test(step)){ return "pcs" } if(/stp|arr/ig.test(step)){ return "arr" } return "pcs" } function now(){ var date = new Date() var time = _.toString(date) res1 = /\d{4}-\d{2}-\d{2}/.exec(time) res2 = /\d{2}:\d{2}:\d{2}/.exec(time) return res1 + " " +res2 } function reNameStep(job) { var stepList = GEN.getStepList({job:job}) if(!stepList){return} var pcs = [] var arr = [] stepList.forEach(function(v){ if(v){ if(v==="cad"){ pcs.unshift(v) } else if(/pcs|cad|orig|pcb/ig.test(v)){ pcs.push(v) } else if(/stp|arr/ig.test(v)){ arr.push(v) } } }) pcs.forEach(function(v, i){ if (i==0 && v == "cad") { } else { GEN.renameStep({job:job,name:v,new_name:'cad' + (i == 0? "" : i+1)}) } }) arr.forEach(function(v, i){ if (i==0 && v == "stp") { } else { GEN.renameStep({job:job,name:v,new_name:'stp' + (i == 0? "" : i+1)}) } }) } function script_info(props){ // result_severity progress if (mode === "aimdfm") { $.QDfm.updateRow({ table: "pdm_aimdfm_task", data: props, where: { id: $.task_id } }); } } function decompression(path, zips) { var files = fs.listDir(path) var count = 0; var zipfiles = files.filter(function(item){ if (item.suffix == "zip" || item.suffix == "rar" || item.suffix=="7z" || item.suffix == "ZIP") { inputState.push(item.suffix); console.log("--->path:" + item.path) if(zips.indexOf(item.path) < 0){ zips.push(item.path); if(item.name.length >= 30 && !/�|\?/.test(item.name)) { var mvname = "custom" + count + "." + item.suffix; count++; fs.rename(item.path, item.dir + "/" + mvname); item.path = item.dir + "/" + mvname } var dir_name = item.path.replace(/\.(zip|7z|rar)$/ig, ""); autoUn(item.path, dir_name); return true } } // else if(/7z/.test(item.completeSuffix)){ // inputState.push("7z"); // if(zips.indexOf(item.path) < 0){ // zips.push(item.path); // var dir_name = item.path.replace(".7z", ""); // autoUn(item.path, dir_name); // return true // } // } return false }) if(zipfiles.length) {decompression(path, zips)} } function changePath(path) { return path.replace(/[^/]+\//ig, function(v){ if(v.length >= 10 && /\s/ig.test(v)) { v = v.replace(" ", "\\ ") return v.slice(0,6) + "~1/" } else { return v } }) } function autoUn(path, dirname) { if(/\.rar$/.test(path)){ fs.mkdir(dirname) process.exec('/opt/rar/unrar', ['x' , path, dirname, "-o+"]) } else { process.exec('/usr/local/lib/p7zip/7za', ['x' , path, "-o"+dirname, "-aoa"]) } } function exportInfo(info){ fs.writeFile("/home/toplinker/samba/Test_Scott/tmp", _.toString(info)) } function changePath2(filePath){ var fileList = fs.listDir(filePath); var tmp = []; for(var i = 0;i<fileList.length;i++){ if(fileList[i].isDir){ var path = fileList[i].path; var fileName = fileList[i].baseName; var obj = { path:path, fileName:fileName } tmp.push(obj); } } var list = []; for(var i = tmp.length-1;i>=0;i--){ var newFileName = tmp[i].fileName.replace(/\s*/g,'');//去除文件名中空格 newFileName = newFileName.replace(/\?/g,'');//去除文件名中? var newPath = tmp[i].path.replace(/^(.*)\/[^\/]*$/,"$1"); var file = fs.rename(tmp[i].path,newPath+'/'+newFileName); list.push(file); } }