using System; using System.Web; using System.Collections.Generic; using System.Linq; using System.Data; using System.IO; using System.IO.Compression; using Customer.Source; using Common; using System.Text.RegularExpressions; using Infrastructure; using NuGet.Configuration; namespace Util.MakeApp { public class MakeAppleCode { #region 生成文件 public static void MakerFile(string fileName, AppProject project, AppProjectVersion ver, List smodules, List codes, List modules, List paramList, List fileList, List pages, List bottoms) { MakeAppCodePub.ProcessSet(ver.id); string AppPackage = project.packageName; //包名 string AppIcon = project.appIcon; //应用桌面图标 string AppName = project.appName; //应用名称 string AppStartBg = project.appStartBg; //启动图 string AppStartListPhoto = project.appStartListPhoto; //启动介绍轮播图 string ApiHost = project.apiHost; //API主机头 string ApiKind = project.appKind; //APP分类 string AppStatic = ver.staticFile; //APP静态资源 string InitPage = project.initPage; //APP首次加载界面 //复制文件 string sourceDir = Function.getPath("/AppTemplate/ios/omnipotent/"); //模版目录 string destinationDir = Function.getPath("applecode/" + project.id + "/omnipotent/"); //生成目录 CopyFolder(sourceDir, destinationDir); MakeAppCodePub.ProcessSet(ver.id); string sourceBaseDir = Function.getPath("/AppTemplate/ios/omega-ios-framework/OmegaBase/"); //模版目录 string destinationBaseDir = Function.getPath("applecode/" + project.id + "/OmegaBase/"); //生成目录 CopyFolder(sourceBaseDir, destinationBaseDir); //替换包名 ReplaceAppPackage(destinationDir, AppPackage); ReplaceAppPackage(destinationBaseDir, AppPackage); MakeAppCodePub.ProcessSet(ver.id); //替换项目索引文件 string projectIndexPath = destinationDir + "omnipotent.xcodeproj/"; string projectIndexContent = Function.ReadInstanceByFull(projectIndexPath + "project.pbxproj"); Match projectIndexContentRegex = Regex.Match(projectIndexContent, "attributesByRelativePath = {[\\s\\S]*?};"); if (projectIndexContentRegex.Success) { string content = projectIndexContentRegex.Value; content = content.Replace("};", " /* 自定义模块 */\n };"); projectIndexContent = projectIndexContent.Replace(projectIndexContentRegex.Value, content); } projectIndexContentRegex = Regex.Match(projectIndexContent, "membershipExceptions = ([\\s\\S]*?);"); if (projectIndexContentRegex.Success) { string content = projectIndexContentRegex.Value; content = content.Replace(");", " /* 自定义模块名称 */\n );"); projectIndexContent = projectIndexContent.Replace(projectIndexContentRegex.Value, content); } string customFrameworksIndex = ""; string customFrameworksIndexName = ""; // string startString = "/* Begin PBXFileReference section */"; // string endString = "/* End PBXFileReference section */"; // int startIndex = projectIndexContent.IndexOf(startString); // int length = projectIndexContent.IndexOf(endString) + endString.Length - startIndex; // string projectIndexList = projectIndexContent.Substring(startIndex, length); // List fileIndexSources = projectIndexList.Replace(startString + "\n", "").Replace("\n" + endString, "").Replace("\t", "").Split('\n').ToList(); List fileIndexs = new List(); // string projectIndexReplace = startString + "\n"; List fileIndexFiles = new List(); //方法代码 string webCodePath = destinationBaseDir + "OmegaBase/Conroller/"; string webCodeContent = Function.ReadInstanceByFull(webCodePath + "LocalWebViewController.swift"); webCodeContent += "\n\n//模块方法代码"; webCodeContent = Function.ReplaceFirst(webCodeContent, "else if message.name == \"", "//模块调用代码 else if message.name == \""); string invokeCodeList = ""; string webCodeList = ""; //权限代码 string rightCodePath = destinationDir + "omnipotent/"; string rightCodeContent = Function.ReadInstanceByFull(rightCodePath + "Info.plist"); string rightCodeList = ""; string queriesSchemes = ""; string urlTypes = ""; //AppDelegate代码 string appDelegateCodePath = destinationDir + "omnipotent/"; string appDelegateCodeContent = Function.ReadInstanceByFull(appDelegateCodePath + "AppDelegate.swift"); appDelegateCodeContent += "\n\n//AppDelegate委托代码"; var importIndex = appDelegateCodeContent.LastIndexOf("import"); var importTagIndex = appDelegateCodeContent.Substring(importIndex).IndexOf("\n") + importIndex; appDelegateCodeContent = appDelegateCodeContent.Substring(0, importTagIndex) + "\n//AppDelegate引用" + appDelegateCodeContent.Substring(importTagIndex + 1); appDelegateCodeContent = Function.ReplaceFirst(appDelegateCodeContent, "{", "//AppDelegate继承代码{"); appDelegateCodeContent = appDelegateCodeContent.Replace("DispatchQueue.global().async {", "//AppDelegate启动代码\nDispatchQueue.global().async {\n //AppDelegate异步启动代码"); string appDelegateCodeList = ""; string appDelegateLaunchCodeList = ""; string appDelegateLaunchAsyncCodeList = ""; string appDelegateFunctionCodeList = ""; string appDelegateAddList = ""; MakeAppCodePub.ProcessSet(ver.id); //替换基础信息 projectIndexContent = Regex.Replace(projectIndexContent, "INFOPLIST_KEY_CFBundleDisplayName = \".*?\";", "INFOPLIST_KEY_CFBundleDisplayName = \"" + AppName + "\";"); projectIndexContent = Regex.Replace(projectIndexContent, "PRODUCT_BUNDLE_IDENTIFIER = .*?;", "PRODUCT_BUNDLE_IDENTIFIER = " + AppPackage + ";"); string apiSet = Function.ReadInstanceByFull(destinationDir + "omnipotent/AppConfiguration.ini"); string AppVersion = ver.versionName; projectIndexContent = Regex.Replace(projectIndexContent, "MARKETING_VERSION = .*?;", "MARKETING_VERSION = " + AppVersion +";"); apiSet = Regex.Replace(apiSet, "kind\":\".*?\"", "kind\":\"" + ApiKind + "/" + AppVersion + "\""); apiSet = Regex.Replace(apiSet, "serverUrls\":\".*?\"", "serverUrls\":\"" + ApiHost + "\""); //读取项目所有关联模块 List moduleIds = modules.Select(m => m.moduleId).ToList(); //读取模块配置参数 Dictionary paramDic = paramList.ToDictionary(m => m.paramName + "_" + m.moduleId, m => m.paramValue); foreach(AppProjectModule module in modules) { AppModule smodule = smodules.FirstOrDefault(m => m.id == module.moduleId); if(smodule != null) { List files = fileList.Where(m => m.moduleId == module.moduleId && m.appType == "ios").ToList(); foreach(AppModuleFile file in files) { string SourceFilePath = file.sourcePath; string ToPath = file.makePath; if(ToPath.EndsWith(".framework.zip")) fileIndexFiles.Add(ToPath.Substring(ToPath.LastIndexOf("/") + 1)); if(ToPath.EndsWith(".framework.zip")) { // string fileName = ToPath.Substring(ToPath.LastIndexOf("/") + 1); // CopyFolder(Function.getPath("/temp/Template/IOS/module/" + fileName + "/"), destinationDir + "omnipotent/customFrameworks/" + fileName + "/"); Function.DownloadNetFile(App.OptionsSetting.OssConfigs.Host + "/AppModule/ios" + SourceFilePath, destinationDir + "omnipotent/" + SourceFilePath); ZipFile.ExtractToDirectory(destinationDir + "omnipotent/" + SourceFilePath, destinationDir + ToPath.Replace(".zip", ""), true); File.Delete(destinationDir + "omnipotent/" + SourceFilePath); } if(module.moduleId == 1) { if(ToPath.EndsWith(".entitlements")) { // string fileName = ToPath.Substring(ToPath.LastIndexOf("/") + 1); // File.Copy(Function.getPath("/temp/Template/IOS/module/" + fileName), destinationDir + "omnipotent/" + fileName, true); Function.DownloadNetFile(App.OptionsSetting.OssConfigs.Host + "/AppModule/ios" + SourceFilePath, destinationDir + ToPath); } //解压阿里云推送配置文件 if (paramDic.ContainsKey("AliyunPList")) { string pListPath = Function.getPath(paramDic["AliyunPList_" + module.moduleId]); string toPListPath = destinationDir + "omnipotent/"; ZipFile.ExtractToDirectory(pListPath, toPListPath, true); } } } AppModuleIosCode code = codes.FirstOrDefault(m => m.moduleId == module.moduleId) ?? new AppModuleIosCode(); string InvokeCode = Function.CheckNull(code.invokeCode); string WebCode = Function.CheckNull(code.webCode); string SystemFramework = Function.CheckNull(code.systemFramework); string SystemLib = Function.CheckNull(code.systemLib); string RightCode = Function.CheckNull(code.rightCode); string ProjectIndexCode = Function.CheckNull(code.projectIndexCode); string AppDelegate = Function.CheckNull(code.appDelegate); string AppDelegateLaunchCode = Function.CheckNull(code.appDelegateLaunchCode); string AppDelegateLaunchAsyncCode = Function.CheckNull(code.appDelegateLaunchAsyncCode); string AppDelegateCode = Function.CheckNull(code.appDelegateCode); string EntitlementsCode = Function.CheckNull(code.entitlementsCode); string AppDelegateAdd = Function.CheckNull(code.appDelegateAdd); // if(module.moduleId == 10) // { // RightCode = RightCode.Replace("微信ID", "" + paramDic["WeChatAppId"] + ""); // RightCode = RightCode.Replace("微信ID", paramDic["WeChatAppId"]); // AppDelegateLaunchCode = AppDelegateLaunchCode.Replace("微信ID", paramDic["WeChatAppId"]); // } // if(module.moduleId == 11) // { // RightCode = RightCode.Replace("支付宝ID", "ap" + paramDic["AlipayAppId"] + ""); // RightCode = RightCode.Replace("支付宝ID", "ap" + paramDic["AlipayAppId"]); // AppDelegateLaunchCode = AppDelegateLaunchCode.Replace("支付宝ID", paramDic["AlipayAppId"]); // } if(RightCode.Contains("${")) { MatchCollection matches = Regex.Matches(RightCode, "\\$\\{.*?\\}"); foreach(Match match in matches) { string paramName = match.Value.Replace("${", "").Replace("}", ""); if(paramDic.ContainsKey(paramName + "_" + module.moduleId)) RightCode = RightCode.Replace(match.Value, paramDic[paramName + "_" + module.moduleId]); } } if(AppDelegateLaunchCode.Contains("${")) { MatchCollection matches = Regex.Matches(AppDelegateLaunchCode, "\\$\\{.*?\\}"); foreach(Match match in matches) { string paramName = match.Value.Replace("${", "").Replace("}", ""); if(paramDic.ContainsKey(paramName + "_" + module.moduleId)) AppDelegateLaunchCode = AppDelegateLaunchCode.Replace(match.Value, paramDic[paramName + "_" + module.moduleId]); } } if(AppDelegateLaunchAsyncCode.Contains("${")) { MatchCollection matches = Regex.Matches(AppDelegateLaunchAsyncCode, "\\$\\{.*?\\}"); foreach(Match match in matches) { string paramName = match.Value.Replace("${", "").Replace("}", ""); if(paramDic.ContainsKey(paramName + "_" + module.moduleId)) AppDelegateLaunchAsyncCode = AppDelegateLaunchAsyncCode.Replace(match.Value, paramDic[paramName + "_" + module.moduleId]); } } //项目索引信息 if(!string.IsNullOrEmpty(ProjectIndexCode)) { fileIndexs.Add(ProjectIndexCode); } //模块方法代码 if(!string.IsNullOrEmpty(WebCode)) { webCodeList += "\n\n" + WebCode; } //模块调用代码 if(!string.IsNullOrEmpty(InvokeCode)) { invokeCodeList += InvokeCode; } //权限代码 if(!string.IsNullOrEmpty(RightCode) && !rightCodeContent.Contains(RightCode)) { if(RightCode.StartsWith("{") && RightCode.EndsWith("}")) { Dictionary dic = Newtonsoft.Json.JsonConvert.DeserializeObject>(RightCode); foreach(string key in dic.Keys) { urlTypes += " \n"; urlTypes += " CFBundleTypeRole\n"; urlTypes += " Editor\n"; urlTypes += " CFBundleURLName\n"; urlTypes += " " + key + "\n"; urlTypes += " CFBundleURLSchemes\n"; urlTypes += " \n"; urlTypes += " " + dic[key] + "\n"; urlTypes += " \n"; urlTypes += " \n"; queriesSchemes += " " + key + "\n"; } } else { rightCodeList += "\n" + RightCode; } } //AppDelegate代码 if(!string.IsNullOrEmpty(AppDelegate)) { string[] AppDelegates = AppDelegate.Split('\n'); foreach(string sub in AppDelegates) { if(!appDelegateCodeList.Contains(sub.Trim())) appDelegateCodeList += sub + "\n"; } } if(!string.IsNullOrEmpty(AppDelegateLaunchCode)) { string[] AppDelegates = AppDelegateLaunchCode.Split('\n'); foreach(string sub in AppDelegates) { if(!appDelegateLaunchCodeList.Contains(sub.Trim())) appDelegateLaunchCodeList += sub + "\n"; } } if(!string.IsNullOrEmpty(AppDelegateLaunchAsyncCode)) { string[] AppDelegates = AppDelegateLaunchAsyncCode.Split('\n'); foreach(string sub in AppDelegates) { if(!appDelegateLaunchAsyncCodeList.Contains(sub.Trim())) appDelegateLaunchAsyncCodeList += sub + "\n"; } } if(!string.IsNullOrEmpty(AppDelegateCode)) { appDelegateFunctionCodeList += "\n\n" + AppDelegateCode; } if(!string.IsNullOrEmpty(AppDelegateAdd)) { appDelegateAddList += AppDelegateAdd; } } } //遍历模块文件,删除不包含的文件 // string[] dirList = Directory.GetDirectories(destinationDir + "omnipotent/modules/", "*.*", SearchOption.TopDirectoryOnly); // foreach (string dir in dirList) // { // string fileName = dir.Substring(dir.LastIndexOf("/") + 1); // if(!fileIndexFiles.Contains(fileName)) // Directory.Delete(dir, true); // } //添加模块文件,引用模块 foreach(string fileIndexFile in fileIndexFiles) { if(fileIndexFile.StartsWith("Omega")) { customFrameworksIndex += "\n\t\t\t\t" + fileIndexFile + " = (\n" + "\t\t\t\t\tCodeSignOnCopy,\n" + "\t\t\t\t\tRemoveHeadersOnCopy,\n" + "\t\t\t\t);"; customFrameworksIndexName += "\n\t\t\t\t" + fileIndexFile + ","; } } //权限CFBundleURLTypes if(!string.IsNullOrEmpty(urlTypes)) { rightCodeList += "\n CFBundleURLTypes\n"; rightCodeList += " \n"; rightCodeList += urlTypes; rightCodeList += " "; } //权限LSApplicationQueriesSchemes if(!string.IsNullOrEmpty(queriesSchemes)) { rightCodeList += "\n LSApplicationQueriesSchemes\n"; rightCodeList += " \n"; rightCodeList += queriesSchemes; rightCodeList += " "; } MakeAppCodePub.ProcessSet(ver.id); //替换项目索引信息 // foreach(string fileIndexCode in fileIndexSources) // { // if(!fileIndexCode.Contains("path = Omega")) // { // projectIndexReplace += "\t\t" + fileIndexCode + "\n"; // } // } // foreach(string fileIndexCode in fileIndexs) // { // projectIndexReplace += "\t\t" + fileIndexCode + "\n"; // } // projectIndexReplace += "\t\t449494BB2DA4B21400486054 /* OmegaBase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = OmegaBase.framework; sourceTree = \"\"; };\n"; // projectIndexReplace += endString; // projectIndexContent = projectIndexContent.Replace(projectIndexList, projectIndexReplace); projectIndexContent = projectIndexContent.Replace("/* 自定义模块 */", customFrameworksIndex); projectIndexContent = projectIndexContent.Replace("/* 自定义模块名称 */", customFrameworksIndexName); webCodeContent = webCodeContent.Replace("//模块调用代码", invokeCodeList); webCodeContent = webCodeContent.Replace("//模块方法代码", webCodeList); appDelegateCodeContent = appDelegateCodeContent.Replace("//AppDelegate引用", appDelegateCodeList); appDelegateCodeContent = appDelegateCodeContent.Replace("//AppDelegate继承代码", appDelegateAddList); appDelegateCodeContent = appDelegateCodeContent.Replace("//AppDelegate委托代码", appDelegateFunctionCodeList); appDelegateCodeContent = appDelegateCodeContent.Replace("//AppDelegate启动代码", appDelegateLaunchCodeList); appDelegateCodeContent = appDelegateCodeContent.Replace("//AppDelegate异步启动代码", appDelegateLaunchAsyncCodeList); Function.WritePageFullPath(projectIndexPath, "project.pbxproj", projectIndexContent); Function.WritePageFullPath(destinationDir + "omnipotent/", "AppConfiguration.ini", apiSet); Function.WritePageFullPath(webCodePath, "LocalWebViewController.swift", webCodeContent); Function.WritePageFullPath(appDelegateCodePath, "AppDelegate.swift", appDelegateCodeContent); MakeAppCodePub.ProcessSet(ver.id); //权限 rightCodeContent = rightCodeContent.Replace("\n", rightCodeList + "\n"); rightCodeContent = rightCodeContent.Replace("user-login", "" + InitPage + ""); Function.WritePageFullPath(rightCodePath, "Info.plist", rightCodeContent); string toPath = destinationDir + "omnipotent/sources/"; //底部导航图标下载 foreach(var bottom in bottoms) { if(!string.IsNullOrEmpty(bottom.selectIcon)) { Function.DownloadNetFile(App.OptionsSetting.OssConfigs.Host + bottom.selectIcon, toPath + "static/bottom/" + bottom.selectIcon.Substring(bottom.selectIcon.LastIndexOf("/") + 1)); } if(!string.IsNullOrEmpty(bottom.normalIcon)) { Function.DownloadNetFile(App.OptionsSetting.OssConfigs.Host + bottom.normalIcon, toPath + "static/bottom/" + bottom.normalIcon.Substring(bottom.normalIcon.LastIndexOf("/") + 1)); } if(!string.IsNullOrEmpty(bottom.pagDefaultIcon)) { Function.DownloadNetFile(App.OptionsSetting.OssConfigs.Host + bottom.pagDefaultIcon, toPath + "static/bottom/" + bottom.pagDefaultIcon.Substring(bottom.pagDefaultIcon.LastIndexOf("/") + 1)); } if(!string.IsNullOrEmpty(bottom.pagLocalPath)) { Function.DownloadNetFile(App.OptionsSetting.OssConfigs.Host + bottom.pagLocalPath, toPath + "static/bottom/" + bottom.pagLocalPath.Substring(bottom.pagLocalPath.LastIndexOf("/") + 1)); } } MakeAppCodePub.ProcessSet(ver.id); //页面图标下载 foreach(var page in pages) { if(page.leftBtn != null) { foreach(var btn in page.leftBtn) { if(!string.IsNullOrEmpty(btn.btnIcon)) { Function.DownloadNetFile(App.OptionsSetting.OssConfigs.Host + btn.btnIcon, toPath + "static/page/" + btn.btnIcon.Substring(btn.btnIcon.LastIndexOf("/") + 1)); } } } if (page.rightBtn != null) { foreach(var btn in page.rightBtn) { if(!string.IsNullOrEmpty(btn.btnIcon)) { Function.DownloadNetFile(App.OptionsSetting.OssConfigs.Host + btn.btnIcon, toPath + "static/page/" + btn.btnIcon.Substring(btn.btnIcon.LastIndexOf("/") + 1)); } } } } MakeAppCodePub.ProcessSet(ver.id); //解压static静态资源 // string staticFilePath = Function.getPath(AppStatic); Function.DownloadNetFile(App.OptionsSetting.OssConfigs.Host + AppStatic, toPath + "static.zip"); ZipFile.ExtractToDirectory(toPath + "static.zip", toPath, true); File.Delete(toPath + "static.zip"); //生成app加密的配置文件 Dictionary appFileDic = MakeAppCodePub.getAppFile(ver, pages, bottoms, toPath); if(appFileDic.ContainsKey("AppInfoList")) Function.WritePageFullPath(destinationDir + "omnipotent/", "AppInfoList.ini", appFileDic["AppInfoList"]); if(appFileDic.ContainsKey("SystemSet")) Function.WritePageFullPath(destinationDir + "omnipotent/", "SystemSet.ini", appFileDic["SystemSet"]); if(appFileDic.ContainsKey("PageInfoList")) Function.WritePageFullPath(destinationDir + "omnipotent/", "PageInfoList.ini", appFileDic["PageInfoList"]); if(appFileDic.ContainsKey("GotoPages")) Function.WritePageFullPath(destinationDir + "omnipotent/", "GotoPages.ini", appFileDic["GotoPages"]); if(appFileDic.ContainsKey("LibFile")) Function.WritePageFullPath(destinationDir + "omnipotent/", "LibFile.ini", appFileDic["LibFile"]); //删除html文件 List htmlFiles = FileHelper.GetSystemFilesFromFullPath(toPath); foreach(string file in htmlFiles) { if(file.EndsWith(".html")) { File.Delete(file); } } MakeAppCodePub.ProcessSet(ver.id); //解压icon图标 // string iconPath = Function.getPath(AppIcon); string toIconPath = destinationDir + "omnipotent/Assets.xcassets/"; // string downloadPath = Path.GetTempPath() + "ios/" + project.id + "/"; string savePath = toPath + AppIcon.Substring(AppIcon.LastIndexOf("/") + 1); Function.DownloadNetFile(App.OptionsSetting.OssConfigs.Host + AppIcon, savePath); ZipFile.ExtractToDirectory(savePath, toIconPath, true); File.Delete(savePath); //解压启动图 // string startBgPath = Function.getPath(AppStartBg); string toStartBgPath = destinationDir + "omnipotent/Assets.xcassets/"; savePath = toPath + AppStartBg.Substring(AppStartBg.LastIndexOf("/") + 1); Function.DownloadNetFile(App.OptionsSetting.OssConfigs.Host + AppStartBg, savePath); ZipFile.ExtractToDirectory(savePath, toStartBgPath, true); File.Delete(savePath); ZipFile.CreateFromDirectory(Function.getPath("applecode/" + project.id + "/"), Function.getPath("applecode/" + fileName)); OssHelper.Instance.Upload(Function.getPath("applecode/" + fileName)); File.Delete(Function.getPath("applecode/" + fileName)); Directory.Delete(Function.getPath("applecode/" + project.id + "/"), true); MakeAppCodePub.ProcessSet(ver.id); } public static void CopyFolder(string sourceDir, string destinationDir, bool move = false) { // 如果目标文件夹不存在,则创建 if (!Directory.Exists(destinationDir)) { Directory.CreateDirectory(destinationDir); } // 获取源文件夹中的所有文件并复制到目标文件夹 foreach (string file in Directory.GetFiles(sourceDir, "*.*", SearchOption.AllDirectories)) { string destFile = file.Replace(sourceDir, destinationDir); string destDir = Path.GetDirectoryName(destFile); // 如果目标文件夹不存在,则创建 if (!Directory.Exists(destDir)) { Directory.CreateDirectory(destDir); } if(move) { File.Move(file, destFile, true); // 如果目标文件已存在,则覆盖 } else { File.Copy(file, destFile, true); // 如果目标文件已存在,则覆盖 } } // 获取源文件夹中的所有子文件夹并递归复制 foreach (string dir in Directory.GetDirectories(sourceDir, "*.*", SearchOption.AllDirectories)) { string destDir = dir.Replace(sourceDir, destinationDir); if (!Directory.Exists(destDir)) { Directory.CreateDirectory(destDir); } } } #endregion #region 替换包名 public static void ReplaceAppPackage(string destinationDir, string AppPackage) { string[] fileList = Directory.GetFiles(destinationDir, "*.*", SearchOption.AllDirectories); foreach (string file in fileList) { bool op = true; if(file.Contains(".framework") || file.Contains("Assets") || file.Contains("sources")) { op = false; } if(op) { string content = Function.ReadInstanceByFull(file); content = content.Replace("com.omega.omegamainbase", AppPackage); Function.WritePageFullPath(file.Substring(0, file.LastIndexOf("/")), file.Substring(file.LastIndexOf("/")), content); } } } #endregion } }