| | |
| | | const scriptDir = __dirname; |
| | | const rootDir = path.resolve(scriptDir, '..'); |
| | | const argv2 = process.argv[2]; |
| | | const arg2 = argv2?.split(' '); |
| | | |
| | | const customerList = arg2?.[0] ? (arg2[0] === 'pro' ? ['ch:pro'] : ['ch']) : ['ch']; |
| | | const customerList = argv2?.split(' ') ?? ''; |
| | | const publicDir = path.join(rootDir, 'public'); |
| | | const distDir = path.join(rootDir, 'dist'); |
| | | const customerListDir = path.join(rootDir, 'customer_list'); |
| | | const customerProjectListDir = path.join(rootDir, 'src', 'views', 'project'); |
| | | const homeDir = os.homedir(); |
| | | const firstCustomerName = customerList[0]?.split(':')[0]; |
| | | /** 公共文件夹,所有客户文件夹共享文件 */ |
| | | const commonDir = path.join(customerListDir, 'common'); |
| | | |
| | | const item = customerList[0]; |
| | | const customerSplit = item?.split(':'); |
| | | const deployEnv = customerSplit?.[1]; |
| | | // 是否为生产环境 |
| | | const isPro = deployEnv==='pro'; |
| | | // const deployEnv = process.argv[3]; |
| | | |
| | | const logColor = (text, color) => { |
| | |
| | | logColor(text, 'green'); |
| | | }; |
| | | |
| | | const logWarn = (text) => { |
| | | logColor(text, 'yellow'); |
| | | }; |
| | | |
| | | /** |
| | | * 退出脚本 |
| | | */ |
| | | const exit = () => { |
| | | process.exit(1); // 退出脚本 |
| | | }; |
| | | |
| | | /** |
| | | * 检查文件是否存在 |
| | | * @param {*} file |
| | | * @param {*} fileText |
| | | */ |
| | | const checkFileExist = (file, fileText) => { |
| | | const checkFileExist = (file, fileText = '') => { |
| | | // 验证源文件夹是否存在 |
| | | if (!fs.existsSync(file)) { |
| | | console.error(chalk.red(`${fileText} "${file}" 不存在!`)); |
| | | process.exit(1); // 退出脚本 |
| | | console.error(chalk.red(`${fileText ? fileText + ' ' : ''}"${file}" 不存在!`)); |
| | | exit(); // 退出脚本 |
| | | } |
| | | }; |
| | | |
| | |
| | | * @param {*} command |
| | | * @param {*} customer |
| | | */ |
| | | const checkCustomer = (command, customer) => { |
| | | const checkCustomer = (command, customer = firstCustomerName) => { |
| | | if (!customer) { |
| | | console.error(chalk.red(`请正确使用命令 “${command} [customer]” `)); |
| | | |
| | | process.exit(1); // 退出脚本 |
| | | exit(); // 退出脚本 |
| | | } |
| | | checkCustomerDirExist(customer); |
| | | }; |
| | | |
| | | let tmpBakDir = ''; |
| | | const moveProjectsToBakDir = (command) => { |
| | | const customer = customerList[0]?.split(':')[0]; |
| | | checkCustomer(command, customer); |
| | | //#region ====================== 创建备份文件夹 ====================== |
| | | let tmpBakRootDir = path.join(homeDir, 'Desktop'); |
| | | if (!fs.existsSync(tmpBakRootDir)) { |
| | | tmpBakRootDir = homeDir; |
| | | } |
| | | tmpBakDir = path.join(tmpBakRootDir, 'bak_project_list'); |
| | | |
| | | fs.ensureDirSync(tmpBakDir); |
| | | fs.emptyDirSync(tmpBakDir); |
| | | //#endregion |
| | | |
| | | const contents = fs.readdirSync(customerProjectListDir); |
| | | for (let index = 0; index < contents.length; index++) { |
| | | const item = contents[index]; |
| | | if (item === customer) { |
| | | continue; |
| | | } |
| | | const itemPath = path.join(customerProjectListDir, item); |
| | | const stats = fs.statSync(itemPath); |
| | | if (stats.isDirectory()) { |
| | | const destBakDir = path.join(tmpBakDir, item); |
| | | fs.moveSync(itemPath, destBakDir, { overwrite: true }); |
| | | } |
| | | } |
| | | const replaceFileContent = (path, callback) => { |
| | | const data = fs.readFileSync(path, 'utf8'); |
| | | if (!data) return; |
| | | const newData = callback(data); |
| | | fs.writeFileSync(path, newData, 'utf8'); |
| | | }; |
| | | |
| | | const restoreProjectDir = () => { |
| | | const contents = fs.readdirSync(tmpBakDir); |
| | | for (let index = 0; index < contents.length; index++) { |
| | | const item = contents[index]; |
| | | const itemPath = path.join(tmpBakDir, item); |
| | | const destProjectDir = path.join(customerProjectListDir, item); |
| | | fs.moveSync(itemPath, destProjectDir, { overwrite: true }); |
| | | const replaceGlobImportPattern = /import.meta.glob\s*\((\s*.*\/views\/\*\*.*)\)/; |
| | | const matchAllPattern = '../views/**/*.{vue,tsx}'; |
| | | |
| | | /** |
| | | * 修改 src/router/backEnd.ts 文件,只导入当前项目文件 |
| | | * @param {*} command |
| | | */ |
| | | const updateImportGlob = () => { |
| | | const backEndFilePath = path.join(rootDir, 'src', 'router', 'backEnd.ts'); |
| | | checkFileExist(backEndFilePath, `${backEndFilePath}文件`); |
| | | const subFile = fs.readdirSync(customerListDir); |
| | | const filterSubFile = subFile?.filter((item) => item !== firstCustomerName); |
| | | |
| | | replaceFileContent(backEndFilePath, (data) => { |
| | | const excludeCustomer = filterSubFile && filterSubFile.length > 0 ? `/(${filterSubFile.join('|')})` : ''; |
| | | const excludePattern = `!../views/project${excludeCustomer}/**/*`; |
| | | const replaceStr = `import.meta.glob(['${matchAllPattern}', '${excludePattern}'])`; |
| | | const newData = data.replace(replaceGlobImportPattern, replaceStr); |
| | | return newData; |
| | | }); |
| | | }; |
| | | |
| | | const restoreImportGlob = () => { |
| | | const backEndFilePath = path.join(rootDir, 'src', 'router', 'backEnd.ts'); |
| | | checkFileExist(backEndFilePath, `${backEndFilePath}文件`); |
| | | |
| | | replaceFileContent(backEndFilePath, (data) => { |
| | | const replaceStr = `import.meta.glob('${matchAllPattern}')`; |
| | | const newData = data.replace(replaceGlobImportPattern, replaceStr); |
| | | return newData; |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * 获取当前日期是第几周 |
| | | * @param dateTime 当前传入的日期值 |
| | | * @returns 返回第几周数字值 |
| | | */ |
| | | const getWeek = (dateTime) => { |
| | | const temptTime = new Date(dateTime.getTime()); |
| | | // 周几 |
| | | const weekday = temptTime.getDay() || 7; |
| | | // 周1+5天=周六 |
| | | temptTime.setDate(temptTime.getDate() - weekday + 1 + 5); |
| | | let firstDay = new Date(temptTime.getFullYear(), 0, 1); |
| | | const dayOfWeek = firstDay.getDay(); |
| | | let spendDay = 1; |
| | | if (dayOfWeek != 0) spendDay = 7 - dayOfWeek + 1; |
| | | firstDay = new Date(temptTime.getFullYear(), 0, 1 + spendDay); |
| | | const d = Math.ceil((temptTime.valueOf() - firstDay.valueOf()) / 86400000); |
| | | const result = Math.ceil(d / 7); |
| | | return result; |
| | | }; |
| | | |
| | | /** |
| | | * 时间日期转换 |
| | | * @param date 当前时间,new Date() 格式 |
| | | * @param format 需要转换的时间格式字符串,默认值YYYY-mm-dd HH:MM:SS |
| | | * @description format 字符串随意,如 `YYYY-mm、YYYY-mm-dd` |
| | | * @description format 季度:"YYYY-mm-dd HH:MM:SS QQQQ" |
| | | * @description format 星期:"YYYY-mm-dd HH:MM:SS WWW" |
| | | * @description format 几周:"YYYY-mm-dd HH:MM:SS ZZZ" |
| | | * @description format 季度 + 星期 + 几周:"YYYY-mm-dd HH:MM:SS WWW QQQQ ZZZ" |
| | | * @returns 返回拼接后的时间字符串 |
| | | */ |
| | | const formatDate = (date, format = 'YYYY-mm-dd HH:MM:SS') => { |
| | | const we = date.getDay(); // 星期 |
| | | const z = getWeek(date); // 周 |
| | | const qut = Math.floor((date.getMonth() + 3) / 3).toString(); // 季度 |
| | | const opt = { |
| | | 'Y+': date.getFullYear().toString(), // 年 |
| | | 'm+': (date.getMonth() + 1).toString(), // 月(月份从0开始,要+1) |
| | | 'd+': date.getDate().toString(), // 日 |
| | | 'H+': date.getHours().toString(), // 时 |
| | | 'M+': date.getMinutes().toString(), // 分 |
| | | 'S+': date.getSeconds().toString(), // 秒 |
| | | 'q+': qut, // 季度 |
| | | }; |
| | | // 中文数字 (星期) |
| | | const week = { |
| | | 0: '日', |
| | | 1: '一', |
| | | 2: '二', |
| | | 3: '三', |
| | | 4: '四', |
| | | 5: '五', |
| | | 6: '六', |
| | | }; |
| | | // 中文数字(季度) |
| | | const quarter = { |
| | | 1: '一', |
| | | 2: '二', |
| | | 3: '三', |
| | | 4: '四', |
| | | }; |
| | | if (/(W+)/.test(format)) |
| | | format = format.replace(RegExp.$1, RegExp.$1.length > 1 ? (RegExp.$1.length > 2 ? '星期' + week[we] : '周' + week[we]) : week[we]); |
| | | if (/(Q+)/.test(format)) format = format.replace(RegExp.$1, RegExp.$1.length == 4 ? '第' + quarter[qut] + '季度' : quarter[qut]); |
| | | if (/(Z+)/.test(format)) format = format.replace(RegExp.$1, RegExp.$1.length == 3 ? '第' + z + '周' : z + ''); |
| | | for (const k in opt) { |
| | | const r = new RegExp('(' + k + ')').exec(format); |
| | | // 若输入的长度不为1,则前面补零 |
| | | if (r) format = format.replace(r[1], RegExp.$1.length == 1 ? opt[k] : opt[k].padStart(RegExp.$1.length, '0')); |
| | | } |
| | | return format; |
| | | }; |
| | | |
| | | /** |
| | |
| | | * @param {*} command |
| | | * @param {*} customer |
| | | */ |
| | | function copyFile(command) { |
| | | const customer = customerList[0]?.split(':')[0]; |
| | | checkCustomer(command, customer); |
| | | function copyFile() { |
| | | // 确保 public 文件,不存在则创建 |
| | | fs.ensureDirSync(publicDir); |
| | | // 清空 public 文件夹 |
| | |
| | | return true; |
| | | }; |
| | | |
| | | const customerDir = path.join(customerListDir, customer); |
| | | |
| | | const customerDir = path.join(customerListDir, firstCustomerName); |
| | | // 复制源文件夹中的所有文件到 public 文件夹 |
| | | fs.copySync(customerDir, publicDir, { filter }); |
| | | fs.copySync(commonDir, publicDir); |
| | | } |
| | | |
| | | /** |
| | |
| | | // 读取 JSON 文件 |
| | | const config = await fs.readJson(deployJSON).catch((err) => { |
| | | console.error(`读取配置文件“${deployJSON}”出错:`, err); |
| | | process.exit(1); |
| | | exit(); |
| | | }); |
| | | |
| | | let deployConfig = null; |
| | |
| | | } |
| | | if (!deployConfig || Object.values(deployConfig).some((item) => !item)) { |
| | | console.error(chalk.red(`${customerName} ${deployEnv} 配置不完整!`)); |
| | | process.exit(1); // 退出脚本 |
| | | exit(); // 退出脚本 |
| | | } |
| | | // 缓存部署配置 |
| | | customerConfig[item] = deployConfig; |
| | |
| | | } |
| | | |
| | | try { |
| | | // 批量备份文件夹到本地 |
| | | // FIXME: 文件夹如果是中文,会乱码 |
| | | // uploadCommand=`get -r /D:/IStation.SQI.WebAirp E:\\139.224.246.185_bak\\IStation.SQI.WebAirp` |
| | | fs.writeFileSync(uploadScriptFile, uploadCommand); |
| | | const sftpArgs = [ |
| | | `${deployConfig.username}@${deployConfig.host} -P ${deployConfig.port} -pw ${deployConfig.password} -b ${uploadScriptFile}`, |
| | |
| | | } |
| | | } |
| | | } |
| | | logSuccess(`🎉🎉🎉【${customerList.join(',')}】项目已成功部署!🎉🎉🎉`); |
| | | logSuccess(`${formatDate(new Date(), 'HH:MM:SS')} > 🎉🎉🎉【${customerList.join(',')}】项目已成功部署!🎉🎉🎉`); |
| | | }; |
| | | |
| | | /** |
| | | * 切换分支 |
| | | */ |
| | | const changeBranch = () =>{ |
| | | return; |
| | | if (isPro) { |
| | | try { |
| | | execSync('git checkout master', { stdio: 'inherit' }); |
| | | } catch (error) {} |
| | | } else { |
| | | try { |
| | | execSync('git checkout test', { stdio: 'inherit' }); |
| | | } catch (error) {} |
| | | } |
| | | } |
| | | |
| | | module.exports = { |
| | | isPro, |
| | | firstCustomerName, |
| | | exit, |
| | | customerList, |
| | | replaceFileContent, |
| | | checkFileExist, |
| | | //#region ====================== 文件路径 ====================== |
| | | rootDir, |
| | | scriptDir, |
| | |
| | | //#region ====================== 打印 ====================== |
| | | logError, |
| | | logSuccess, |
| | | logWarn, |
| | | //#endregion |
| | | formatDate, |
| | | |
| | | moveProjectsToBakDir, |
| | | restoreProjectDir, |
| | | updateImportGlob, |
| | | restoreImportGlob, |
| | | deployEnv, |
| | | changeBranch |
| | | }; |