<template>
	<div>
		<el-container style="height: 100vh;">
			<!-- #333744 -->
			<el-aside width="180px" style="user-select: none; border-right: 1px solid #fafafa; background-color: #333744; overflow-x: hidden;">
				<p class="soft-name" style="-webkit-app-region: drag; color: #fff;">
					<img src="../assets/image/icon.png" class="soft-icon" />
					<span style="letter-spacing: 1px;">{{productName}}</span>
				</p>
				
				<el-menu :default-openeds="['a']" :default-active="menuIndex" @select="setMenuIndex" active-text-color="#409EFF" background-color="#333744" text-color="#fff" style="margin-top: 10px;">
					<el-submenu index="a">
						<template slot="title"><img src="../assets/image/m-download.png" class="m-image"/>图片下载</template>
						<el-menu-item index="1">
							<img src="../assets/image/m-douyin.png" class="m-image"/><span slot="title">抖音</span>
						</el-menu-item>
						<el-menu-item index="2">
							<img src="../assets/image/m-kuaishou.png" class="m-image"/><span slot="title">快手</span>
						</el-menu-item>
						<el-menu-item index="3">
							<img src="../assets/image/m-weibo.png" class="m-image"/><span slot="title">微博</span>
						</el-menu-item>
						<el-menu-item index="10">
							<img src="../assets/image/m-chrome.png" class="m-image"/><span slot="title">其他(Beta)</span>
						</el-menu-item>
					</el-submenu>
				</el-menu>
			</el-aside>
			
			<el-container>
				<el-header height="45px" style="background-color: #fafafa; padding: 0 10px;">
					<soft-header ref="headerRef" @update-soft="updateSoft()" @export-file="exportFile" @login-url="loginUrl" @clear-cache="clearCache"></soft-header>
				</el-header>
								
				<el-main ref="el-main" style="background-color: #fafafa;">
					<template>
						<div class="content-top">
							<div>
								<el-button-group>
									<el-button type="primary" size="mini" icon="el-icon-circle-plus-outline"
										@click="addVisible = true;">添加链接</el-button>
									<el-button type="primary" size="mini" icon="el-icon-upload"
										@click="pickLink()">导入链接</el-button>
									<el-button type="primary" size="mini" icon="el-icon-delete"
										@click="clearList()">清空链接</el-button>
								</el-button-group>
								
								<el-link type="info" style="margin-left: 20px; vertical-align:baseline; font-size: 12px;" @click="downloadExample()">导入模板下载<i class="el-icon-download"></i></el-link>
							</div>
							
							<el-row type="flex" style="align-items: center;">
								<div class="set-item">
									<span class="set-title">保存目录：</span>
									<el-input :title="downloadDir" ref="upload-input" size="mini" @focus="pickPath" placeholder="请选择输出目录" v-model="downloadDir" readonly style="width:200px;" prefix-icon="el-icon-folder"></el-input>
									<el-popover placement="bottom" popper-class="popper-open" trigger="hover" content="打开保存目录">
										<i class="el-icon-folder-opened" slot="reference" style="padding-left: 5px; cursor: pointer; font-size: 22px; vertical-align: middle;" @click="openFolder()"></i>
									</el-popover>
								</div>
								
								<el-button type="danger" @click="exportFile()" :loading="loading">开始下载</el-button>
							</el-row>
						</div>
						
						<div style="padding: 20px 20px 0 20px; height: calc(100% - 62px);">
							<el-row type="flex" justify="space-between">
								<div>
									<h3 style="display: inline-block;">
										<span v-if="menuIndex == '1'">抖音 - </span>
										<span v-if="menuIndex == '2'">快手 - </span>
										<span v-if="menuIndex == '3'">微博 - </span>
										<span v-if="menuIndex == '10'">网页 - </span>
										视频下载
									</h3>
									<!-- <el-popover placement="bottom" popper-class="popper-open" trigger="hover" content="下载类型至少选一个,评论图默认只下载商品首页展示的评论内容">
										<i class="el-icon-info" slot="reference" style="margin-right: 10px; color: #F56C6C;"></i>
									</el-popover> -->
									<el-link v-if="menuIndex != '10'" :underline="false" type="danger" style="text-align: center; font-size: 12px;">
										不支持win7及以下系统
									</el-link>
									<el-link v-if="menuIndex == '10'" :underline="false" type="danger" style="text-align: center; font-size: 12px;">
										非会员功能，仅提供测试试用
									</el-link>
									
								</div>
							</el-row>
						
							<div class="table-scroll" style="padding-top: 30px; height: calc(100% - 31px);">
								<!-- 1、 -->
								<vxe-table ref="xTable" show-overflow class="img-table" max-height="100%" empty-text="没有更多数据了！" :loading="tabLoading" :row-config="{isHover: true}" 
									:loading-config="{icon: 'vxe-icon-indicator roll', text: '列表加载中...'}" :data="this[listStr+'List']" :scroll-y="{enabled: true}">
									<vxe-column type="seq" width="60"></vxe-column>
									<vxe-column field="title" title="目录名称" width="200">
										<template #default="{ row, rowIndex }">
											<span v-if="row.title">{{row.title}}</span>
											<el-tag size="mini" v-else>默认使用网页标题</el-tag>
										</template>
									</vxe-column>
									<vxe-column field="url" title="网页链接"></vxe-column>
									<vxe-column field="status" title="下载状态" width="200">
										<template #default="{ row }">
											<template v-if="row.status == '1'">
												<i class="el-icon-info" style="font-size: 16px; color: #999;"></i>
												<span>待操作</span>
											</template>
											<template v-if="row.status == '2'">
												<i class="el-icon-loading" style="font-size: 16px; color: #999;"></i>
												<span>任务处理中...</span>
											</template>
											<template v-if="row.status == '3'">
												<i class="el-icon-loading" style="font-size: 16px; color: #999;"></i>
												<span>视频下载中..<span v-if="row.num > 0">第{{row.num}}个</span></span>
											</template>
											<template v-if="row.status == '4'">
												<i class="el-icon-success" style="font-size: 16px; color: #19be6b;"></i>
												<span>下载完成</span>
											</template>
											<template v-if="row.status == '5'">
												<i class="el-icon-error" style="font-size: 16px; color: #ed4014;"></i>
												<span>网络异常,请重试!</span>
											</template>
											<template v-if="row.status == '6'">
												<i class="el-icon-error" style="font-size: 16px; color: #ed4014;"></i>
												<span>验证码拦截,请手动验证!</span>
											</template>
										</template>
									</vxe-column>
									<vxe-column title="操作" width="80">
										<template #default="{ row, rowIndex }">
											<i class="el-icon-delete cur-pointer" style="font-size: 20px;" @click="delFile(rowIndex)"></i>
										</template>
									</vxe-column>
								</vxe-table>
							</div>
						</div>
			
					</template>
								
					<el-dialog title="添加链接" :visible.sync="addVisible" width="500px" :close-on-click-modal="false" :close-on-press-escape="false" :show-close="false">
						<div>
							<el-form label-position="right" label-width="80px" :rules="rules" :model="formData" ref="formData">
								<el-form-item label="目录名称" prop="title">
									<el-input v-model="formData.title" placeholder="为空则默认使用网页标题前50个字符"></el-input>
								</el-form-item>
								<el-form-item label="网页链接" prop="url">
									<el-input type="textarea" :rows="10" v-if="menuIndex < 10" :placeholder="'请输入网址链接(例:' + exampleUrl[menuIndex-1] + ')'" v-model="formData.url"></el-input>
									<el-input type="textarea" :rows="10" v-else :placeholder="'请输入网址链接'" v-model="formData.url"></el-input>
								</el-form-item>
							</el-form>
						</div>
						<span slot="footer" class="dialog-footer">
							<el-button @click="addVisible = false; $refs['formData'].resetFields();">取 消</el-button>
							<el-button type="primary" @click="onSubmit">确 定</el-button>
						</span>
					</el-dialog>
					
					<el-dialog title="提示" :visible.sync="loginVisible" width="400px" :close-on-click-modal="false" :close-on-press-escape="false">
						<div style="text-align: center; color: #999; font-size: 14px;">
							<template v-if="menuIndex == '1'">
								<p>阿里巴巴渠道建议登录后下载</p>
								<p class="visible-tips-style">目前检测还未登录阿里巴巴账号，未登录可能会导致图片下载不全</p>
							</template>
							<template v-else-if="menuIndex == '2'">
								<p>京东渠道需要登录后才能下载</p>
								<p class="visible-tips-style">目前检测还未登录京东账号，需立即登录</p>
							</template>
							<template v-else-if="menuIndex == '5'">
								<p>小红书渠道需要登录后才能下载</p>
								<p class="visible-tips-style">目前检测还未登录小红书账号，需立即登录</p>
							</template>
							<template v-else>
								<p>天猫/淘宝渠道需要登录后才能下载</p>
								<p class="visible-tips-style">目前检测还未登录天猫/淘宝账号，需立即登录</p>
							</template>
							
						</div>
						<div slot="footer" class="dialog-footer-center">
							<el-button v-if="menuIndex == '2'" @click="loginVisible = false; loginUrl('https://passport.jd.com/new/login.aspx')">点击登录京东账号</el-button>
							<template v-else-if="menuIndex == '1'">
								<el-button @click="loginVisible = false; loginUrl('https://www.1688.com')">点击登录阿里巴巴账号</el-button>
								<el-button type="primary" @click="loginVisible = false; skipLogin = true; exportFile();">继续下载</el-button>
							</template>
							<el-button v-else-if="menuIndex == '5'" @click="loginVisible = false; loginUrl('https://www.xiaohongshu.com')">点击登录小红书账号</el-button>
							<el-button v-else @click="loginVisible = false; loginUrl('https://login.taobao.com')">点击登录天猫/淘宝账号</el-button>
						</div>
					</el-dialog>
					
					<!-- 非会员转换提示框 -->
					<el-dialog title="非会员提示" :visible.sync="tipsModal" width="400px">
						<div class="member-model">
							<div class="tips-flex">
								<i class="el-icon-s-opportunity"></i>
								<p class="m-title">{{tipsDesc}}</p>
							</div>
							<div class="member-btn">
								<el-button size="small" round type="primary" @click="openVip()">开通会员</el-button>
							</div>
						</div>
					</el-dialog>
			
				</el-main>
				
				<el-footer height="48px">
					<!-- 更新 -->
					<soft-update ref="updateRef" :showDowload="dowloadModel" :dowloadFinish="finishModel"></soft-update>
				</el-footer>
			</el-container>
		</el-container>
	</div>
