2 Commits

3 changed files with 32 additions and 45 deletions

10
app.py
View File

@@ -1,7 +1,7 @@
"""
图片编辑器 - Image Editor v1.2.3
图片编辑器 - Image Editor v1.2.5
前端图片处理工具:合并、分割、挖孔填充、圆形切图、文字图片等
v1.2.3: 执行操作后保持当前配置面板
v1.2.5: 修复操作后面板判断问题
端口: 19018
"""
@@ -25,7 +25,7 @@ def index():
@app.route('/api/health')
def health():
return jsonify({'status': 'ok', 'version': '1.2.2', 'time': datetime.now().isoformat()})
return jsonify({'status': 'ok', 'version': '1.2.5', 'time': datetime.now().isoformat()})
@app.route('/api/save', methods=['POST'])
def save_image():
@@ -64,9 +64,9 @@ def list_images():
if __name__ == '__main__':
print("=" * 50)
print("图片编辑器 - Image Editor v1.2.2")
print("图片编辑器 - Image Editor v1.2.5")
print("=" * 50)
print("右侧面板始终显示,首页显示快捷入口")
print("修复操作后面板判断问题")
print(f"访问地址: http://localhost:19018")
print("=" * 50)
app.run(host='0.0.0.0', port=19018, debug=True)

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 KiB

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片编辑器 - Image Editor v1.2.3</title>
<title>图片编辑器 - Image Editor v1.2.5</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/remixicon@3.5.0/fonts/remixicon.css" rel="stylesheet">
<style>
@@ -90,9 +90,6 @@
<!-- 功能按钮 -->
<div class="mt-3 flex gap-2 flex-wrap">
<button onclick="setTool('upload')" id="tool-upload" class="tool-btn px-3 py-2 bg-gray-200 rounded-lg">
<i class="ri-upload-cloud-line mr-1"></i>上传图片
</button>
<button onclick="setTool('merge')" id="tool-merge" class="tool-btn px-3 py-2 bg-gray-200 rounded-lg">
<i class="ri-stack-line mr-1"></i>合并图片
</button>
@@ -127,7 +124,8 @@
<canvas id="mainCanvas"></canvas>
<div id="emptyHint" class="text-gray-400 text-center">
<i class="ri-image-add-line text-6xl"></i>
<p class="mt-2">点击"上传图片"或拖放图片开始编辑</p>
<p class="mt-2">拖动图片到此处上传</p>
<p class="text-sm mt-1">支持多张图片同时上传</p>
</div>
</div>
@@ -192,7 +190,10 @@
const ctx = canvas.getContext('2d');
const container = document.getElementById('canvasContainer');
// 返回首页面板
// 检查是否有图片(画布有内容)
function hasImage() {
return state.images.length > 0 || document.getElementById('emptyHint').classList.contains('hidden');
}
function goHome() {
document.querySelectorAll('.tool-btn').forEach(btn => btn.classList.remove('active'));
state.currentTool = null;
@@ -245,11 +246,6 @@
// 更新右侧配置面板内容(不隐藏)
showPanel(tool);
// 上传图片直接触发文件选择
if (tool === 'upload') {
document.getElementById('fileInput').click();
}
}
// 显示右侧面板内容
@@ -266,18 +262,18 @@
// 获取各工具的配置面板内容
function getPanelConfig(tool) {
// 默认首页面板
<!-- 默认首页面板 -->
if (!tool || tool === 'home') {
return {
title: '欢迎使用',
content: `
<div class="space-y-4">
<p class="text-sm text-gray-600">点击顶部功能按钮开始编辑图片</p>
<div class="p-3 bg-blue-50 rounded-lg border-2 border-dashed border-blue-300 text-center">
<i class="ri-upload-cloud-2-line text-3xl text-blue-500"></i>
<p class="text-sm text-blue-600 mt-2">拖动图片到左侧画布区域上传</p>
</div>
<div class="grid grid-cols-2 gap-2">
<button onclick="setTool('upload')" class="p-3 bg-blue-50 rounded-lg hover:bg-blue-100 text-center">
<i class="ri-upload-cloud-line text-2xl text-blue-500"></i>
<p class="text-xs mt-1">上传图片</p>
</button>
<button onclick="setTool('merge')" class="p-3 bg-green-50 rounded-lg hover:bg-green-100 text-center">
<i class="ri-stack-line text-2xl text-green-500"></i>
<p class="text-xs mt-1">合并图片</p>
@@ -318,20 +314,9 @@
}
switch(tool) {
case 'upload':
return {
title: '上传图片',
content: `
<p class="text-sm text-gray-600 mb-4">点击按钮选择图片,或直接拖放图片到画布区域</p>
<button onclick="document.getElementById('fileInput').click()" class="w-full px-4 py-3 bg-blue-500 text-white rounded-lg">
<i class="ri-upload-cloud-line mr-2"></i>选择图片
</button>
`,
actions: ''
};
case 'merge':
if (state.images.length < 2) {
if (!hasImage() || state.images.length < 2) {
return {
title: '合并图片',
content: `<p class="text-sm text-red-500">请先上传至少2张图片</p>`,
@@ -408,7 +393,7 @@
};
case 'split':
if (state.images.length === 0) {
if (!hasImage()) {
return {
title: '分割图片',
content: `<p class="text-sm text-red-500">请先上传图片</p>`,
@@ -439,7 +424,7 @@
};
case 'hole':
if (state.images.length === 0) {
if (!hasImage()) {
return {
title: '挖孔填充',
content: `<p class="text-sm text-red-500">请先上传图片</p>`,
@@ -485,7 +470,7 @@
};
case 'circle':
if (state.images.length === 0) {
if (!hasImage()) {
return {
title: '圆形切图',
content: `<p class="text-sm text-red-500">请先上传图片</p>`,
@@ -571,7 +556,7 @@
};
case 'resize':
if (state.images.length === 0) {
if (!hasImage()) {
return {
title: '调整大小',
content: `<p class="text-sm text-red-500">请先上传图片</p>`,
@@ -602,7 +587,7 @@
};
case 'crop':
if (state.images.length === 0) {
if (!hasImage()) {
return {
title: '裁剪',
content: `<p class="text-sm text-red-500">请先上传图片</p>`,
@@ -872,6 +857,8 @@
updateImageList();
hideEmptyHint();
saveState('加载: ' + name);
// 刷新当前面板
refreshCurrentPanel();
};
img.src = dataUrl;
}
@@ -896,7 +883,7 @@
const list = document.getElementById('imageList');
const items = document.getElementById('imageItems');
document.getElementById('imageCount').textContent = `(${state.images.length}张)`;
if (state.images.length === 0) { list.classList.add('hidden'); return; }
if (!hasImage()) { list.classList.add('hidden'); return; }
list.classList.remove('hidden');
items.innerHTML = '';
state.images.forEach((item, index) => {
@@ -916,7 +903,7 @@
drawCanvas();
updateImageList();
saveState('移除图片');
if (state.images.length === 0) showEmptyHint();
if (!hasImage()) showEmptyHint();
}
function hideEmptyHint() {
@@ -997,7 +984,7 @@
});
const mergedData = canvas.toDataURL('image/png');
state.images = [];
hideEmptyHint(); state.images = [];
loadImage(mergedData, 'merged');
refreshCurrentPanel();
}
@@ -1175,7 +1162,7 @@
ctx.drawImage(circleCanvas, 0, 0);
const circleData = canvas.toDataURL('image/png');
state.images = [];
hideEmptyHint(); state.images = [];
loadImage(circleData, 'circle');
refreshCurrentPanel();
}
@@ -1226,7 +1213,7 @@
});
const textData = canvas.toDataURL('image/png');
state.images = [];
hideEmptyHint(); state.images = [];
loadImage(textData, 'text');
refreshCurrentPanel();
}
@@ -1244,7 +1231,7 @@
ctx.drawImage(img.img, 0, 0, newWidth, newHeight);
const resizedData = canvas.toDataURL('image/png');
state.images = [];
hideEmptyHint(); state.images = [];
loadImage(resizedData, 'resized');
refreshCurrentPanel();
}
@@ -1264,7 +1251,7 @@
ctx.drawImage(img.img, x, y, w, h, 0, 0, w, h);
const croppedData = canvas.toDataURL('image/png');
state.images = [];
hideEmptyHint(); state.images = [];
loadImage(croppedData, 'cropped');
refreshCurrentPanel();
}