|
@@ -45,14 +45,22 @@
|
|
|
<img src="../assets/image/m-name.png" class="m-image"/>
|
|
|
<span slot="title">批量命名</span>
|
|
|
</el-menu-item>
|
|
|
+ <el-menu-item index="8" @click="setMenuIndex(8)">
|
|
|
+ <img src="../assets/image/m-pinjie.png" class="m-image"/>
|
|
|
+ <span slot="title">图片拼接</span>
|
|
|
+ </el-menu-item>
|
|
|
<el-menu-item index="10" @click="setMenuIndex(10)">
|
|
|
<img src="../assets/image/m-caijian.png" class="m-image"/>
|
|
|
<span slot="title">批量裁剪</span>
|
|
|
</el-menu-item>
|
|
|
- <el-menu-item index="8" @click="setMenuIndex(8)">
|
|
|
- <img src="../assets/image/m-pinjie.png" class="m-image"/>
|
|
|
- <span slot="title">图片拼接</span>
|
|
|
+ <el-menu-item index="12" @click="setMenuIndex(12)">
|
|
|
+ <img src="../assets/image/m-feige.png" class="m-image"/>
|
|
|
+ <span slot="title">图片分割</span>
|
|
|
</el-menu-item>
|
|
|
+ <!-- <el-menu-item index="13" @click="setMenuIndex(13)">
|
|
|
+ <img src="../assets/image/m-web.png" class="m-image"/>
|
|
|
+ <span slot="title">网页转图片</span>
|
|
|
+ </el-menu-item> -->
|
|
|
</el-menu>
|
|
|
</el-aside>
|
|
|
<el-container>
|
|
@@ -143,8 +151,8 @@
|
|
|
</template>
|
|
|
|
|
|
|
|
|
- <!-- 3、更改尺寸 4、美化图片 5、添加水印 6、图片圆角 9、批量旋转 10、图片裁剪 -->
|
|
|
- <template v-else-if="[3,4,5,6,9,10].indexOf(menuIndex) > -1">
|
|
|
+ <!-- 3、更改尺寸 4、美化图片 5、添加水印 6、图片圆角 9、批量旋转 10、图片裁剪 12、图片分割 -->
|
|
|
+ <template v-else-if="[3,4,5,6,9,10,12].indexOf(menuIndex) > -1">
|
|
|
<div class="soft-content">
|
|
|
<div class="content-left" style="width: calc(100% - 270px)">
|
|
|
<!-- 图片裁剪 -->
|
|
@@ -203,20 +211,33 @@
|
|
|
:full="true"
|
|
|
@realTime="realTime"
|
|
|
@imgLoad="cropImgLoad"
|
|
|
- ></vueCropper>
|
|
|
+ >
|
|
|
+ </vueCropper>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="merge-content" v-else>
|
|
|
<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="{borderRadius: menuIndex == 6 ? handleData.circularValue+'%' : 0, maxWidth: '80%',maxHeight: '500px', transform: 'rotate('+handleData.rotateValue+'deg) rotateY('+ (handleData.hflip ? '180' : '0') +'deg) rotateX('+ (handleData.vflip ? '180' : '0') +'deg) scale('+viewScale+')'}" />
|
|
|
+ <template v-if="menuIndex != 12">
|
|
|
+ <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="{borderRadius: menuIndex == 6 ? handleData.circularValue+'%' : 0, maxWidth: '80%',maxHeight: '500px', transform: 'rotate('+handleData.rotateValue+'deg) rotateY('+ (handleData.hflip ? '180' : '0') +'deg) rotateX('+ (handleData.vflip ? '180' : '0') +'deg) scale('+viewScale+')'}" />
|
|
|
+ </template>
|
|
|
+ <template v-if="menuIndex == 12">
|
|
|
+ <div id="fg-bg" class="fg-bg" :style="'background-image: url('+imgSrc+');'">
|
|
|
+ <div class="grid-overlay" style="width: 100%; height: 100%; position: absolute; top: 0; left: 0; pointer-events: none; background-color: #00000020;">
|
|
|
+ <div v-for="n in cutX-1" :key="n" :style="gridLineStyle(n, cutX-1, 'x')"></div>
|
|
|
+ </div>
|
|
|
+ <div class="grid-overlay" style="width: 100%; height: 100%; position: absolute; top: 0; left: 0; pointer-events: none; background-color: #00000020;">
|
|
|
+ <div v-for="m in cutY-1" :key="m" :style="gridLineStyle(m, cutY-1, 'y')"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -548,6 +569,18 @@
|
|
|
<el-tag type="danger">批量裁剪请点击“应用全部”按钮</el-tag>
|
|
|
</div>
|
|
|
</template>
|
|
|
+
|
|
|
+ <!-- 12图片分割 -->
|
|
|
+ <template v-if="menuIndex == 12">
|
|
|
+ <div class="handle-item">
|
|
|
+ <label class="handle-label">行数:</label>
|
|
|
+ <el-input-number size="small" v-model="cutX" :min="1" :max="100"></el-input-number>
|
|
|
+ </div>
|
|
|
+ <div class="handle-item">
|
|
|
+ <label class="handle-label">列数:</label>
|
|
|
+ <el-input-number size="small" v-model="cutY" :min="1" :max="100"></el-input-number>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -1010,6 +1043,9 @@ export default {
|
|
|
renameLoading: false,
|
|
|
mergeLoading: false,
|
|
|
mergeInterval: false,
|
|
|
+
|
|
|
+ cutX: 3,
|
|
|
+ cutY: 3,
|
|
|
};
|
|
|
},
|
|
|
computed:{
|
|
@@ -1089,6 +1125,41 @@ export default {
|
|
|
this.initDrop();
|
|
|
},
|
|
|
methods: {
|
|
|
+ gridLineStyle(index, total, type) { // 3行4列 2-3
|
|
|
+ let obj = document.getElementById('fg-bg');
|
|
|
+ if(obj){
|
|
|
+ obj.style.width = '80%';
|
|
|
+ obj.style.height = '80%';
|
|
|
+ let scale = this.handleData.width / this.handleData.height;
|
|
|
+ if(this.handleData.width >= this.handleData.height){
|
|
|
+ obj.style.height = obj.clientWidth / scale + 'px';
|
|
|
+ }else{
|
|
|
+ obj.style.width = obj.clientHeight * scale + 'px';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ let num = Number(total)+1;
|
|
|
+ if(type == 'x'){ //行
|
|
|
+ let top = (100 / num * index) + '%';
|
|
|
+ return {
|
|
|
+ width: '100%',
|
|
|
+ height: '1px',
|
|
|
+ backgroundColor: 'rgba(255, 255, 255)',
|
|
|
+ position: 'absolute',
|
|
|
+ left: 0,
|
|
|
+ top: top
|
|
|
+ };
|
|
|
+ }else{ //列
|
|
|
+ let left = (100 / num * index) + '%';
|
|
|
+ return {
|
|
|
+ width: '1px',
|
|
|
+ height: '100%',
|
|
|
+ backgroundColor: 'rgba(255, 255, 255)',
|
|
|
+ position: 'absolute',
|
|
|
+ left: left,
|
|
|
+ top: 0
|
|
|
+ };
|
|
|
+ }
|
|
|
+ },
|
|
|
// 鼠标滚轮事件
|
|
|
initRoll(){
|
|
|
let element = document.getElementById('show-img');
|
|
@@ -1700,7 +1771,7 @@ export default {
|
|
|
this.imgInfo = currentRow;
|
|
|
this.imgInfoIndex = index;
|
|
|
|
|
|
- if([3,6,7,9].indexOf(this.menuIndex) > -1){
|
|
|
+ if([3,6,7,9,12].indexOf(this.menuIndex) > -1){
|
|
|
this.imgLoading = true;
|
|
|
electronApi.fileStream(currentRow.path).then(buffer => {
|
|
|
this.imgSrc = "data:image/png;base64,"+buffer.toString('base64');
|
|
@@ -1854,6 +1925,71 @@ export default {
|
|
|
let task = '';
|
|
|
|
|
|
switch (this.menuIndex) {
|
|
|
+ case 12: //图片分割
|
|
|
+ let name = imgInfo.name.substr(0, imgInfo.name.lastIndexOf('.'))
|
|
|
+ newPath = this.downloadDir + separator + pjson.softInfo.softName + separator + name + '_%d.' +imgInfo.type;
|
|
|
+ task = new Promise((resolve,reject) => {
|
|
|
+ let imgPath = imgInfo.path;
|
|
|
+ let cmd = [
|
|
|
+ 'convert.exe',
|
|
|
+ '-monitor',
|
|
|
+ imgPath,
|
|
|
+ '-crop',
|
|
|
+ this.cutY+'x'+this.cutX+'@',
|
|
|
+ '+repage',
|
|
|
+ '+adjoin',
|
|
|
+ newPath
|
|
|
+ ];
|
|
|
+
|
|
|
+ electronApi.spawnExec(cmd,{
|
|
|
+ stderr:(data) => {
|
|
|
+ let str = data.toString();
|
|
|
+ const regexDuration = /Load.*?,(.*?)%/;
|
|
|
+ const 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)
|
|
|
+
|
|
|
+ let num = this.cutY * this.cutX;
|
|
|
+ //未购买 添加系统水印
|
|
|
+ this.addWatermark(index,imgInfo,newPath, num);
|
|
|
+ resolve({type:this.menuIndex,index, img});
|
|
|
+ }).catch(err => {
|
|
|
+ // console.log(err.stderr.toString());
|
|
|
+ reject({type:this.menuIndex,index,err});
|
|
|
+ });
|
|
|
+ });
|
|
|
+ break;
|
|
|
case 11: // 修改dpi
|
|
|
task = new Promise((resolve,reject) => {
|
|
|
let imgPath = imgInfo.path;
|
|
@@ -2672,7 +2808,11 @@ export default {
|
|
|
if(this.menuIndex == 3){
|
|
|
width = width * (this.handleData.scaling / 100);
|
|
|
}
|
|
|
- if (width < 500) {
|
|
|
+ if (width < 100){
|
|
|
+ fontSize = 8;
|
|
|
+ }else if (width < 300) {
|
|
|
+ fontSize = 12;
|
|
|
+ }else if (width < 500) {
|
|
|
fontSize = 16;
|
|
|
} else if (width < 1000) {
|
|
|
fontSize = 28
|
|
@@ -2713,7 +2853,7 @@ export default {
|
|
|
});
|
|
|
},
|
|
|
// 添加默认水印
|
|
|
- async addWatermark(index,imgInfo,newPath) {
|
|
|
+ async addWatermark(index,imgInfo,newPath, num) {
|
|
|
return new Promise((resolve,reject) => {
|
|
|
let authority = this.$refs.headerRef.authority;
|
|
|
|
|
@@ -2721,25 +2861,59 @@ export default {
|
|
|
// 有权限,则不做任何操作
|
|
|
resolve(true)
|
|
|
} else {
|
|
|
+ if(num){
|
|
|
+ imgInfo.width = imgInfo.width / this.cutY;
|
|
|
+ }
|
|
|
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)
|
|
|
- });
|
|
|
+ if(num){
|
|
|
+ let name = imgInfo.name.substr(0, imgInfo.name.lastIndexOf('.'))
|
|
|
+ for(let i = 0; i < num; i++){
|
|
|
+ if(i < 10){
|
|
|
+ let pathReg = this.downloadDir + separator + pjson.softInfo.softName + separator + name + '_' + i + '.' +imgInfo.type;
|
|
|
+ pathReg = pathReg.replace(/\\/g, '/');
|
|
|
+
|
|
|
+ // 合并系统水印
|
|
|
+ let params2 = [
|
|
|
+ 'convert.exe',
|
|
|
+ '-monitor',
|
|
|
+ pathReg,
|
|
|
+ sysDefaultTmpPath,
|
|
|
+ '-gravity',
|
|
|
+ 'center',
|
|
|
+ '-composite',
|
|
|
+ pathReg
|
|
|
+ ];
|
|
|
+
|
|
|
+ electronApi.spawnExec(params2).then(result => {
|
|
|
+ resolve(result)
|
|
|
+ }).catch(err => {
|
|
|
+ reject(err)
|
|
|
+ });
|
|
|
+ }else{
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ // 合并系统水印
|
|
|
+ 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})
|
|
|
});
|
|
@@ -3927,8 +4101,27 @@ export default {
|
|
|
font-size: 16px;
|
|
|
}
|
|
|
|
|
|
+ .el-menu-item:hover img{
|
|
|
+ zoom: 1.1;
|
|
|
+ }
|
|
|
+
|
|
|
.el-menu-item:hover{
|
|
|
font-weight: 800;
|
|
|
font-size: 16px;
|
|
|
}
|
|
|
+
|
|
|
+ .el-menu-item, .el-submenu__title{
|
|
|
+ height: 52px !important;
|
|
|
+ line-height: 52px !important;
|
|
|
+ }
|
|
|
+
|
|
|
+ .fg-bg{
|
|
|
+ position: relative;
|
|
|
+ width: 80%;
|
|
|
+ height: 80%;
|
|
|
+ margin: auto;
|
|
|
+ background-size: contain;
|
|
|
+ background-repeat: no-repeat;
|
|
|
+ background-position: center center;
|
|
|
+ }
|
|
|
</style>
|