</template>

<script>
	import os from 'os'
	import fs from 'fs'
	import request from 'request'
	import path from 'path';
	import xlsx from 'node-xlsx';
	import softUpdate from './update.vue';
	import softHeader from './header.vue';
	import electronApi from '@/utils/electronApi';
	import pjson from '/package.json'
	// import puppeteer from 'puppeteer'
	import puppeteer from 'puppeteer-extra'
	const StealthPlugin = require('puppeteer-extra-plugin-stealth');
	const listNameArr = ['douyin','kuaishou','weibo','','','','','', '' ,'common'];
	
	let separator = '';
	if (os.platform == 'linux') {
		separator = '/'
	} else {
		separator = '\\'
	}
	
	// let chromePath = process.cwd() + '\\resources\\app\\node_modules\\puppeteer\\.local-chromium\\win64-1045629\\chrome-win\\chrome.exe';
	// if (process.env.NODE_ENV == 'development') {
	//     chromePath = process.cwd() + '\\node_modules\\puppeteer\\.local-chromium\\win64-1045629\\chrome-win\\chrome.exe';
	// }
	export default {
		name: 'landing-page',
		components: {
			softUpdate,
			softHeader
		},
		data() {
			return {
				tipsModal: false,
				tipsDesc: "非VIP用户不能下载视频，如需完整功能请开通VIP会员。",
				settingArr: ['mainImg'],
				loginVisible: false,
				addVisible: false,
				formData: {
					title: '',
					url: ''
				},
				rules:{ //   
					title: [
						{ min: 0, max: 50, message: '不能超过 50 个字符', trigger: 'blur' },  
						{ pattern: /^[^\\/:*?"<>|]*$/, message: '标题中不能包含 \\ / : * ? " < > |', trigger: 'blur' } 
					],
					url: [
						{ required: true, message: '请输入网页链接', trigger: 'blur' },
						{ pattern: /^(http|https):\/\/.+$/, message: '请输入正确的网址链接(http://或https://开头)', trigger: 'blur' } 
					],
				},
				tabLoading: false,
				douyinList: [],
				kuaishouList: [],
				weiboList: [],
				commonList: [],
				productName: pjson.softInfo.softName,
				imgUrl: this.$api.imgUrl,
				imgSrc: '',
				menuIndex: '1',
				settingData: {
					detailImg: true,
					skuImg: true,
					commentImg: false,
					video: false,
				},
				exampleUrl: ['https://www.douyin.com', 'https://www.kuaishou.com', 'https://www.weibo.com'],

				fileList: [],
				
				downloadDir: os.userInfo().homedir + separator + "Downloads",
				dowloadModel: false,
				finishModel: false,

				loading: false,
				checkLoading: false, //点击检测登录状态
				execLimit: 1,
				execNum: 3, // 限制5张
				
				/** 浏览器名称 **/
				videoBrowser: null,
				loginBrowser: null, // 登录用的浏览器实例
				skipLogin: false,
			};
		},
		computed: {
			listStr: function(){
				let index = Number(this.menuIndex) - 1;
				return listNameArr[index];
			}
		},
		async mounted() {
			this.$refs.updateRef.updateSoft(true);

			let homedir = os.userInfo().homedir;
			if (fs.existsSync(homedir + separator + "Desktop")) {
				this.downloadDir = homedir + separator + "Desktop"
			} else {
				this.downloadDir = homedir + separator + "Downloads"
			}
			
			if (!fs.existsSync(os.tmpdir() + separator + 'chrome-data-capture-video')) {
				fs.mkdirSync(os.tmpdir() + separator + 'chrome-data-capture-video');
			}

			// 打开浏览器
			const {
				shell
			} = require('electron');
			const links = document.querySelectorAll('a[href]');
			links.forEach(link => {
				link.addEventListener('click', e => {
					const url = link.getAttribute('href');
					e.preventDefault();
					shell.openExternal(url);
				});
			});
			
		},
		methods: {
			// 实时获取浏览器路径
			initPath(){
				let chromePath = puppeteer.executablePath().replace('win32-1', 'win64-1');
				return chromePath;
			},
			// 删除文件夹内容
			deleteAll(folderPath, flag) {
				if (fs.existsSync(folderPath)) {
					fs.readdirSync(folderPath).forEach((file, index) => {
						var curPath = path.join(folderPath, file);
						if (fs.lstatSync(curPath).isDirectory()) {
							this.deleteAll(curPath, true);
						} else {
							fs.unlinkSync(curPath);
						}
					});
					if(flag){
						fs.rmdirSync(folderPath);
					}
				}
			},
			checkAuthority(){
				let authority = this.$refs.headerRef.authority;
				this.$refs.imgRef.authority = authority;
			},
			setMenuIndex(index){
				this.menuIndex = index;
				if(index.indexOf('2-') > -1){
					let num = Number(index.split('-')[1]);
					this.$refs.imgRef.setMenuIndex(num);
				}
			},
			// 选择目录
			pickPath() {
				this.$refs['upload-input'].blur();
				electronApi.call('pickDir', []).then((path) => {
					if (path) {
						this.downloadDir = path;
					}
				});
			},
			// 打开自定义下载目录
			openFolder() {
				let path = this.downloadDir;
				if (fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName)) {
					path = this.downloadDir + separator + pjson.softInfo.softName;
				} else {
					fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName);
					path = this.downloadDir + separator + pjson.softInfo.softName;
				}
				electronApi.call('showItemInfolder', [path + '\\tty.tty'])
			},
			openVip() {
				this.$refs.headerRef.openVip();
			},
			updateSoft() {
				this.$refs.updateRef.updateSoft();
			},
			// 删除文件
			delFile(rowIndex){
				let index = Number(this.menuIndex) - 1;
				let type = listNameArr[index];
				
				this.$confirm('确认删除此行数据吗?', '提示', {
					confirmButtonText: '确定',
					cancelButtonText: '取消',
					type: 'warning'
				}).then(() => {
					this[type+'List'].splice(rowIndex, 1);
					if(this[type+'List'].length == 0) {
						this.clearList();
					}
				}).catch(() => {
						  
				});
			},
			// 清除列表
			clearList() {
				let index = Number(this.menuIndex) - 1;
				this[listNameArr[index]+'List'] = [];
			},
			// 提交表单
			onSubmit(){
				this.$refs['formData'].validate((valid) => {
					if (valid) {
						let info = {
							url: this.formData.url,
							title: this.formData.title,
							status: '1',
							num: 0,
							newPath: ''
						}
						let index = Number(this.menuIndex) - 1;
						this[listNameArr[index]+'List'].push(info);
						this.$refs['formData'].resetFields();
						this.addVisible = false;
					} else {
						return false;
					}
				});
			},
			async pickLink() { // 导入链接
				const spinLoad = this.$loading();
				await electronApi.call('pickFile', ['xlsx,xls', true]).then(async (path) => {
					spinLoad.close();
					if(path.length > 0){
						this.$notify({
							title: '提示',
							message: '导入成功',
							type: 'success'
						});
						let workSheetsFromBuffer = xlsx.parse(fs.readFileSync(path[0]));
						if(workSheetsFromBuffer && workSheetsFromBuffer.length > 0){
							let errMsg = "";
							workSheetsFromBuffer[0].data.map((item, index) => {
								if(item.length > 0){
									let ititle = '';
									if(item[0]){
										ititle = item[0].toString().trim();
									}
									
									if(item[0] == '目录名称' && item[1] == '网页链接'){
										return false;
									}

									if(this.containsAnyChar(ititle.toString(), ['\\', '/', ':', '*', '?', '"', '<', '>', '|'])){  //判断是否含有特殊字符
										errMsg += "第" + (index+1) + '行-名称不能包以下字符 \\ / : * ? " < > |';
										ititle = ititle.replace(/[\\|/|:|*|?|"|<|>||]/g, "");
									}
									if(item[1] == undefined){
										errMsg += "第" + (index+1) + "行格式有误</br>";
										item[1] = '';
									}else if(!/^(http|https):\/\/.+$/.exec(item[1])){
										errMsg += "第" + (index+1) + "行网址格式有误</br>";
									}else{
										let info = {
											url: item[1],
											title: ititle,
											status: '1',
											num: 0,
											newPath: ''
										}
										let key = Number(this.menuIndex) - 1;
										this[listNameArr[key]+'List'].push(info);
									}
								}
							});
							if(errMsg){
								this.$notify({
									title: '请检查文件以下问题',
									dangerouslyUseHTMLString: true,
									message: errMsg,
									type: 'warning'
								});
							}
						}else{
							this.$notify({
								title: '提示',
								message: '格式有误，请重新导入',
								type: 'warning'
							});
						}
					}
				});
			},
			settingGroup(name){
				let authority = this.$refs.headerRef.authority.isAuthority;
				let index = name.indexOf('video');
				if(index > -1 && !authority){ // 非会员选中下载视频选项-提示
					this.tipsModal = true;
					name.splice(index, 1);
				}
			},
			// 清除缓存的后续操作
			async clearCache(){
				this.jdStatus = 3;
				this.tbStatus = 3;
				this.redStatus = 3;
				this.alibabaStatus = 3;
				this.aliguojiStatus = 3;
				
				if(this.loginBrowser){
					await this.loginBrowser.close();
					this.loginBrowser = null;
				}
				
				if(this.videoBrowser){
					await this.videoBrowser.close();
					this.videoBrowser = null;
				}
			},
			
			// 去登录
			loginUrl(url){
				(async () => {
					try{
						if (!fs.existsSync(os.tmpdir() + separator + 'chrome-data-capture-video')) {
							fs.mkdirSync(os.tmpdir() + separator + 'chrome-data-capture-video');
						}
						let userDataDir = os.tmpdir() + separator + 'chrome-data-capture-video';
						puppeteer.use(StealthPlugin());
						this.loginBrowser = await puppeteer.launch({
							headless: false,
							executablePath: this.initPath(),
							args: ['--window-size=1280,800'],
							userDataDir: userDataDir, 
						});
						const page = await this.loginBrowser.newPage();
						await page.setViewport({ width: 1280, height: 800 });
						
						await page.evaluateOnNewDocument(() => {
						    const newProto = navigator.__proto__;
							delete newProto.webdriver;
							navigator.__proto__ = newProto;
						});
						await page.goto(url, {waitUntil : 'networkidle2'});
					}catch(e){
						this.showError(e);
					}
				})();
			},
			
			// 开始下载
			async exportFile(flag) {
				if(this.loginBrowser){
					await this.loginBrowser.close();
					this.loginBrowser = null;
				}
				let authority = this.$refs.headerRef.authority.isAuthority;
				if (!fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName)) {
					fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName);
				}
				
				let index = Number(this.menuIndex) - 1;
				let fileList = this[listNameArr[index]+'List'];
				
				if(fileList.length > 0){
					if (!authority && !flag) { // 非会员点击转换弹出提示框
						this.$refs.headerRef.memberModel = true;
						this.$refs.headerRef.isClick = true;
						return false;
					} else {
						this.$refs.headerRef.memberModel = false;
						this.loading = true;
						setTimeout(() => {
							this.loading = false;
						}, 60000);
					}
					
					if (!fs.existsSync(os.tmpdir() + separator + 'chrome-data-capture-video')) {
						fs.mkdirSync(os.tmpdir() + separator + 'chrome-data-capture-video');
					}
					
					
					let taskArr = [];
					let task = "";
					let userDataDir = os.tmpdir() + separator + 'chrome-data-capture-video';
					// 运行不同平台的浏览器
					puppeteer.use(StealthPlugin());
					this.videoBrowser = await puppeteer.launch({
						headless: false,
						executablePath: this.initPath(),
						userDataDir: userDataDir, 
						args: [
							'--start-maximized',
							'--no-sandbox',
							'--disable-setuid-sandbox',
							'--disable-blink-features=AutomationControlled',
						]
					});
					
					for(let i = 0; i < fileList.length; i++){
						let item = fileList[i];
						
						task = this.videoDownload(item, this.videoBrowser);
					
						if(task){
							taskArr.push(task);
						}
						
						if((i+1) % this.execLimit == 0){
							await Promise.all(taskArr).then(result => {
								taskArr = [];
							}).catch(err => {
								console.log('err'+i, err)
							})
						}
					}
					
					if(taskArr.length > 0){
						await Promise.all(taskArr).then(result => {
							taskArr = [];
						}).catch(err => {
							// 错误文件添加到服务中
							console.log('err',err)
						})
					}
					
					if(this.videoBrowser){
						this.videoBrowser.close();
						this.videoBrowser = null;
					}
					
					this.loading = false;
					// 打开文件夹
					if(fileList.length > 0){
						this.$message({message: '恭喜你，任务已完成！', type: 'success'});
						electronApi.call('showItemInfolder',[this.downloadDir + separator + pjson.softInfo.softName +'\\tty.tty'])
					}
				}
			},
			
			// 1 - 抖音视频下载
			async videoDownload(urlInfo, browser){
				let task = await new Promise((resolve,reject) =>{
					(async () => {
						try{
							let authority = this.$refs.headerRef.authority.isAuthority;
							urlInfo.status = '2';
							urlInfo.num = 0;
							const page = await browser.newPage();
							
							let responseVideo = [];
							page.on('response', async(response) => {
								// 检查响应的 MIME 类型是否以 'video/' 开头
								if (response.headers()['content-type'] && response.headers()['content-type'].startsWith('video/')) {
									if(responseVideo.indexOf(response.url()) < 0 && !response.url().startsWith('blob:https://')){
										responseVideo.push(response.url());
									}
								}
							});
							await page.goto(urlInfo.url, {waitUntil : 'networkidle2'});
							
							if(urlInfo.title){
								if (fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title)) {
									urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
								} else {
									fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title);
									urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + urlInfo.title;
								}
							}else{
								await this.getTitle(page, urlInfo); // 生成页面标题对应的文件夹
							}
							
							urlInfo.status = '3';
							console.log(responseVideo);
							//视频下载
							for(let j = 0; j < responseVideo.length; j++){
								let num = Number(j) + 1;
								let suffix = '.mp4';
								let outputPath = urlInfo.newPath + '\\视频' + num + suffix;
								await this.downloadImage(responseVideo[j], outputPath, urlInfo);
							}
							
							this.loading = false;
							urlInfo.status = '4';
							resolve(true);
							
						}catch(e){
							urlInfo.status = '5';
							reject(e);
							this.showError(e);
						}
					})();
				});
			},
			
			//
			downloadExample(){
				let url = 'https://www.xingyousoft.com/soft/XYCapture/example.xlsx';
				if (!fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName)) {
					fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName);
				}
				let path = this.downloadDir + separator + pjson.softInfo.softName + '\\链接模板下载.xlsx';
				this.downloadImage(url, path, 'example');
			},
			
			// 下载网址链接的图片
			async downloadImage(imageUrl, outputPath, urlInfo) {
				let _this = this;
				let received_bytes = 0;
				let total_bytes = 0;
				try {
					let req = request({
					    method: 'GET', uri: imageUrl, strictSSL: false
					});
					let out = fs.createWriteStream(outputPath);
					req.pipe(out);
					
					return new Promise((resolve, reject) => { 
						req.on('response', (data) => {
							total_bytes = parseInt(data.headers['content-length']);
							const status = data.statusCode;
							if (status < 200 || status >= 300) {
								//reject(false);
								this.$notify.error({
									title: '网络资源访问异常！- 1',
									message: imageUrl.slice(0,50)
								});
							}else if(isNaN(total_bytes)){
								//reject(false);
								this.$notify.error({
									title: '网络资源访问异常！- 2',
									message: imageUrl.slice(0,50)
								});
							}else{
								// console.log('下载中...')
							}
						});
									
						req.on('data', (chunk) => {
						    received_bytes += chunk.length;
						});
						
						req.on('end', ()=> {
							if(urlInfo != 'example'){
								urlInfo.num += 1;
							}else{
								this.$msgbox({
									title: '消息',
									message: '模板下载成功，保存位置：' + this.downloadDir + separator + pjson.softInfo.softName,
									showCancelButton: true,
									confirmButtonText: '去查看',
									cancelButtonText: '取消',
								}).then(action => {
									this.openFolder();
								}).catch(action => {
									
								});
							}
							//console.log('下载完成', outputPath)
							resolve(true);
						});
					});
			    } catch (error) {  
			        console.error(imageUrl, `Failed to download image: ${error.message}`);  
			        throw error;  
			    }  
			},
			
			// 获取页面标题 - 生成对应的文件夹
			async getTitle(page, urlInfo){
				// 已页面标题作为新建文件夹,保留前50个字
				let title = await page.title();
				if(title){
					title = title.substring(0, 50);
					if(this.containsAnyChar(title, ['\\', '/', ':', '*', '?', '"', '<', '>', '|'])){  //判断是否含有特殊字符
						title = title.replace(/[\\|/|:|*|?|"|<|>||]/g, "");
					}
					if (fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName + separator + title)) {
						urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + title;
					} else {
						fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName + separator + title);
						urlInfo.newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + title;
					}
				}
			},
			
			// 下载base64位的图片
			async downloadBaseImage(base64String, outputPath, urlInfo) {
				const buffer = Buffer.from(base64String, 'base64');
				const writeStream = fs.createWriteStream(outputPath);
				writeStream.write(buffer);  
				writeStream.end();
				writeStream.on('finish', () => {
					urlInfo.num += 1;
				});
				// 监听错误事件  
				writeStream.on('error', (err) => {  
					console.error('base64位写入文件时出错:', err);  
				});
			},
			
			// 错误提示
			showError(e){
				let str = '';
				if(e.toString().indexOf('ERR_NAME_NOT_RESOLVE') > -1){
					str = '无法解析该网址，请查看网址是否正确！-1';
				}else if(e.toString().indexOf('Cannot navigate to invalid URL') > -1){
					str = '无效的网址，请查看网址格式是否正确！-2';
				}else if(e.toString().indexOf('ERR_CONNECTION_TIMED_OUT') > -1){
					str = '链接请求超时，请查看网络状态！-3';
				}else if(e.toString().indexOf('TimeoutError') > -1){
					str = '链接请求超时，请查看网络状态！-4';
				}else if(e.toString().indexOf('operation not permitted') > -1){
					str = '权限受限，请以管理员权限运行软件！-5';
				}else if(e.toString().indexOf('browser has disconnected') > -1){
					str = '内置浏览器已关闭！-6';
				}else if(e.toString().indexOf('Failed to launch the browser') > -1){
					str = '请先关闭内置浏览器！-7';
				}else{
					str = e.toString();
					//console.log(e);
				}
				this.loading = false;
				this.$notify.error({
					title: '提示',
					message: str
				});
			},
			
			// 是否包含特殊字符
			containsAnyChar(str, charsArray) {
			    for (let i = 0; i < charsArray.length; i++) {
			        if (str.includes(charsArray[i])) {  
			            return true;
			        }  
			    }  
			    return false; 
			},
			
			// 随机生成字符
			randomString(length) {  
			    let result  = '';  
			    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';  
			    const charactersLength = characters.length;  
			    for (let i = 0; i < length; i++ ) {
			       result += characters.charAt(Math.floor(Math.random() * charactersLength));  
			    }  
			    return result;  
			} 
			
		}
	};
