|
@@ -1,1935 +0,0 @@
|
|
|
-<template>
|
|
|
- <!-- 1/2/3/5 -->
|
|
|
- <el-main ref="el-main" style="background-color: #fafafa;">
|
|
|
- <template>
|
|
|
- <div class="content-top">
|
|
|
- <el-button-group>
|
|
|
- <el-button type="primary" size="mini" icon="el-icon-document"
|
|
|
- @click="pickFile()">添加文件</el-button>
|
|
|
- <el-button type="primary" size="mini" icon="el-icon-folder"
|
|
|
- @click="pickDir()">添加文件夹</el-button>
|
|
|
- <el-button type="primary" size="mini" icon="el-icon-delete"
|
|
|
- @click="clearList()">清空图片</el-button>
|
|
|
- </el-button-group>
|
|
|
-
|
|
|
- <el-row type="flex" style="align-items: center;">
|
|
|
- <div class="set-item">
|
|
|
- <span class="set-title">保存目录:</span>
|
|
|
- <el-input :title="handleData.newPath" ref="upload-input" size="mini" @focus="pickPath" placeholder="请选择输出目录" v-model="handleData.newPath" 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="exportImg()" :loading="loading">开始转换</el-button>
|
|
|
- </el-row>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div v-if="imgList.length == 0" class="upload-area" style="height: calc(100% - 63px);">
|
|
|
- <div class="file-area" @click="pickFile()" @dragover.prevent @drop="handleDrop" style="height: 100%;">
|
|
|
- <div class="file-area-pos">
|
|
|
- <img src="../assets/image/upload.png" style="width: 220px;"/>
|
|
|
- <p style="font-size: 16px;">将图片文件拖住至此处,或点击此处选择图片</p>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="img-content" style="padding: 20px; height: calc(100% - 62px);" v-else @dragover.prevent @drop="handleDrop">
|
|
|
- <el-row type="flex" justify="space-between">
|
|
|
- <h3>
|
|
|
- 图片处理 -
|
|
|
- <span v-if="menuIndex == 1">格式转换</span>
|
|
|
- <span v-if="menuIndex == 2">图片压缩</span>
|
|
|
- <span v-if="menuIndex == 3">修改尺寸</span>
|
|
|
- <span v-if="menuIndex == 5">添加水印</span>
|
|
|
- </h3>
|
|
|
- </el-row>
|
|
|
-
|
|
|
- <!-- 1、格式转换 2、图片压缩 -->
|
|
|
- <template v-if="menuIndex == 1 || menuIndex == 2">
|
|
|
- <div style="padding: 15px 0 20px;">
|
|
|
- <!-- 1格式转化 -->
|
|
|
- <template v-if="menuIndex == 1">
|
|
|
- <label>输出转换:</label>
|
|
|
- <el-select v-model="handleData.imgFormat" style="width:100px;" size="mini">
|
|
|
- <el-option v-for="(item, key) in imgFormat" :key="key" :value="item" :label="item"></el-option>
|
|
|
- </el-select>
|
|
|
- <vxe-button v-if="handleData.imgFormat == 'ICO'" type="text" status="info" icon="vxe-icon-info-circle-fill" @click="$message('图标资源ICO有最大尺寸限制,建议尺寸低于512x512')"></vxe-button>
|
|
|
- <vxe-button v-if="isGif" type="text" status="info" icon="vxe-icon-info-circle-fill" @click="$message('GIF图片默认输出第一帧,多帧输出到单独文件夹中')"></vxe-button>
|
|
|
- <el-checkbox v-if="isGif" v-model="gifChecked">GIF图片输出所有帧</el-checkbox>
|
|
|
- </template>
|
|
|
- <!-- 2图片压缩 -->
|
|
|
- <template v-if="menuIndex == 2">
|
|
|
- <label>压缩质量:</label>
|
|
|
- <el-input-number v-model="handleData.quality" :min="1" :max="100" size="mini"></el-input-number>
|
|
|
- <el-tag size="mini" type="danger" style="margin-left: 10px;" v-show="menuIndex == 2">质量越低压缩的越小</el-tag>
|
|
|
- </template>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div style="height: calc(100% - 78px);">
|
|
|
- <vxe-table ref="xTable" show-overflow class="img-table" max-height="100%" empty-text="没有更多数据了!" :row-config="{isCurrent: true, isHover: true}"
|
|
|
- :edit-config="{trigger: 'click', mode: 'cell'}" :data="imgList" :scroll-y="{enabled: true}">
|
|
|
- <vxe-column field="name" :title="'文件名'+'(' + imgList.length + ')'" min-width="120"></vxe-column>
|
|
|
- <vxe-column field="path" title="缩略图" width="70">
|
|
|
- <template #default="{ row }">
|
|
|
- <el-image style="width: 30px; height: 30px" :src="row.path" fit="contain"></el-image>
|
|
|
- </template>
|
|
|
- </vxe-column>
|
|
|
- <vxe-column field="size" title="大小" min-width="100" max-width="120">
|
|
|
- <template #default="{ row }">
|
|
|
- <span v-if="row.width == 0 && row.height == 0">-</span>
|
|
|
- <span v-else>{{row.size}}</span>
|
|
|
- </template>
|
|
|
- </vxe-column>
|
|
|
-
|
|
|
- <vxe-column field="width" title="尺寸" min-width="110" max-width="130">
|
|
|
- <template #default="{ row }">
|
|
|
- <span v-if="row.width == 0 && row.height == 0">{{'加载中 '+row.loadPercent+'%'}}</span>
|
|
|
- <span v-else>{{row.width + '*' + row.height}}</span>
|
|
|
- </template>
|
|
|
- </vxe-column>
|
|
|
- <vxe-column field="progress" title="进度" min-width="110" max-width="160">
|
|
|
- <template #default="{ row }">
|
|
|
- <el-progress :text-inside="true" :stroke-width="20" :percentage="row.percent"></el-progress>
|
|
|
- </template>
|
|
|
- </vxe-column>
|
|
|
- <vxe-column field="action" title="操作" width="80">
|
|
|
- <template #default="{ row, rowIndex }">
|
|
|
- <i style="font-size: 18px;" class="el-icon-delete cur-pointer" @click="delImgFile(rowIndex)"></i>
|
|
|
- </template>
|
|
|
- </vxe-column>
|
|
|
- </vxe-table>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
-
|
|
|
-
|
|
|
- <!-- 3、更改尺寸 5、添加水印 -->
|
|
|
- <template v-else-if="[3,5].indexOf(menuIndex) > -1">
|
|
|
- <div class="soft-content" style="padding: 15px 0 0 0; height: calc(100% - 20px);">
|
|
|
- <div class="content-left" style="width: calc(100% - 270px)">
|
|
|
- <div class="merge-flex">
|
|
|
- <div class="merge-scroll">
|
|
|
- <vxe-table fit show-overflow :show-header="false" align="center" height="100%" :row-config="{isCurrent: true, isHover: true, height: 100}"
|
|
|
- :data="imgList" @cell-click="selectTab">
|
|
|
- <vxe-column field="name" width="123" show-overflow>
|
|
|
- <template #default="{ row, rowIndex }">
|
|
|
- <vxe-button type="text" icon="vxe-icon-close" class="vxebtn-del" @click="delImgFile(rowIndex)"></vxe-button>
|
|
|
- <el-image style="width: 60px; height: 60px" :src="row.path" fit="contain" :title="row.name"></el-image>
|
|
|
- <div class="img-mid-progress" v-if="row.percent > 0">
|
|
|
- <el-progress :percentage="row.percent"></el-progress>
|
|
|
- </div>
|
|
|
- <div style="padding: 0 5px; overflow: hidden;white-space: nowrap;text-overflow: ellipsis;" :title="row.name">{{row.name}}</div>
|
|
|
- </template>
|
|
|
- </vxe-column>
|
|
|
- </vxe-table>
|
|
|
- </div>
|
|
|
- <div class="merge-content">
|
|
|
- <div style="width: 100%; height: 100%;">
|
|
|
- <div id="show-img" class="show-img" style="position:relative;overflow: hidden; width: 100%; height: 100%;">
|
|
|
- <div style="position: absolute;top: 5px; left: 5px;padding: 0 10px 10px 10px; background: #00000060; color: #fff;font-size: 12px;z-index: 2;">
|
|
|
- <label>放大:</label>
|
|
|
- <el-slider v-model="viewScale" class="info-input" :min="0.5" :max="5" :step="0.1"></el-slider>
|
|
|
- {{viewScale.toFixed(1)}}
|
|
|
- </div>
|
|
|
- <img draggable="false" class="result-img" :src="imgSrc"
|
|
|
- :style="{maxWidth: '80%',maxHeight: '500px', transform: 'rotate('+handleData.rotateValue+'deg) rotateY('+ (handleData.hflip ? '180' : '0') +'deg) rotateX('+ (handleData.vflip ? '180' : '0') +'deg) scale('+viewScale+')'}" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- </div>
|
|
|
- <div class="content-right" style="width: 260px;">
|
|
|
- <div class="setting-area">
|
|
|
- <div class="img-handle">
|
|
|
- <!-- 3更改尺寸 -->
|
|
|
- <div v-if="menuIndex == 3">
|
|
|
- <div class="handle-item">
|
|
|
- <el-radio-group v-model="handleData.sizeType">
|
|
|
- <el-radio-button label="1">按比例调整</el-radio-button>
|
|
|
- <el-radio-button label="2">按尺寸调整</el-radio-button>
|
|
|
- </el-radio-group>
|
|
|
- </div>
|
|
|
- <div class="handle-item" v-if="handleData.sizeType == '1'">
|
|
|
- <label class="handle-label">缩放比例:</label>
|
|
|
- <el-input-number size="small" v-model="handleData.scaling" :min="1" :max="500"></el-input-number>
|
|
|
- </div>
|
|
|
- <div class="handle-item" v-if="handleData.sizeType == '2'">
|
|
|
- <label class="handle-label">宽度:</label>
|
|
|
- <el-input-number size="small" v-model="handleData.width" :min="1" @change="scaleWidthChange"></el-input-number> px
|
|
|
- </div>
|
|
|
- <div class="handle-item" v-if="handleData.sizeType == '2'">
|
|
|
- <label class="handle-label">高度:</label>
|
|
|
- <el-input-number size="small" v-model="handleData.height" :min="1" @change="scaleHeightChange"></el-input-number> px
|
|
|
- </div>
|
|
|
- <div class="handle-item" v-if="handleData.sizeType == '2'">
|
|
|
- <label class="handle-label">锁定比例:</label>
|
|
|
- <el-checkbox size="small" v-model="handleData.lockScale"></el-checkbox>
|
|
|
- <span style="font-size: 12px; color: #666;">(原始尺寸{{imgInfo.originalWidth}}:{{imgInfo.originalHeight}})</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <!-- 5添加水印 -->
|
|
|
- <div v-if="menuIndex == 5">
|
|
|
- <div class="handle-item">
|
|
|
- <el-radio-group v-model="handleData.watermarkType">
|
|
|
- <el-radio-button label="1">文字水印</el-radio-button>
|
|
|
- <el-radio-button label="2">图片水印</el-radio-button>
|
|
|
- </el-radio-group>
|
|
|
- </div>
|
|
|
- <div class="handle-item" v-if="handleData.watermarkType == '1'">
|
|
|
- <label class="handle-label">水印类型:</label>
|
|
|
- <el-select size="small" v-model="handleData.watermarkStyle" style="width:150px;">
|
|
|
- <el-option value="1" label="单个水印"></el-option>
|
|
|
- <el-option value="2" label="多个水印"></el-option>
|
|
|
- </el-select>
|
|
|
- </div>
|
|
|
- <div v-if="handleData.watermarkType == '1'">
|
|
|
- <div class="handle-item">
|
|
|
- <label class="handle-label">文字内容:</label>
|
|
|
- <el-input type="text" v-model="handleData.watermarkValue" size="small" placeholder="请输入文字水印内容" style="width:150px;" @change="handleImg"></el-input>
|
|
|
- </div>
|
|
|
- <div class="handle-item">
|
|
|
- <label class="handle-label">文字样式:</label>
|
|
|
- <el-color-picker style="vertical-align: middle;" v-model="handleData.watermarkColor" show-alpha @change="handleImg"></el-color-picker>
|
|
|
- <el-input-number size="small" style="width: 105px;" v-model="handleData.watermarkFont" @change="handleImg" :min="0" :max="200"></el-input-number>
|
|
|
- </div>
|
|
|
- <div class="handle-item">
|
|
|
- <label class="handle-label">旋转角度:</label>
|
|
|
- <el-input-number size="small" style="width: 140px;" v-model="handleData.rotate" @change="handleImg" ></el-input-number> °
|
|
|
- </div>
|
|
|
- <div class="handle-item">
|
|
|
- <label class="handle-label">文字字体:</label>
|
|
|
- <el-select size="small" v-model="handleData.fonts" style="width:120px;" @change="handleImg">
|
|
|
- <el-option v-for="(item,key) in fonts" :key="key" :value="item.path" :label="item.name"></el-option>
|
|
|
- </el-select>
|
|
|
- <vxe-button type="text" status="info" icon="vxe-icon-info-circle-fill" @click="$message({message:'文字为中文时,请选择中文字体!', type:'warning'})"></vxe-button>
|
|
|
- </div>
|
|
|
- <template v-if="handleData.watermarkStyle == 2">
|
|
|
- <div class="handle-item" style="overflow: hidden;" v-if="handleData.watermarkType != '0'">
|
|
|
- <label class="handle-label">水印行数:</label>
|
|
|
- <el-input-number size="small" :min="1" v-model="handleData.watermarkDensityY" @change="handleImg" ></el-input-number>
|
|
|
- </div>
|
|
|
- <div class="handle-item" style="overflow: hidden;" v-if="handleData.watermarkType != '0'">
|
|
|
- <label class="handle-label">水印列数:</label>
|
|
|
- <el-input-number size="small" :min="1" v-model="handleData.watermarkDensityX" @change="handleImg" ></el-input-number>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- </div>
|
|
|
- <!-- 图片水印 -->
|
|
|
- <div v-if="handleData.watermarkType == '2'">
|
|
|
- <div class="handle-item">
|
|
|
- <label class="handle-label">图片水印:</label>
|
|
|
- <el-upload :style="{display: 'inline-block'}" action="/" :before-upload="getImgPath">
|
|
|
- <el-input type="text" readonly v-model="handleData.watermarkImgPath" size="small" style="width:125px;" ></el-input>
|
|
|
- <i class="el-icon-folder-opened open-folder" style="font-size:22px;"></i>
|
|
|
- </el-upload>
|
|
|
- </div>
|
|
|
- <div class="handle-item">
|
|
|
- <label class="handle-label">比例:</label>
|
|
|
- <el-input-number size="small" style="margin-right:5px;" :min="1" :max="200" v-model="handleData.watermarkImgSize" @change="handleImg" ></el-input-number>%
|
|
|
- </div>
|
|
|
- <div class="handle-item" v-if="handleData.watermarkType == '2'">
|
|
|
- <label class="handle-label">不透明度:</label>
|
|
|
- <el-input-number size="small" style="margin-right:5px;" :min="1" :max="100" v-model="handleData.watermarkImgOpactiy" @change="handleImg" ></el-input-number>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div class="handle-item" v-if="handleData.watermarkType == '2'">
|
|
|
- <label class="handle-label">旋转角度:</label>
|
|
|
- <el-input-number size="small" v-model="handleData.watermarkImgRotate" @change="handleImg" ></el-input-number>
|
|
|
- </div>
|
|
|
- <div class="handle-item" v-if="handleData.watermarkType != '0'">
|
|
|
- <label class="handle-label">水印位置:</label>
|
|
|
- <el-radio-group class="position-radio" v-model="handleData.watermarkPosition" :style="{width: '120px', color: '#fff'}" @change="handleImg">
|
|
|
- <el-radio :disabled="handleData.watermarkStyle == '2' && handleData.watermarkType == 1" :style="{margin: '2px 2px 2px 0', fontSize: 0}" v-for="key in watermarkPosition" :key="key" :label="key"></el-radio>
|
|
|
- </el-radio-group>
|
|
|
- <div class="handle-item">
|
|
|
- <label class="handle-label">水平边距:</label>
|
|
|
- <el-input-number size="small" v-model="handleData.watermarkX" @change="handleImg" ></el-input-number>
|
|
|
- </div>
|
|
|
- <div class="handle-item">
|
|
|
- <label class="handle-label">垂直边距:</label>
|
|
|
- <el-input-number size="small" v-model="handleData.watermarkY" @change="handleImg" ></el-input-number>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
-
|
|
|
- </div>
|
|
|
-
|
|
|
- <!-- 未登录弹窗 -->
|
|
|
- <el-dialog :visible.sync="memberModel" width="400px" custom-class="member-dialog member-dialog2" style="border-radius: 20px; overflow: hidden;">
|
|
|
- <div class="member-model">
|
|
|
- <div class="adv-banner">
|
|
|
- <img src="../assets/image/popup.png" style="width: 100%; height: 100%;"/>
|
|
|
- </div>
|
|
|
- <div class="font-12" style="padding: 20px; margin-bottom: 10px;">
|
|
|
- <div style="text-align: center; margin-bottom: 10px;">
|
|
|
- <p style="font-size: 16px;font-weight: 600;color: #f73131;">非VIP导出图片有官方水印</p>
|
|
|
- <p style="font-size: 14px; font-weight: 600; margin-top: 15px;">开通会员即享以下权益</p>
|
|
|
- </div>
|
|
|
- <el-row :gutter="20" class="micon-list">
|
|
|
- <el-col :span="6" class="micon-item">
|
|
|
- <img src="../assets/image/member1.png" style="width: 60px;"/>
|
|
|
- <p>不限功能</p>
|
|
|
- </el-col>
|
|
|
- <el-col :span="6" class="micon-item">
|
|
|
- <img src="../assets/image/member2.png" style="width: 60px;"/>
|
|
|
- <p>不限设备</p>
|
|
|
- </el-col>
|
|
|
- <el-col :span="6" class="micon-item">
|
|
|
- <img src="../assets/image/member3.png" style="width: 60px;"/>
|
|
|
- <p>无官方水印</p>
|
|
|
- </el-col>
|
|
|
- <el-col :span="6" class="micon-item">
|
|
|
- <img src="../assets/image/member4.png" style="width: 60px;"/>
|
|
|
- <p>技术支持</p>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
- </div>
|
|
|
- <div class="micon-btn">
|
|
|
- <el-button class="micon-btn1" style="margin:0 10px;" @click="exportImg(true)" :round="true">开始转换</el-button>
|
|
|
- <el-button class="micon-btn2" type="primary" @click="openVip()" :round="true">开通会员</el-button>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </el-dialog>
|
|
|
-
|
|
|
- </template>
|
|
|
- </el-main>
|
|
|
-
|
|
|
-</template>
|
|
|
-
|
|
|
-<script>
|
|
|
-import os from 'os'
|
|
|
-import fs from 'fs'
|
|
|
-import pathMod, { resolve } from 'path';
|
|
|
-import electronApi from '@/utils/electronApi';
|
|
|
-import pjson from '/package.json'
|
|
|
-import Vue from 'vue'
|
|
|
-const sizeOf = require('image-size')
|
|
|
-
|
|
|
-let separator = '';
|
|
|
-if (os.platform == 'linux') {
|
|
|
- separator = '/'
|
|
|
-} else {
|
|
|
- separator = '\\'
|
|
|
-}
|
|
|
-
|
|
|
-export default {
|
|
|
- name: 'landing-page',
|
|
|
- components: {
|
|
|
-
|
|
|
- },
|
|
|
- data() {
|
|
|
- return {
|
|
|
- memberModel: false,
|
|
|
- isGif: false, //是否含有gif图片
|
|
|
- gifChecked: false, // 是否输出所有帧
|
|
|
- rollFlag: false,
|
|
|
- viewScale: 1,
|
|
|
- productName: pjson.softInfo.softName,
|
|
|
- setModal: false,
|
|
|
- resetModal: false,
|
|
|
- renameModal: false,
|
|
|
- subTitle: '请查看列表文件状态',
|
|
|
- cropimgShow: false,
|
|
|
- cropImgIndex: -1,
|
|
|
- cropInt: false,
|
|
|
- selectInt: false,
|
|
|
- virtualWidth: 0,
|
|
|
- virtualHeight: 0,
|
|
|
- execLimit: 3,
|
|
|
- defaultFont:'c:\\windows\\fonts\\simkai.ttf',
|
|
|
- imgShow:false,
|
|
|
- pickProgress:false,
|
|
|
- pickProgressPercent:0,
|
|
|
- fonts:[],
|
|
|
- watermarkPosition:['NorthWest','North','NorthEast','West','Center','East','SouthWest','South','SouthEast'],
|
|
|
- imgUrl: this.$api.imgUrl,
|
|
|
- imgSrc: '',
|
|
|
- imgList: [],
|
|
|
- mergeList: [], // 拼接图片列表
|
|
|
- cropList: [], // 裁剪图片列表
|
|
|
- imgInfo: '',
|
|
|
- imgInfoIndex: 0,
|
|
|
- menuIndex: 1, // 选中菜单
|
|
|
- imgFormat: ['PNG','BMP','JPEG','JPG','ICO','WBMP','WEBP','HEIC','GIF','JFIF','TTF','TIF','TIFF','SVG','3FR','3G2','3GP','AAI','AVIF','AI','ART','ARW','BGR','BGRA','BGRO','BIE','BMP2','BMP3','BRF','CAL','CALS','CANVAS','CAPTION','CIN','CIP','CLIP','CMYK','CMYKA','CR2','CRW','CUR','CUT','DATA','DCM','DCR','DCX','DDS','DFONT','DJVU','DNG','DOT','DPX','DXT1','DXT5','EPDF','EPI','EPS','EPS2','EPS3','EPSF','EPSI','EPT','EPT2','EPT3','ERF','EXR','FAX','FILE','FITS','FRACTAL','FTP','FTS','G3','G4','GIF87','GRADIENT','GRAY','GRAYA','GROUP4','GV','H','HALD','HDR','HISTOGRAM','HRZ','ICB','ICON','IIQ','INFO','INLINE','IPL','ISOBRL','ISOBRL6','J2C','J2K','JBG','JBIG','JNG','JNX','JP2','JPC','JPE','JPM','JPS','JPT','JSON','K25','KDC','LABEL','M2V','M4V','MAC','MAGICK','MAP','MASK','MAT','MATTE','MEF','MIFF','MKV','MNG','MONO','MRW','MSL','MSVG','MVG','NEF','NRW','ORF','OTB','OTF','PAL','PALM','PAM','PANGO','PATTERN','PBM','PCD','PCDS','PCL','PCT','PEF','PES','PFA','PFB','PFM','PGM','PGX','PICON','PICT','PIX','PJPEG','PLASMA','PNG00','PNG24','PNG32','PNG48','PNG64','PNG8','PNM','PPM','PREVIEW','PS','PS2','PS3','PSB','PSD','PTIF','PWP','RADIAL-GRADIENT','RAF','RAS','RAW','RGB','RGBA','RGBO','RGF','RLA','RLE','RMF','RW2','SCR','SCT','SFW','SGI','SHTML','SIX','SIXEL','SPARSE-COLOR','SR2','SRF','STEGANO','SUN','SVGZ','TGA','THUMBNAIL','TIFF64','TILE','UBRL','UBRL6','UIL','UYVY','VDA','VICAR','VID','VIFF','VIPS','VST','WMF','WMV','WMZ','WPG','X','X3F','XBM','XC','XCF','XPM','XPS','XV','XWD','YCbCr','YCbCrA','YUV'], // 图片格式
|
|
|
- positionList: ['上左', '上中', '上右', '中左', '中间', '中右', '下左', '下中', '下右'],
|
|
|
-
|
|
|
- downloadDir: '', // 默认下载目录
|
|
|
- softdownloadDir: '', // 软件下载目录
|
|
|
- handleData: {
|
|
|
- dpi: 300,
|
|
|
- width: 0,
|
|
|
- height: 0,
|
|
|
- pathType: '2', // 输出目录类型
|
|
|
- newPath: os.userInfo().homedir + separator + "Downloads", // 新路径
|
|
|
- autoRename: false, // 是否自动重命名
|
|
|
- imgFormat: 'JPG', // 转换类型
|
|
|
- quality: 92, // 图片品质
|
|
|
- colorNum:256, // 颜色数量 1 - 256
|
|
|
- sizeType: '1', // 调整尺寸
|
|
|
- scaling: 100, // 缩放比例
|
|
|
- rotateValue: 0, // 旋转角度
|
|
|
- color: '0', // 图片色彩
|
|
|
- colorValue: 256,
|
|
|
- paintValue: 1, //油画数值
|
|
|
- brightnessValue: 0, // 亮度
|
|
|
- saturationValue: 0, //饱和度
|
|
|
- hueValue: 0, // 色调
|
|
|
- contrastValue: 0, // 对比度
|
|
|
- opacityValue: 100, // 透明度
|
|
|
- compressScaling:100,
|
|
|
- compressOutType:2,
|
|
|
- watermarkType: '1', // 水印类型 1文字 2图片
|
|
|
- watermarkStyle: '1', // 1 单个 2平铺
|
|
|
- watermarkValue: '', // 水印文字内容
|
|
|
- watermarkColor: '#ff0000',
|
|
|
- watermarkFont: 16,
|
|
|
- watermarkX: 0,
|
|
|
- watermarkY: 0,
|
|
|
- watermarkDensityX: 3, // 平铺水印密度
|
|
|
- watermarkDensityY: 3, // 平铺水印密度
|
|
|
- watermarkImgPath: '', //图片水印路径
|
|
|
- watermarkImgOpactiy: 100, // 水印不透明度
|
|
|
- watermarkImgSize: 100, // 水印缩放比例
|
|
|
- watermarkImgRotate: 0,
|
|
|
- watermarkPosition: 'Center', // 水印位置
|
|
|
- lineFlag: false,
|
|
|
- lineWidth: 3,
|
|
|
- lineColor: '#ff0000',
|
|
|
- fonts:'',
|
|
|
- rotate: 30,
|
|
|
- circularFlag: false,
|
|
|
- circularValue: 10,
|
|
|
- hflip: false,
|
|
|
- vflip: false,
|
|
|
- lockScale: true,
|
|
|
- },
|
|
|
- dowloadModel: false,
|
|
|
- finishModel: false,
|
|
|
- version: '0.0.1',
|
|
|
-
|
|
|
- isStart: false, // 是否开始转换
|
|
|
- isUpdate: false, // 是否有更新
|
|
|
-
|
|
|
- loading: false,
|
|
|
- authority:{
|
|
|
- isAuthority: false
|
|
|
- }, // 用户权限
|
|
|
- sysDefaultTmpPath:'', // 系统水印路径
|
|
|
- previewTmpPath:'', // 预览图片路径
|
|
|
- imgLoading:false,
|
|
|
- };
|
|
|
- },
|
|
|
- mounted() {
|
|
|
- let __dirname = os.userInfo().homedir;
|
|
|
- this.softdownloadDir = __dirname + separator + "Downloads";
|
|
|
- if(fs.existsSync(__dirname + separator + "Desktop")){
|
|
|
- this.downloadDir = __dirname + separator + "Desktop"
|
|
|
- } else{
|
|
|
- this.downloadDir = __dirname + separator + "Downloads"
|
|
|
- }
|
|
|
- this.handleData.newPath = this.downloadDir;
|
|
|
-
|
|
|
- // 预览图片路径
|
|
|
- this.previewTmpPath = os.tmpdir()+separator+'preview.png';
|
|
|
-
|
|
|
- this.fonts = [
|
|
|
- {
|
|
|
- name:'宋体',
|
|
|
- path:'c:\\Windows\\fonts\\simsun.ttc',
|
|
|
- },
|
|
|
- {
|
|
|
- name:'仿宋',
|
|
|
- path:'c:\\windows\\fonts\\simfang.ttf',
|
|
|
- },
|
|
|
- {
|
|
|
- name:'楷体',
|
|
|
- path:'c:\\windows\\fonts\\simkai.ttf',
|
|
|
- },
|
|
|
- {
|
|
|
- name:'微软雅黑 常规',
|
|
|
- path:'C:\\Windows\\Fonts\\msyh.ttc',
|
|
|
- },
|
|
|
- {
|
|
|
- name:'微软雅黑 粗体',
|
|
|
- path:'c:\\windows\\fonts\\msyhbd.ttc'
|
|
|
- }
|
|
|
- ];
|
|
|
- this.defaultFont = 'c:\\windows\\fonts\\simkai.ttf';
|
|
|
- },
|
|
|
- methods: {
|
|
|
- // 检查是否授权登录-是否是会员状态
|
|
|
- checkAuthority(){
|
|
|
- this.$emit('check-authority', '');
|
|
|
- },
|
|
|
- openVip(){
|
|
|
- this.memberModel = false;
|
|
|
- this.$emit('open-vip', '');
|
|
|
- },
|
|
|
- // 拖拽事件
|
|
|
- handleDrop(e){
|
|
|
- //阻止默认行为
|
|
|
- e.preventDefault();
|
|
|
- //获取文件列表
|
|
|
- let files = e.dataTransfer.files;
|
|
|
- let pathArr = [];
|
|
|
- for(let i = 0; i < files.length; i++){
|
|
|
- pathArr.push(files[i].path);
|
|
|
- }
|
|
|
- this.pushFileToList(pathArr);
|
|
|
- },
|
|
|
- // 鼠标滚轮事件
|
|
|
- initRoll(){
|
|
|
- let element = document.getElementById('show-img');
|
|
|
- if(!this.rollFlag){
|
|
|
- // 添加滚轮事件监听器
|
|
|
- element.addEventListener('wheel', (event) => {
|
|
|
- this.rollFlag = true;
|
|
|
- // event.deltaY 是滚轮滚动的距离,正值表示向下滚动,负值表示向上滚动
|
|
|
- if (event.deltaY < 0) {
|
|
|
- if(this.viewScale < 5){
|
|
|
- this.viewScale += 0.1;
|
|
|
- }
|
|
|
- } else {
|
|
|
- if(this.viewScale > 0){
|
|
|
- this.viewScale -= 0.1;
|
|
|
- }
|
|
|
- }
|
|
|
- event.preventDefault();
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- },
|
|
|
- // 选择目录
|
|
|
- pickPath() {
|
|
|
- this.$refs['upload-input'].blur();
|
|
|
- electronApi.call('pickDir', []).then((path) => {
|
|
|
- if (path) {
|
|
|
- this.handleData.newPath = 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'])
|
|
|
- },
|
|
|
- // 清除列表
|
|
|
- clearList() {
|
|
|
- if(this.menuIndex != 8 && this.menuIndex != 10){
|
|
|
- this.imgList = [];
|
|
|
- this.imgSrc = '';
|
|
|
- this.setDefaultData();
|
|
|
- }else if(this.menuIndex == 8){
|
|
|
- this.mergeList = [];
|
|
|
- }else{
|
|
|
- this.cropList = [];
|
|
|
- this.cropImgIndex = -1;
|
|
|
- this.setDefaultCropData();
|
|
|
- this.cropOptionsImgInfo = {};
|
|
|
- }
|
|
|
-
|
|
|
- this.rollFlag = false;
|
|
|
- this.isGif = false;
|
|
|
- this.gifChecked = false;
|
|
|
- },
|
|
|
- setMenuIndex(index){
|
|
|
- this.menuIndex = index;
|
|
|
- this.setDefaultData();
|
|
|
- if(index == 5){
|
|
|
- this.handleData.fonts = this.defaultFont.toString();
|
|
|
- }else if(index == 3){
|
|
|
- this.handleData.width = this.imgInfo.width ? this.imgInfo.width : 0;
|
|
|
- this.handleData.height = this.imgInfo.height ? this.imgInfo.height : 0;
|
|
|
- }
|
|
|
- if(this.imgList.length > 0){
|
|
|
- this.setDefaultImgInfo(this.imgList[0]);
|
|
|
- }
|
|
|
-
|
|
|
- if([3,4,5,6,9].indexOf(this.menuIndex) == -1){ // 滚动事件
|
|
|
- this.rollFlag = false;
|
|
|
- }
|
|
|
-
|
|
|
- },
|
|
|
- setDefaultCropData(){
|
|
|
- this.cropOptions = {
|
|
|
- img: '',
|
|
|
- autoCrop: true, // 是否默认生成截图框
|
|
|
- autoCropWidth: 100,
|
|
|
- autoCropHeight: 100,
|
|
|
- cropWidth: 100,
|
|
|
- cropHeight: 100,
|
|
|
- original: false,
|
|
|
- maxImgSize: 20000,
|
|
|
- canMove: false,
|
|
|
- centerBox: true, // 截图框是否被限制在图片里面
|
|
|
- fixed: false, //是否开启截图框宽高固定比例
|
|
|
- fixedValue: 'free',
|
|
|
- cropType: '1',
|
|
|
- cropClassify: '1',
|
|
|
- fixedNumber: [1, 1],
|
|
|
- infoTrue: true,
|
|
|
- previewInfo: '',
|
|
|
- cropScale: 100,
|
|
|
- };
|
|
|
- },
|
|
|
- setDefaultData(){
|
|
|
- this.handleData = {
|
|
|
- dpi: 300,
|
|
|
- width: 0,
|
|
|
- height: 0,
|
|
|
- pathType: this.handleData.pathType, // 输出目录类型
|
|
|
- newPath: this.handleData.newPath, // 新路径
|
|
|
- autoRename: false, // 是否自动重命名
|
|
|
- imgFormat: 'JPG', // 转换类型
|
|
|
- quality: 92, // 图片品质
|
|
|
- colorNum: 256, // 颜色数量
|
|
|
- color: '0', // 图片色彩
|
|
|
- sizeType: '1', // 调整尺寸
|
|
|
- scaling: 100, // 缩放比例
|
|
|
- colorValue: 256,
|
|
|
- paintValue: 1, // 油画数值
|
|
|
- brightnessValue: 0, // 亮度
|
|
|
- saturationValue: 0, //饱和度
|
|
|
- hueValue: 0, // 色调
|
|
|
- contrastValue: 0, // 对比度
|
|
|
- rotateValue: 0, // 旋转角度
|
|
|
- opacityValue: 100, // 透明度
|
|
|
- compressScaling:100,
|
|
|
- compressOutType:2,
|
|
|
- watermarkType: '1', // 水印类型 1文字 2图片
|
|
|
- watermarkStyle: '1', // 1 单个 2平铺
|
|
|
- watermarkValue: '', // 水印文字内容
|
|
|
- watermarkColor: '#ff0000',
|
|
|
- watermarkFont: 16,
|
|
|
- watermarkX: 0,
|
|
|
- watermarkY: 0,
|
|
|
- watermarkDensityX: 3, // 平铺水印密度
|
|
|
- watermarkDensityY: 3, // 平铺水印密度
|
|
|
- watermarkImgPath: '', //图片水印路径
|
|
|
- watermarkImgOpactiy: 100, // 水印不透明度
|
|
|
- watermarkImgSize: 100, //水印缩放比例
|
|
|
- watermarkImgRotate:0,
|
|
|
- watermarkPosition: 'Center',
|
|
|
- lineFlag: false,
|
|
|
- lineWidth: 3,
|
|
|
- lineColor: '#ff0000',
|
|
|
- fonts: this.defaultFont.toString(),
|
|
|
- rotate: 30,
|
|
|
- circularFlag: false,
|
|
|
- circularValue: 10,
|
|
|
- hflip: false,
|
|
|
- vflip: false,
|
|
|
- lockScale: true,
|
|
|
- };
|
|
|
- },
|
|
|
- // 选择水印图片
|
|
|
- getImgPath(e) {
|
|
|
- if (e) {
|
|
|
- this.handleData.watermarkImgPath = e.path;
|
|
|
- this.handleImg();
|
|
|
- }
|
|
|
- },
|
|
|
- pickFile(){
|
|
|
- electronApi.call('pickFile', [this.imgFormat.join(','),true]).then(async(files) =>{
|
|
|
- this.pushFileToList(files,0);
|
|
|
- });
|
|
|
- },
|
|
|
- pickDir(){
|
|
|
- electronApi.call('pickDir', []).then((path) =>{
|
|
|
- if(path){
|
|
|
- this.dealDir(path);
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
- dealDir(currentDirPath){
|
|
|
- let files = fs.readdirSync(currentDirPath)
|
|
|
-
|
|
|
- for (let i = 0; i < files.length; i++) {
|
|
|
- let name = files[i];
|
|
|
- var filePath = pathMod.join(currentDirPath, name);
|
|
|
- var stat = fs.statSync(filePath);
|
|
|
-
|
|
|
- if (stat.isFile()) {
|
|
|
- this.pushFileToList([filePath]);
|
|
|
- } else if (stat.isDirectory()) {
|
|
|
- this.dealDir(filePath)
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
- pushFileToList(files){
|
|
|
- // 直接渲染
|
|
|
- files.map(file => {
|
|
|
- let filename = file.substr(file.lastIndexOf(separator)+1);
|
|
|
-
|
|
|
- let size = fs.statSync(file).size;
|
|
|
- let imgInfo = {
|
|
|
- name: filename,
|
|
|
- size: this.$utils.handleSize(size),
|
|
|
- width: 0,
|
|
|
- height: 0,
|
|
|
- originalWidth: 0,
|
|
|
- originalHeight: 0,
|
|
|
- path: file,
|
|
|
- type: filename.lastIndexOf('.') == -1 ? '' : filename.substr(filename.lastIndexOf('.')+1),
|
|
|
- loadPercent: 0,
|
|
|
- percent: 0,
|
|
|
- top: 0,
|
|
|
- left: 0
|
|
|
- };
|
|
|
-
|
|
|
- if(!imgInfo.type){
|
|
|
- this.$message({message: '不是有效的图片文件! - '+ file , type: 'warning'});
|
|
|
- }else{
|
|
|
- if(this.imgFormat.indexOf(imgInfo.type.toUpperCase()) == -1){
|
|
|
- this.$message({message: '不是有效的图片文件! - '+ file , type: 'warning'});
|
|
|
- }else{
|
|
|
- if(imgInfo.type.toUpperCase() == 'GIF'){
|
|
|
- this.isGif = true;
|
|
|
- }
|
|
|
- try {
|
|
|
- let dimensions = sizeOf(file);
|
|
|
- imgInfo.width = dimensions.width;
|
|
|
- imgInfo.height = dimensions.height;
|
|
|
- imgInfo.originalWidth = dimensions.width;
|
|
|
- imgInfo.originalHeight = dimensions.height;
|
|
|
- } catch (error) {
|
|
|
- }
|
|
|
-
|
|
|
- // 过滤重复图片
|
|
|
- let flag = true;
|
|
|
- for(let m = 0; m < this.imgList.length; m++){
|
|
|
- if(this.imgList[m].name == imgInfo.name && this.imgList[m].path == imgInfo.path){
|
|
|
- flag = false;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(!flag){
|
|
|
- this.$message({message: '该图片已经存在队列中 - '+ file , type: 'warning'});
|
|
|
- }else{
|
|
|
- this.imgList.push(imgInfo);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- })
|
|
|
-
|
|
|
- // 设置第一个为默认图片
|
|
|
- if(this.imgSrc == '' && this.imgList[0]){
|
|
|
- this.setDefaultImgInfo(this.imgList[0])
|
|
|
- }
|
|
|
-
|
|
|
- },
|
|
|
- // 设置默认的图片
|
|
|
- setDefaultImgInfo(info){
|
|
|
- this.imgInfo = info;
|
|
|
- this.handleData.width = this.imgInfo.width;
|
|
|
- this.handleData.height = this.imgInfo.height;
|
|
|
- this.imgLoading = true;
|
|
|
-
|
|
|
- if([1,2,7,11].indexOf(this.menuIndex) == -1){
|
|
|
- electronApi.fileStream(this.imgInfo.path).then(buffer => {
|
|
|
- this.imgSrc = "data:image/png;base64,"+buffer.toString('base64');
|
|
|
- this.imgLoading = false;
|
|
|
- }).catch(err => {
|
|
|
- this.imgLoading = false;
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- if([3,4,5,6,9].indexOf(this.menuIndex) > -1){ // 绑定滚动事件
|
|
|
- setTimeout(() => {
|
|
|
- if(!this.rollFlag){
|
|
|
- this.initRoll();
|
|
|
- }
|
|
|
- }, 600);
|
|
|
- }
|
|
|
-
|
|
|
- },
|
|
|
- // 选择新路径
|
|
|
- getFolder(e) {
|
|
|
- this.handleData.newPath = e.path;
|
|
|
- this.downloadDir = e.path;
|
|
|
- },
|
|
|
- selectTab(data, index) {
|
|
|
- let currentRow = data.rowIndex > -1 ? this.imgList[data.rowIndex] : data;
|
|
|
- index = index ? 0 : data.rowIndex;
|
|
|
- this.imgInfo = currentRow;
|
|
|
- this.imgInfoIndex = index;
|
|
|
-
|
|
|
- if([3,6,7,9].indexOf(this.menuIndex) > -1){
|
|
|
- this.imgLoading = true;
|
|
|
- electronApi.fileStream(currentRow.path).then(buffer => {
|
|
|
- this.imgSrc = "data:image/png;base64,"+buffer.toString('base64');
|
|
|
- this.imgLoading = false;
|
|
|
- }).catch(err => {
|
|
|
- this.imgLoading = false;
|
|
|
- })
|
|
|
- this.handleData.width = Number(currentRow.width);
|
|
|
- this.handleData.height = Number(currentRow.height);
|
|
|
- }else if([4,5].indexOf(this.menuIndex) > -1){
|
|
|
- this.handleImg();
|
|
|
- }else if(this.menuIndex == 1){
|
|
|
- this.handleData.imgFormat = 'JPG';
|
|
|
- }
|
|
|
- },
|
|
|
- // 导出
|
|
|
- async exportImg(flag) {
|
|
|
- await this.checkAuthority();
|
|
|
- if(!fs.existsSync(this.downloadDir + separator + pjson.softInfo.softName)){
|
|
|
- fs.mkdirSync(this.downloadDir + separator + pjson.softInfo.softName);
|
|
|
- }
|
|
|
-
|
|
|
- if (this.imgList.length > 0) {
|
|
|
- if (!this.authority.isAuthority && !flag) {
|
|
|
- this.memberModel = true;
|
|
|
- return false;
|
|
|
- } else {
|
|
|
- this.memberModel = false;
|
|
|
- }
|
|
|
-
|
|
|
- this.loading = true;
|
|
|
- setTimeout(()=>{
|
|
|
- this.loading = false;
|
|
|
- }, 1500)
|
|
|
-
|
|
|
-
|
|
|
- // 删除水印,防止直接篡改水印图片
|
|
|
- this.deleteSysWtater();
|
|
|
-
|
|
|
- // 更改尺寸的时候,宽度和高度不允许为0
|
|
|
- if(this.menuIndex == 3 && this.handleData.sizeType != 1){
|
|
|
- if(this.handleData.width <= 0 || this.handleData.height <=0){
|
|
|
- this.$message({message: '请设置缩放的宽度和高度' , type: 'warning'});
|
|
|
- return false
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- //percent
|
|
|
- let taskArr = [];
|
|
|
- let newPath = '';
|
|
|
- for(let i=0; i<this.imgList.length; i++){
|
|
|
- let item = this.imgList[i];
|
|
|
- let lastIndex = item.path.lastIndexOf('.');
|
|
|
- let imgType = item.type;
|
|
|
- let suffix = '';
|
|
|
- if(this.menuIndex == 1){
|
|
|
- suffix = this.handleData.imgFormat.toLowerCase();
|
|
|
- }else{
|
|
|
- suffix = item.name.lastIndexOf('.') != -1 ? item.name.substr(item.name.lastIndexOf('.')+1) : imgType.toLowerCase();
|
|
|
- }
|
|
|
- // 图片压缩,输出格式为jpg
|
|
|
- if(this.menuIndex == 2 && this.handleData.compressOutType == 1){
|
|
|
- suffix = 'jpg';
|
|
|
- }
|
|
|
- newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + item.name.slice(0, item.name.lastIndexOf('.')) + '.' +suffix;
|
|
|
-
|
|
|
- // 处理图像
|
|
|
- let task = this.dealImg(i, item, newPath);
|
|
|
- if(task){
|
|
|
- taskArr.push(task);
|
|
|
- }
|
|
|
-
|
|
|
- if((i+1) % this.execLimit == 0){
|
|
|
- await Promise.all(taskArr).then(result => {
|
|
|
- taskArr = [];
|
|
|
- }).catch(err => {
|
|
|
- })
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(taskArr.length > 0){
|
|
|
- await Promise.all(taskArr).then(result => {
|
|
|
- taskArr = [];
|
|
|
- }).catch(err => {
|
|
|
- // 错误文件添加到服务中
|
|
|
- console.log('err',err);
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- // 打开文件夹
|
|
|
- if(this.imgList.length > 0){
|
|
|
- this.$message({message: '恭喜你,任务已完成!', type: 'success'});
|
|
|
- electronApi.call('showItemInfolder',[newPath])
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
- // 操作
|
|
|
- handleImg() {
|
|
|
- if (this.imgInfo.path) {
|
|
|
- this.imgLoading = true;
|
|
|
- this.dealImg(this.imgInfoIndex);
|
|
|
- }
|
|
|
- },
|
|
|
- // 处理图片
|
|
|
- dealImg(index, img, path){
|
|
|
- let reduceFlag = img ? false : true;
|
|
|
- let imgInfo = img ? img : this.imgInfo;
|
|
|
- let newPath = img ? path : this.previewTmpPath;
|
|
|
- let task = '';
|
|
|
-
|
|
|
- switch (this.menuIndex) {
|
|
|
- case 1: // 格式转换
|
|
|
- task = new Promise((resolve,reject) => {
|
|
|
-
|
|
|
- let imgPath = imgInfo.path;
|
|
|
- let gifParams = [];
|
|
|
- if(imgInfo.type.toLowerCase() == 'psd'){
|
|
|
- imgPath = imgInfo.path + '[0]';
|
|
|
- }
|
|
|
- if(imgInfo.type.toLowerCase() == 'gif'){
|
|
|
- if(this.gifChecked){
|
|
|
- gifParams = ['-coalesce'];
|
|
|
- let name = imgInfo.name.slice(0, imgInfo.name.lastIndexOf('.'));
|
|
|
- let gifPath = this.downloadDir + separator + pjson.softInfo.softName + separator + name;
|
|
|
- if(!fs.existsSync(gifPath)){
|
|
|
- fs.mkdirSync(gifPath);
|
|
|
- }
|
|
|
- newPath = gifPath + separator + name + '.' + this.handleData.imgFormat.toLowerCase();
|
|
|
- }else{
|
|
|
- imgPath = imgInfo.path + '[0]';
|
|
|
- }
|
|
|
- }
|
|
|
- let cmd = [
|
|
|
- 'convert.exe',
|
|
|
- '-monitor',
|
|
|
- ...gifParams,
|
|
|
- imgPath,
|
|
|
- newPath
|
|
|
- ];
|
|
|
-
|
|
|
- electronApi.spawnExec(cmd,{
|
|
|
- stderr:(data) => {
|
|
|
- let str = data.toString();
|
|
|
- const regexDuration = /Load.*?,(.*?)%/;
|
|
|
- let regexDuration2 = /Save.*?,(.*?)%/;
|
|
|
- if(imgInfo.type.toLowerCase() == 'gif'){
|
|
|
- regexDuration2 = /Write.*?,(.*?)%/;
|
|
|
- }
|
|
|
-
|
|
|
- const res = regexDuration.exec(str);
|
|
|
- const res2 = regexDuration2.exec(str);
|
|
|
- let p1 = 0;
|
|
|
- let p2 = 0;
|
|
|
- if(res && res[1]){
|
|
|
- p1 = parseInt(res[1]);
|
|
|
- if(p1 > 0){
|
|
|
- imgInfo.percent = Math.round(p1/2);
|
|
|
- }
|
|
|
- }else{
|
|
|
- if(res2 && res2[1]){
|
|
|
- p2 = parseInt(res2[1]);
|
|
|
- }
|
|
|
- if(p2 > 0){
|
|
|
- imgInfo.percent = Math.round(50+(p2/2));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(this.imgList.indexOf(index)){
|
|
|
- this.imgList.splice(index,1,imgInfo);
|
|
|
- }
|
|
|
- }
|
|
|
- }).then(res => {
|
|
|
- setTimeout(() => {
|
|
|
- if(this.imgList.indexOf(index)){
|
|
|
- imgInfo.percent = 100;
|
|
|
- this.imgList.splice(index, 1, imgInfo);
|
|
|
- }else{
|
|
|
- reject({type:this.menuIndex,index,err:'用户强制终止!'});
|
|
|
- }
|
|
|
- }, 150)
|
|
|
-
|
|
|
- //未购买 添加系统水印
|
|
|
- this.addWatermark(index,imgInfo,newPath);
|
|
|
- resolve({type:this.menuIndex,index, img});
|
|
|
- }).catch(err => {
|
|
|
- // console.log(err.stderr.toString());
|
|
|
- reject({type:this.menuIndex,index,err});
|
|
|
- });
|
|
|
- });
|
|
|
-
|
|
|
- break;
|
|
|
-
|
|
|
- case 2: // 图片压缩
|
|
|
- task = new Promise(async (resolve,reject) => {
|
|
|
- let extraParams = [];
|
|
|
- if(this.handleData.compressOutType == 1 || imgInfo.type.toLowerCase() != 'png'){
|
|
|
- if(this.handleData.compressOutType == 1 || imgInfo.type.toLowerCase() == 'jpg' || imgInfo.type.toLowerCase() == 'JPEG'){
|
|
|
- let sizeOld = fs.statSync(imgInfo.path).size;
|
|
|
-
|
|
|
- extraParams=['-resize',this.handleData.compressScaling+'%','-define','jpeg:dct-method=fastest','-define','jpeg:extent='+sizeOld,'-sampling-factor','4:2:0','-strip','-interlace','Plane','-background','white','-flatten','-alpha','off','-quality',this.handleData.quality+'%']
|
|
|
- }else{
|
|
|
- extraParams=['+dither','-strip','-colors',256*(this.handleData.quality/90),'-depth',8]
|
|
|
- }
|
|
|
-
|
|
|
- electronApi.spawnExec(['convert.exe','-monitor',...extraParams,imgInfo.path, newPath],{
|
|
|
- stderr:(data) => {
|
|
|
- let str = data.toString();
|
|
|
- const regexDuration = /Load.*?,(.*?)%/;
|
|
|
- const regexDuration2 = /Save.*?,(.*?)%/;
|
|
|
- const res = regexDuration.exec(str);
|
|
|
- const res2 = regexDuration2.exec(str);
|
|
|
-
|
|
|
- let p1 = 0;
|
|
|
- let p2 = 0;
|
|
|
- if(res && res[1]){
|
|
|
- p1 = parseInt(res[1]);
|
|
|
- if(p1 > 0){
|
|
|
- imgInfo.percent = Math.round(p1/2);
|
|
|
- }
|
|
|
- }else{
|
|
|
- if(res2 && res2[1]){
|
|
|
- p2 = parseInt(res2[1]);
|
|
|
- }
|
|
|
- if(p2 > 0){
|
|
|
- imgInfo.percent = Math.round(50+(p2/2));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(this.imgList[index]){
|
|
|
- this.imgList.splice(index,1,imgInfo);
|
|
|
- }
|
|
|
- }
|
|
|
- }).then(res => {
|
|
|
- setTimeout(() => {
|
|
|
- if(this.imgList[index]){
|
|
|
- imgInfo.percent = 100;
|
|
|
- this.imgList.splice(index, 1, imgInfo);
|
|
|
- }else{
|
|
|
- reject({type:this.menuIndex,index,err:'用户强制终止!'});
|
|
|
- }
|
|
|
- }, 150)
|
|
|
-
|
|
|
- //未购买 添加系统水印
|
|
|
- this.addWatermark(index,imgInfo,newPath);
|
|
|
- resolve({type:this.menuIndex,index, imgInfo});
|
|
|
- }).catch(err => {
|
|
|
- err.stdout = err.stdout.toString();
|
|
|
- err.stderr = err.stderr.toString();
|
|
|
-
|
|
|
- reject({type:this.menuIndex,index,err});
|
|
|
- });
|
|
|
- }else{
|
|
|
- // 复制文件到缓存目录 生成结束后输出到目标文件夹
|
|
|
- let tmpPath = os.tmpdir()+separator+'YSI_'+Math.random();
|
|
|
- let tmpPath2 = os.tmpdir()+separator+'YSO_'+Math.random() + '.png';
|
|
|
-
|
|
|
- fs.copyFileSync(imgInfo.path,tmpPath);
|
|
|
-
|
|
|
- // 添加系统水印
|
|
|
- await this.addWatermark(index,imgInfo,tmpPath);
|
|
|
-
|
|
|
- electronApi.spawnExec(['pngquant.exe',tmpPath,'-f','-v','--strip','--quality',this.handleData.quality,'-o',tmpPath2],{
|
|
|
- stderr:(data) => {
|
|
|
- let str = data.toString();
|
|
|
- const regexDuration = /selecting colors...(.*?)%/;
|
|
|
- const res = regexDuration.exec(str);
|
|
|
- if(res && res[1]){
|
|
|
- imgInfo.percent = Math.round(parseInt(res[1])-2);
|
|
|
- }
|
|
|
-
|
|
|
- if(this.imgList[index]){
|
|
|
- this.imgList.splice(index,1,imgInfo);
|
|
|
- }
|
|
|
- }
|
|
|
- }).then((res) => {
|
|
|
- setTimeout(() => {
|
|
|
- if(this.imgList[index]){
|
|
|
- imgInfo.percent = 100;
|
|
|
- this.imgList.splice(index, 1, imgInfo);
|
|
|
- }else{
|
|
|
- reject({type:this.menuIndex,index,err:'用户强制终止!'});
|
|
|
- }
|
|
|
- }, 150)
|
|
|
-
|
|
|
- // 复制
|
|
|
- fs.copyFileSync(tmpPath2,newPath);
|
|
|
-
|
|
|
- resolve({type:this.menuIndex,index, imgInfo});
|
|
|
- }).catch(err => {
|
|
|
- err.stdout = err.stdout.toString();
|
|
|
- err.stderr = err.stderr.toString();
|
|
|
-
|
|
|
- // 如果失败,重新使用推荐的最小值来转换
|
|
|
- // const regexQ = /\(Q=(.*?)\)/g;
|
|
|
- // const res2 = regexQ.exec(err.stderr);
|
|
|
- // const quality = res2[1];
|
|
|
- this.pngFailedExec(index,tmpPath,tmpPath2,imgInfo,newPath).then(rr => {
|
|
|
- resolve({type:this.menuIndex,index, imgInfo});
|
|
|
- }).catch(err2 => {
|
|
|
- reject({type:this.menuIndex,index,err});
|
|
|
- });
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
- break;
|
|
|
-
|
|
|
- case 3: // 更改尺寸
|
|
|
- task = new Promise((resolve,reject) => {
|
|
|
- let params = [];
|
|
|
- let extraParams = [];
|
|
|
-
|
|
|
- if(this.handleData.rotateValue != 0){
|
|
|
- extraParams = ['-rotate',this.handleData.rotateValue];
|
|
|
- }
|
|
|
-
|
|
|
- let vflipParams = [];
|
|
|
- let hflipParams = [];
|
|
|
- if(this.handleData.vflip){
|
|
|
- vflipParams = ['-flip'];
|
|
|
- }
|
|
|
- if(this.handleData.hflip){
|
|
|
- hflipParams = ['-flop'];
|
|
|
- }
|
|
|
-
|
|
|
- if (this.handleData.sizeType == 1) { // 按照比列缩放
|
|
|
- params = [
|
|
|
- 'convert.exe',
|
|
|
- '-monitor',
|
|
|
- '-resize',
|
|
|
- this.handleData.scaling+'%',
|
|
|
- ...extraParams,
|
|
|
- ...vflipParams,
|
|
|
- ...hflipParams,
|
|
|
- imgInfo.path,
|
|
|
- newPath
|
|
|
- ];
|
|
|
- } else { // 按照尺寸缩放
|
|
|
- params = [
|
|
|
- 'convert.exe',
|
|
|
- '-monitor',
|
|
|
- '-resize',
|
|
|
- `${Number(this.handleData.width)}x${Number(this.handleData.height)}!`,
|
|
|
- ...extraParams,
|
|
|
- ...vflipParams,
|
|
|
- ...hflipParams,
|
|
|
- imgInfo.path,
|
|
|
- newPath
|
|
|
- ];
|
|
|
- }
|
|
|
-
|
|
|
- electronApi.spawnExec(params,{
|
|
|
- stderr:(data) => {
|
|
|
- let str = data.toString();
|
|
|
- const regexDuration = /Load.*?,(.*?)%/;
|
|
|
- const regexDuration2 = /Save.*?,(.*?)%/;
|
|
|
-
|
|
|
- const res = regexDuration.exec(str);
|
|
|
- const res2 = regexDuration2.exec(str);
|
|
|
-
|
|
|
- let p1 = 0;
|
|
|
- let p2 = 0;
|
|
|
- if(res && res[1]){
|
|
|
- p1 = parseInt(res[1]);
|
|
|
- if(p1 > 0){
|
|
|
- imgInfo.percent = Math.round(p1/2);
|
|
|
- }
|
|
|
- }else{
|
|
|
- if(res2 && res2[1]){
|
|
|
- p2 = parseInt(res2[1]);
|
|
|
- }
|
|
|
- if(p2 > 0){
|
|
|
- imgInfo.percent = Math.round(50+(p2/2));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(this.imgList[index]){
|
|
|
- this.imgList.splice(index,1,imgInfo);
|
|
|
- }
|
|
|
- }
|
|
|
- }).then(res => {
|
|
|
- setTimeout(() => {
|
|
|
- if(this.imgList[index]){
|
|
|
- imgInfo.percent = 100;
|
|
|
- this.imgList.splice(index, 1, imgInfo);
|
|
|
- }else{
|
|
|
- reject({type:this.menuIndex,index,err:'用户强制终止!'});
|
|
|
- }
|
|
|
- }, 150)
|
|
|
-
|
|
|
- //未购买 添加系统水印
|
|
|
- this.addWatermark(index,imgInfo,newPath);
|
|
|
-
|
|
|
- resolve({type:this.menuIndex,index, img});
|
|
|
- }).catch(err => {
|
|
|
- reject({type:this.menuIndex,index,err});
|
|
|
- });
|
|
|
- })
|
|
|
-
|
|
|
- break;
|
|
|
-
|
|
|
- case 5: // 添加水印
|
|
|
- if (this.handleData.watermarkType == '1') { // 文字水印
|
|
|
- if(this.handleData.fonts == ''){
|
|
|
- this.$message({message: '请选择字体', type: 'warning'});
|
|
|
- this.imgLoading = false;
|
|
|
- break;
|
|
|
- }else{
|
|
|
- task = this.textWatermark(index, imgInfo, newPath,!img);
|
|
|
- }
|
|
|
- } else if (this.handleData.watermarkType == '2') { // 图片水印
|
|
|
- // 平铺功能去掉
|
|
|
- this.handleData.watermarkStyle = 1;
|
|
|
-
|
|
|
- if(!this.handleData.watermarkImgPath){
|
|
|
- this.$message({message: '请上传图片水印', type: 'warning'});
|
|
|
- this.imgLoading = false;
|
|
|
- break;
|
|
|
- }else{
|
|
|
- task = this.imgWatermark(index, imgInfo, newPath,!img);
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- return task;
|
|
|
- },
|
|
|
- //如果转换失败,则使用推荐的Quaity转换图片
|
|
|
- pngFailedExec(index,tmpPath,tmpPath2,imgInfo,newPath){
|
|
|
- return new Promise((resolve,reject) => {
|
|
|
- electronApi.spawnExec(['pngquant.exe',tmpPath,'-f','-v','--strip','-o',tmpPath2],{
|
|
|
- stderr:(data) => {
|
|
|
- let str = data.toString();
|
|
|
- const regexDuration = /selecting colors...(.*?)%/;
|
|
|
- const res = regexDuration.exec(str);
|
|
|
- if(res && res[1]){
|
|
|
- imgInfo.percent = Math.round(parseInt(res[1])-2);
|
|
|
- }
|
|
|
-
|
|
|
- if(this.imgList[index]){
|
|
|
- this.imgList.splice(index,1,imgInfo);
|
|
|
- }
|
|
|
- }
|
|
|
- }).then((res) => {
|
|
|
- setTimeout(() => {
|
|
|
- if(this.imgList[index]){
|
|
|
- imgInfo.percent = 100;
|
|
|
- this.imgList.splice(index, 1, imgInfo);
|
|
|
- }else{
|
|
|
- reject({type:this.menuIndex,index,err:'用户强制终止!'});
|
|
|
- }
|
|
|
- }, 150)
|
|
|
-
|
|
|
- // 复制
|
|
|
- fs.copyFileSync(tmpPath2,newPath);
|
|
|
-
|
|
|
- resolve({type:this.menuIndex,index, imgInfo});
|
|
|
- }).catch(err => {
|
|
|
- err.stdout = err.stdout && err.stdout.toString();
|
|
|
- err.stderr = err.stderr && err.stderr.toString();
|
|
|
-
|
|
|
- reject({type:this.menuIndex,index,err});
|
|
|
- });
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- // scaleWidthChange
|
|
|
- scaleWidthChange(e){
|
|
|
- let scale = Number(this.imgInfo.originalWidth) / Number(this.imgInfo.originalHeight);
|
|
|
- if(this.handleData.lockScale){ // 锁定比例
|
|
|
- this.handleData.height = Math.round(this.handleData.width / scale);
|
|
|
- }
|
|
|
- },
|
|
|
- // scaleHeightChange
|
|
|
- scaleHeightChange(e){
|
|
|
- let scale = Number(this.imgInfo.originalWidth) / Number(this.imgInfo.originalHeight);
|
|
|
- if(this.handleData.lockScale){ // 锁定比例
|
|
|
- this.handleData.width = Math.round(this.handleData.height * scale);
|
|
|
- }
|
|
|
- },
|
|
|
- // 文字水印
|
|
|
- async textWatermark(index, imgInfo, newPath,isPreview=false) {
|
|
|
- let m = this.handleData.watermarkDensityX <= 0 ? 3 : this.handleData.watermarkDensityX;
|
|
|
- let n = this.handleData.watermarkDensityY <= 0 ? 3 : this.handleData.watermarkDensityY;
|
|
|
-
|
|
|
- return new Promise((resolve,reject) => {
|
|
|
- let tmpPath = os.tmpdir()+separator+'water_font_'+Math.random()+'.png';
|
|
|
- let params = [
|
|
|
- 'convert.exe',
|
|
|
- '-monitor',
|
|
|
- '-background',
|
|
|
- 'none',
|
|
|
- '-fill',
|
|
|
- this.handleData.watermarkColor,
|
|
|
- '-font',
|
|
|
- this.handleData.fonts.toString(),
|
|
|
- '-pointsize',
|
|
|
- this.handleData.watermarkFont,
|
|
|
- '-alpha', 'set', '-channel', 'A', '-evaluate', 'Multiply', this.handleData.watermarkImgOpactiy/100, '+channel', // 透明度
|
|
|
- '-rotate',
|
|
|
- this.handleData.rotate,
|
|
|
- 'label:' + (this.handleData.watermarkValue ? this.handleData.watermarkValue : pjson.softInfo.softName),
|
|
|
- '-gravity',
|
|
|
- 'center',
|
|
|
- '-extent',
|
|
|
- this.handleData.watermarkStyle == 2 ? (imgInfo.width/m)+'x'+(imgInfo.height/n) : '100%',
|
|
|
- tmpPath
|
|
|
- ];
|
|
|
-
|
|
|
- electronApi.spawnExec(params,{stderr:(data) => { imgInfo.percent = 30;this.imgList.splice(index,1,imgInfo);}}).then(async (res) => {
|
|
|
- // 生成平铺水印图片
|
|
|
- if(this.handleData.watermarkStyle == 2){ // 平铺
|
|
|
- let tmpPath2 = os.tmpdir()+separator+'water_pu_'+Math.random()+'.png';
|
|
|
- let params2 = [
|
|
|
- 'convert.exe',
|
|
|
- '-monitor',
|
|
|
- tmpPath,
|
|
|
- '-write',
|
|
|
- 'mpr:tiler',
|
|
|
- '+delete',
|
|
|
- '-size',
|
|
|
- imgInfo.width+'x'+imgInfo.height,
|
|
|
- 'tile:mpr:tiler',
|
|
|
- tmpPath2
|
|
|
- ];
|
|
|
- await electronApi.spawnExec(params2,{stderr:(data) => { imgInfo.percent=60;this.imgList.splice(index,1,imgInfo);}}).then(async (res2) => {
|
|
|
- await this.waterComposite(index, imgInfo, newPath, tmpPath2);
|
|
|
- if(fs.existsSync(tmpPath)){
|
|
|
- fs.unlinkSync(tmpPath);
|
|
|
- }
|
|
|
- })
|
|
|
- }else{
|
|
|
- await this.waterComposite(index, imgInfo, newPath, tmpPath);
|
|
|
- }
|
|
|
-
|
|
|
- if(isPreview){ // 预览状态
|
|
|
- electronApi.fileStream(newPath).then(buffer => {
|
|
|
- this.imgSrc = "data:image/png;base64,"+buffer.toString('base64');
|
|
|
- this.imgLoading = false;
|
|
|
- }).catch(err => {
|
|
|
- this.imgLoading = false;
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- resolve({type:this.menuIndex, index:index, info:imgInfo});
|
|
|
- }).catch(err => {
|
|
|
- reject({type:this.menuIndex, index:index, err: err});
|
|
|
- });
|
|
|
- });
|
|
|
- },
|
|
|
- // 图片水印
|
|
|
- async imgWatermark(index, imgInfo, newPath,isPreview=false) {
|
|
|
- let m = this.handleData.watermarkDensityX <= 0 ? 3 : this.handleData.watermarkDensityX;
|
|
|
- let n = this.handleData.watermarkDensityY <= 0 ? 3 : this.handleData.watermarkDensityY;
|
|
|
-
|
|
|
- return new Promise((resolve,reject) => {
|
|
|
- let tmpPath = os.tmpdir()+separator+'water_img_'+Math.random()+'.png';
|
|
|
-
|
|
|
- let params = [
|
|
|
- 'convert.exe',
|
|
|
- '-monitor',
|
|
|
- '-background',
|
|
|
- 'none',
|
|
|
- '-resize',
|
|
|
- `${Number(this.handleData.watermarkImgSize)}%`,
|
|
|
- '-alpha', 'set', '-channel', 'A', '-evaluate', 'Multiply', this.handleData.watermarkImgOpactiy/100, '+channel', // 透明度
|
|
|
- '-rotate',
|
|
|
- this.handleData.watermarkImgRotate,
|
|
|
- '-gravity',
|
|
|
- 'center',
|
|
|
- '-extent',
|
|
|
- this.handleData.watermarkStyle == 2 ? (imgInfo.width/m)+'x'+(imgInfo.height/n) : '100%',
|
|
|
- this.handleData.watermarkImgPath,
|
|
|
- tmpPath
|
|
|
- ];
|
|
|
-
|
|
|
- electronApi.spawnExec(params).then(async (res) => {
|
|
|
- // 生成平铺水印图片
|
|
|
- if(this.handleData.watermarkStyle == 2){ // 平铺
|
|
|
- let tmpPath2 = os.tmpdir()+separator+'water_pu_'+Math.random()+'.png';
|
|
|
- let params2 = [
|
|
|
- 'convert.exe',
|
|
|
- '-monitor',
|
|
|
- tmpPath,
|
|
|
- '-write',
|
|
|
- 'mpr:tiler',
|
|
|
- '+delete',
|
|
|
- '-size',
|
|
|
- imgInfo.width+'x'+imgInfo.height,
|
|
|
- 'tile:mpr:tiler',
|
|
|
- tmpPath2
|
|
|
- ];
|
|
|
- await electronApi.spawnExec(params2,{stderr:(data) => { imgInfo.percent=60;this.imgList.splice(index,1,imgInfo);}}).then(async (res2) => {
|
|
|
- await this.waterComposite(index, imgInfo, newPath, tmpPath2);
|
|
|
- if(fs.existsSync(tmpPath)){
|
|
|
- fs.unlinkSync(tmpPath);
|
|
|
- }
|
|
|
- })
|
|
|
- }else{
|
|
|
- await this.waterComposite(index, imgInfo, newPath, tmpPath);
|
|
|
- }
|
|
|
-
|
|
|
- if(isPreview){ // 预览状态
|
|
|
- electronApi.fileStream(newPath).then(buffer => {
|
|
|
- this.imgSrc = "data:image/png;base64,"+buffer.toString('base64');
|
|
|
- this.imgLoading = false;
|
|
|
- }).catch(err => {
|
|
|
- this.imgLoading = false;
|
|
|
- })
|
|
|
- }
|
|
|
-
|
|
|
- resolve({type:this.menuIndex, index:index, info:imgInfo});
|
|
|
- }).catch(err => {
|
|
|
- reject({type:this.menuIndex, index:index, err: err});
|
|
|
- });
|
|
|
- });
|
|
|
- },
|
|
|
- async waterComposite(index, imgInfo, newPath,waterImg){
|
|
|
- let params2 = [
|
|
|
- 'convert.exe',
|
|
|
- '-monitor',
|
|
|
- imgInfo.path,
|
|
|
- waterImg,
|
|
|
- '-gravity',
|
|
|
- this.handleData.watermarkStyle == 2 ? 'Center' : this.handleData.watermarkPosition,
|
|
|
- '-geometry',
|
|
|
- '+'+this.handleData.watermarkX+'+'+this.handleData.watermarkY,
|
|
|
- '-composite',
|
|
|
- newPath
|
|
|
- ];
|
|
|
-
|
|
|
- await electronApi.spawnExec(params2,{
|
|
|
- stderr:(data) => {
|
|
|
- let percent = 0;
|
|
|
- let str = data.toString();
|
|
|
- const regexDuration = /Load.*?,(.*?)%/;
|
|
|
- const regexDuration2 = /Resize.*?,(.*?)%/;
|
|
|
-
|
|
|
- const res = regexDuration.exec(str);
|
|
|
- const res2 = regexDuration2.exec(str);
|
|
|
-
|
|
|
- let p1 = 0;
|
|
|
- let p2 = 0;
|
|
|
- if(res && res[1]){
|
|
|
- p1 = parseInt(res[1]);
|
|
|
- if(p1 > 0){
|
|
|
- imgInfo.percent = Math.round(p1/2);
|
|
|
- }
|
|
|
- }else{
|
|
|
- if(res2 && res2[1]){
|
|
|
- p2 = parseInt(res2[1]);
|
|
|
- }
|
|
|
- if(p2 > 0){
|
|
|
- imgInfo.percent = Math.round(50+(p2/2));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if(this.handleData.watermarkStyle == 2){ // 平铺
|
|
|
- imgInfo.percent = 60 + Math.round(percent*0.4);
|
|
|
- }else{
|
|
|
- imgInfo.percent = percent;
|
|
|
- }
|
|
|
-
|
|
|
- if(this.imgList[index]){
|
|
|
- this.imgList.splice(index,1,imgInfo);
|
|
|
- }
|
|
|
- },
|
|
|
- }).then(res2 => {
|
|
|
- setTimeout(() => {
|
|
|
- if(this.imgList[index]){
|
|
|
- imgInfo.percent = 100;
|
|
|
- this.imgList.splice(index, 1, imgInfo);
|
|
|
- if(fs.existsSync(waterImg)){
|
|
|
- fs.unlinkSync(waterImg);
|
|
|
- }
|
|
|
- }else{
|
|
|
- reject({type:this.menuIndex,index,err:'用户强制终止!'});
|
|
|
- }
|
|
|
- }, 150)
|
|
|
-
|
|
|
- //未购买 添加系统水印
|
|
|
- this.addWatermark(index,{...imgInfo,path:newPath},newPath);
|
|
|
- });
|
|
|
- },
|
|
|
- // 初始化系统水印图片
|
|
|
- async initSysWater(imgInfo){
|
|
|
- return new Promise((resolve,reject) => {
|
|
|
- let fontSize = 40;
|
|
|
- let width = imgInfo.width;
|
|
|
- if(this.menuIndex == 3){
|
|
|
- width = width * (this.handleData.scaling / 100);
|
|
|
- }
|
|
|
- if (width < 500) {
|
|
|
- fontSize = 16;
|
|
|
- } else if (width < 1000) {
|
|
|
- fontSize = 28
|
|
|
- }else if(width < 2000){
|
|
|
- fontSize = 40;
|
|
|
- }else if(width < 3000){
|
|
|
- fontSize = 100;
|
|
|
- }else{
|
|
|
- fontSize = 220;
|
|
|
- }
|
|
|
-
|
|
|
- let sysDefaultTmpPath = os.tmpdir()+separator+'water_xy_'+fontSize+'.png';
|
|
|
-
|
|
|
- let params = [
|
|
|
- 'convert.exe',
|
|
|
- '-monitor',
|
|
|
- '-background',
|
|
|
- 'none',
|
|
|
- '-fill',
|
|
|
- 'rgba(0,0,0,0.8)',
|
|
|
- '-font',
|
|
|
- this.defaultFont,
|
|
|
- '-pointsize',
|
|
|
- fontSize,
|
|
|
- 'label:https://www.xingyousoft.com',
|
|
|
- sysDefaultTmpPath
|
|
|
- ];
|
|
|
-
|
|
|
- if(fs.existsSync(sysDefaultTmpPath)){
|
|
|
- resolve(sysDefaultTmpPath)
|
|
|
- }else{
|
|
|
- electronApi.spawnExec(params).then((res) => {
|
|
|
- resolve(sysDefaultTmpPath)
|
|
|
- }).catch(err => {
|
|
|
- reject(err)
|
|
|
- });
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
- // 添加默认水印
|
|
|
- async addWatermark(index,imgInfo,newPath) {
|
|
|
- return new Promise(async(resolve,reject) => {
|
|
|
- await this.checkAuthority();
|
|
|
- if (this.authority.isAuthority) {
|
|
|
- // 有权限,则不做任何操作
|
|
|
- resolve(true)
|
|
|
- } else {
|
|
|
- this.initSysWater(imgInfo).then(re => {
|
|
|
- let sysDefaultTmpPath = re;
|
|
|
- // 合并系统水印
|
|
|
- let params2 = [
|
|
|
- 'convert.exe',
|
|
|
- '-monitor',
|
|
|
- newPath,
|
|
|
- sysDefaultTmpPath,
|
|
|
- '-gravity',
|
|
|
- 'center',
|
|
|
- '-composite',
|
|
|
- newPath
|
|
|
- ];
|
|
|
-
|
|
|
- electronApi.spawnExec(params2).then(result => {
|
|
|
- resolve(result)
|
|
|
- }).catch(err => {
|
|
|
- reject(err)
|
|
|
- });
|
|
|
- }).catch(err2 =>{
|
|
|
- reject({err2})
|
|
|
- });
|
|
|
- }
|
|
|
- })
|
|
|
- },
|
|
|
- deleteSysWtater(){
|
|
|
- let w1 = os.tmpdir()+separator+'water_xy_16.png';
|
|
|
- let w2 = os.tmpdir()+separator+'water_xy_28.png';
|
|
|
- let w3 = os.tmpdir()+separator+'water_xy_40.png';
|
|
|
- let w4 = os.tmpdir()+separator+'water_xy_100.png';
|
|
|
-
|
|
|
- if(fs.existsSync(w1)){
|
|
|
- fs.unlinkSync(w1);
|
|
|
- }
|
|
|
-
|
|
|
- if(fs.existsSync(w2)){
|
|
|
- fs.unlinkSync(w2);
|
|
|
- }
|
|
|
-
|
|
|
- if(fs.existsSync(w3)){
|
|
|
- fs.unlinkSync(w3);
|
|
|
- }
|
|
|
-
|
|
|
- if(fs.existsSync(w4)){
|
|
|
- fs.unlinkSync(w4);
|
|
|
- }
|
|
|
- },
|
|
|
-
|
|
|
- // 删除文件
|
|
|
- delImgFile(rowIndex){
|
|
|
- this.$confirm('确认删除这张图片吗?', '提示', {
|
|
|
- confirmButtonText: '确定',
|
|
|
- cancelButtonText: '取消',
|
|
|
- type: 'warning'
|
|
|
- }).then(() => {
|
|
|
- this.imgList.splice(rowIndex, 1);
|
|
|
- if (this.imgList.length == 0) {
|
|
|
- this.clearList();
|
|
|
- }
|
|
|
- }).catch(() => {
|
|
|
-
|
|
|
- });
|
|
|
- },
|
|
|
-
|
|
|
- }
|
|
|
-};
|
|
|
-</script>
|
|
|
-
|
|
|
-<style lang="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;
|
|
|
- }
|
|
|
-
|
|
|
- .title-flex{
|
|
|
- display: flex;
|
|
|
- flex-wrap: nowrap;
|
|
|
- justify-content: flex-start;
|
|
|
- }
|
|
|
- .demo-spin-icon-load{
|
|
|
- animation: ani-demo-spin 1s linear infinite;
|
|
|
- }
|
|
|
-
|
|
|
- .line-density{
|
|
|
- display: inline-block;
|
|
|
- width: calc(100% - 74px);
|
|
|
- }
|
|
|
-
|
|
|
- .handle-item{
|
|
|
- .handle-label{
|
|
|
- width: 70px;
|
|
|
- }
|
|
|
- .ivu-input-number-handler-wrap{
|
|
|
- opacity: 1;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .set-height{
|
|
|
- height: 100%;
|
|
|
- }
|
|
|
-
|
|
|
- .merge-flex{
|
|
|
- padding: 10px;
|
|
|
- height: 100%;
|
|
|
- display: flex;
|
|
|
- flex-wrap: nowrap;
|
|
|
- justify-content: flex-start;
|
|
|
-
|
|
|
- .merge-content{
|
|
|
- width: calc(100% - 140px);
|
|
|
- height: 100%;
|
|
|
- }
|
|
|
-
|
|
|
- .merge-top{
|
|
|
- overflow: hidden;
|
|
|
- margin-bottom: 10px;
|
|
|
- display: flex;
|
|
|
- flex-wrap: nowrap;
|
|
|
- justify-content: space-between;
|
|
|
- }
|
|
|
-
|
|
|
- .action-right{
|
|
|
- width: 70px;
|
|
|
- display: flex;
|
|
|
- flex-wrap: nowrap;
|
|
|
- justify-content: space-between;
|
|
|
- line-height: 1;
|
|
|
- cursor: pointer;
|
|
|
-
|
|
|
- .action-ritem:hover{
|
|
|
- color: #ce0000;
|
|
|
- }
|
|
|
-
|
|
|
- .iconfont{
|
|
|
- font-size: 20px;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .merge-left{
|
|
|
- width: 110px;
|
|
|
- text-align: center;
|
|
|
- height: 100%;
|
|
|
- overflow-y: auto;
|
|
|
- }
|
|
|
- .img-area{
|
|
|
- width: 90px;
|
|
|
- height: 60px;
|
|
|
- text-align: center;
|
|
|
- line-height: 56px;
|
|
|
- border: 1px solid #ddd;
|
|
|
- }
|
|
|
- .merge-scroll{
|
|
|
- display: flex;
|
|
|
- flex-wrap: nowrap;
|
|
|
- overflow: hidden auto;
|
|
|
- position: relative;
|
|
|
- width: 130px;
|
|
|
- flex-direction: column;
|
|
|
- margin-right: 8px;
|
|
|
- }
|
|
|
- .merge-item{
|
|
|
- width: 90px;
|
|
|
- margin-bottom: 10px;
|
|
|
- }
|
|
|
- .merge-imgdel{
|
|
|
- position: absolute;
|
|
|
- right: -8px;
|
|
|
- top: 0px;
|
|
|
- font-size: 12px;
|
|
|
- padding: 2px;
|
|
|
- background-color: #ccc;
|
|
|
- border-radius: 50%;
|
|
|
- color: #fff;
|
|
|
- cursor: pointer;
|
|
|
- &:hover{
|
|
|
- background-color: #ce0000;
|
|
|
- }
|
|
|
- }
|
|
|
- .mergelist-img{
|
|
|
- max-width: 100%;
|
|
|
- max-height: 100%;
|
|
|
- vertical-align: middle;
|
|
|
- }
|
|
|
- .merge-name{
|
|
|
- overflow: hidden;
|
|
|
- text-overflow:ellipsis;
|
|
|
- white-space: nowrap;
|
|
|
- margin-bottom: 5px;
|
|
|
- }
|
|
|
- .mer-title{
|
|
|
- font-weight: 600;
|
|
|
- margin-bottom: 10px;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- ::-webkit-scrollbar {
|
|
|
- /*滚动条整体样式*/
|
|
|
- width: 6px; /*高宽分别对应横竖滚动条的尺寸*/
|
|
|
- height: 6px;
|
|
|
- }
|
|
|
- ::-webkit-scrollbar-thumb {
|
|
|
- /*滚动条里面小方块*/
|
|
|
- border-radius: 10px;
|
|
|
- box-shadow: inset 0 0 5px rgba(97, 184, 179, 0.1);
|
|
|
- background: #666;
|
|
|
- }
|
|
|
- ::-webkit-scrollbar-track {
|
|
|
- /*滚动条里面轨道*/
|
|
|
- box-shadow: inset 0 0 5px rgba(87, 175, 187, 0.1);
|
|
|
- border-radius: 10px;
|
|
|
- background: #ededed;
|
|
|
- }
|
|
|
-
|
|
|
- .mlist-scroll{
|
|
|
- overflow: auto;
|
|
|
- background-color: #fff;
|
|
|
- padding: 5px;
|
|
|
- height: calc(100% - 45px);
|
|
|
-
|
|
|
- &.bgmini{
|
|
|
- background: url('../assets/image/bgmini.png');
|
|
|
- }
|
|
|
-
|
|
|
- .mlist-content{
|
|
|
- width: 50%;
|
|
|
- position: relative;
|
|
|
- box-shadow: 2px 2px 6px #ddd, -2px -2px 6px #ddd;
|
|
|
- margin: auto;
|
|
|
- transform-origin: 50% 0;
|
|
|
- }
|
|
|
- .mlist-area{
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- display: flex;
|
|
|
- flex-wrap: nowrap;
|
|
|
- flex-direction: column;
|
|
|
- justify-content: space-between;
|
|
|
- }
|
|
|
- .merge-row{
|
|
|
- display: flex;
|
|
|
- flex-wrap: nowrap;
|
|
|
- justify-content: space-between;
|
|
|
- width: 100%;
|
|
|
- }
|
|
|
- .merge-col{
|
|
|
- text-align: center;
|
|
|
- overflow: hidden;
|
|
|
- position: relative;
|
|
|
- &:hover{
|
|
|
- // border: 2px solid #2b83e0;
|
|
|
- }
|
|
|
- }
|
|
|
- .merge-img{
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- cursor:move;
|
|
|
- }
|
|
|
- .merge-img2{
|
|
|
- max-width: 100%;
|
|
|
- max-height: 100%;
|
|
|
- vertical-align: middle;
|
|
|
- position: absolute;
|
|
|
- top: 0 !important;
|
|
|
- left: 0 !important;
|
|
|
- right: 0 !important;
|
|
|
- bottom: 0 !important;
|
|
|
- margin: auto;
|
|
|
- }
|
|
|
- .merge-add{
|
|
|
- font-size: 50px;
|
|
|
- border: 1px solid #ccc;
|
|
|
- height: 100%;
|
|
|
- background-color: #fafafa;
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- cursor: pointer;
|
|
|
- &:hover{
|
|
|
- background-color: #f3f3f3;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .disnone{
|
|
|
- display: none;
|
|
|
- }
|
|
|
-
|
|
|
- // 横图
|
|
|
- .horizontal-scroll{
|
|
|
- width: 80%;
|
|
|
- margin: auto;
|
|
|
- height: 250px;
|
|
|
- margin-top: 10%;
|
|
|
- box-shadow: 2px 2px 6px #ddd, -2px -2px 6px #ddd;
|
|
|
- overflow: auto;
|
|
|
- box-sizing: content-box;
|
|
|
- }
|
|
|
- .horizontal-content{
|
|
|
- height: 100%;
|
|
|
- display: flex;
|
|
|
- flex-wrap: nowrap;
|
|
|
- justify-content: flex-start;
|
|
|
- .horizontal-item{
|
|
|
- display: flex;
|
|
|
- }
|
|
|
- .horizontal-area{
|
|
|
- display: inline-block;
|
|
|
- height: 100%;
|
|
|
- }
|
|
|
- .horizontal-img{
|
|
|
- height: 100%;
|
|
|
- box-sizing: content-box;
|
|
|
- flex-shrink: 0;
|
|
|
- &:last-child{
|
|
|
- margin-right: 0 !important;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 竖图
|
|
|
- .vertical-content{
|
|
|
- width: 250px;
|
|
|
- margin: auto;
|
|
|
- box-shadow: 2px 2px 6px #ddd, -2px -2px 6px #ddd;
|
|
|
- box-sizing: content-box;
|
|
|
- .vertical-img{
|
|
|
- width: 100%;
|
|
|
- display: inherit;
|
|
|
- &:last-child{
|
|
|
- margin-bottom: 0 !important;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .i-fanzhuan{
|
|
|
- font-size: 25px;
|
|
|
- margin-right: 20px;
|
|
|
- cursor: pointer;
|
|
|
-
|
|
|
- &:hover,&.active{
|
|
|
- color: #ce0000;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .flex-crop{
|
|
|
- display: flex;
|
|
|
- flex-wrap: wrap;
|
|
|
- justify-content: space-between;
|
|
|
-
|
|
|
- .crop-button{
|
|
|
- width: 65px;
|
|
|
- margin: 10px 0 !important;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .show-preview{
|
|
|
- margin: auto;
|
|
|
- }
|
|
|
-
|
|
|
- .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;
|
|
|
- }
|
|
|
-
|
|
|
- .el-aside,.el-menu{
|
|
|
- border-right: none !important;
|
|
|
- }
|
|
|
-
|
|
|
- .vxebtn-del{
|
|
|
- position: absolute !important;
|
|
|
- right: 0;
|
|
|
- top: 10px;
|
|
|
- color: #F56C6C !important;
|
|
|
- z-index: 2;
|
|
|
- }
|
|
|
-
|
|
|
- .m-image{
|
|
|
- width: 25px;
|
|
|
- margin-right: 5px;
|
|
|
- }
|
|
|
-
|
|
|
- .el-menu-item.is-active{
|
|
|
- font-weight: 800;
|
|
|
- font-size: 16px;
|
|
|
- }
|
|
|
-
|
|
|
- .el-menu-item:hover{
|
|
|
- font-weight: 800;
|
|
|
- font-size: 16px;
|
|
|
- }
|
|
|
-
|
|
|
- .file-area-pos{
|
|
|
- position: absolute;
|
|
|
- width: 400px;
|
|
|
- height: 330px;
|
|
|
- top: 0;
|
|
|
- bottom: 0;
|
|
|
- left: 0;
|
|
|
- right: 0;
|
|
|
- margin: auto;
|
|
|
- }
|
|
|
-</style>
|