</script>

<style lang="scss">
	@import "../assets/css/fontx/iconfont.css";
	@import "../assets/css/home.scss";

	.ivu-input-number-controls-outside-btn i {
		font-weight: 800;
	}

	.update-point {
		display: inline-block;
		width: 8px;
		height: 8px;
		border-radius: 8px;
		background: #ff0000;
		top: 14px;
		position: absolute;
		left: -13px;
	}

	.menu-item {
		padding: 8px 0;
		font-size: 14px;

		.iconfont {
			font-size: 32px;
		}

		&:hover,
		&.active {
			color: #ed4014;
		}
	}

	.ivu-progress-show-info .ivu-progress-outer {
		padding-right: 40px !important;
		margin-right: -40px !important;
	}

	.tips {
		text-align: center;
		padding: 10px 0;
		color: #ed4014;
		font-size: 12px;
	}

	.handle-desc {
		display: inline-block;
		width: calc(100% - 100px);
		overflow: hidden;
	}

	.ivu-menu-submenu-title {
		font-weight: 600;
	}

	.ivu-menu .ivu-menu-item {
		line-height: 1;
	}

	// new-el
	.el-menu {
		border-right: none !important;
	}

	.cmenu-item {
		padding: 0 20px 20px;
		margin-bottom: 15px;

		.cmenu-title {
			font-size: 18px;
			font-weight: 600;
			padding-bottom: 20px;
		}

		.citem-nav {
			text-align: center;
			border-radius: 10px;
			min-height: 110px;
			padding: 15px 0;
			background-color: #fff;
			font-size: 15px;
			cursor: pointer;

			&.bg-linear1 {
				color: #fff;
				font-size: 20px;
				background: linear-gradient(to right bottom, #2A56CA, #5795F4);
			}

			&.bg-linear2 {
				color: #fff;
				font-size: 20px;
				background: linear-gradient(to right top, #147FBB, #5EB3E3);
			}

			&.bg-linear3 {
				color: #fff;
				font-size: 20px;
				background: linear-gradient(to right bottom, #2F9E8A, #56CDB1);
			}

			&:hover {
				margin-top: -5px;
				box-shadow: 3px 3px 6px #ccc, -3px -3px 6px #ccc;
			}

			.citem-img {
				width: 50px;
				margin-bottom: 10px;
			}
		}
	}
	
	.popper-open{
		text-align: center !important;
		padding: 10px !important;
		background: #303133 !important;
		color: #fff !important;
		min-width: 120px !important;
		opacity: 0.8;
	}
	
	.popper-open[x-placement^=bottom] .popper__arrow::after{
		border-bottom-color: #303133 !important;
	}
	
	textarea.el-textarea__inner{
		height: 100% !important;
		font-family: "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif;
	}
	
	.set-item{
		margin-right: 15px;
		
		.set-title{
			font-size: 13px;
		}
	}
	
	.outarea{
		height: 100%;
		border: 1px solid #DCDFE6;
		background-color: #4851a415; 
		padding: 15px;
		font-size: 20px;
		overflow: hidden auto;
	}
	
	.outtext{
		height: 100%;
		font-size: 20px;
		overflow: hidden auto;
		
		textarea{
			background-color: #4851a415; 
		}
	}
	
	.pin-tips{
		font-size: 14px;
		position: absolute;
		bottom: 10px;
		color: #ff0000;
		left: 0;
		right: 0;
		margin: auto;
		text-align: center;
	}
	
	.outarea.red-border{
		border: 1px solid #F56C6C;
	}
	
	.outtext.red-border textarea{
		border: 1px solid #F56C6C;
	}
	
	h3{
		margin: 0;
	}
	
	.m-image{
		width: 20px;
		margin-right: 5px;
	}
	
	.dialog-footer-center{
		text-align: center;
	}
	
	.visible-tips-style{
		font-size: 18px; 
		color: #f73131; 
		font-weight: 600; 
		padding: 30px 40px 0;
	}
	
	.no-select{
		user-select: none; 
	}
	
	.tips-flex{
		display: flex;
		flex-wrap: nowrap;
		justify-content: space-around;
		align-items: center;
		
		.el-icon-s-opportunity{
			font-size: 50px;
			color: #f73131;
			margin-right: 10px;
		}
		
		.m-title{
			flex: 1;
			color: #f73131;
		}
	}
	
</style>