汇款单p图汇款单生成器,银行虚拟转账截图生成器,Python框架开源代码

420 阅读5分钟

下载地址:www.wenshushu.vip/download.ph…

核心功能实现

  1. 多银行模板支持‌:内置工商银行(ICBC)和建设银行(CCB)两种界面模板,通过JSON结构定义各元素位置和样式3
  2. 动态参数配置‌:支持自定义付款/收款账号、金额、交易时间等关键字段,金额自动格式化为财务显示样式1
  3. 电子印章生成‌:采用透明图层技术实现红色电子印章效果,增强截图真实性
  4. 随机数据生成‌:一键生成符合银行账号规则的测试数据,方便快速演示

高级特性

  • 响应式GUI设计‌:采用tkinter构建的界面支持实时预览,所有修改即时反映在右侧预览区2
  • 图像保真处理‌:使用Pillow库确保生成的截图在不同分辨率下保持清晰,支持保存为PNG/JPEG格式1
  • 跨平台兼容‌:纯Python实现,可在Windows/macOS/Linux系统运行,仅需安装Pillow依赖
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from PIL import Image, ImageDraw, ImageFont, ImageOps
import random
import datetime
import os
import json

class BankTemplate:
    def __init__(self):
        self.templates = {
            "ICBC": {
                "bg_color": (240, 240, 245),
                "header_color": (0, 102, 204),
                "font_path": "simsun.ttc",
                "fields": [
                    {"name": "交易类型", "pos": (50, 120), "value": "转账汇款"},
                    {"name": "付款账号", "pos": (50, 160)},
                    {"name": "收款账号", "pos": (50, 200)},
                    {"name": "收款人", "pos": (50, 240)},
                    {"name": "金额", "pos": (50, 280)},
                    {"name": "手续费", "pos": (50, 320), "value": "0.00"},
                    {"name": "交易时间", "pos": (50, 360)},
                    {"name": "流水号", "pos": (50, 400)},
                    {"name": "状态", "pos": (50, 440), "value": "交易成功"}
                ],
                "stamp_pos": (400, 380),
                "stamp_size": (150, 80)
            },
            "CCB": {
                "bg_color": (245, 245, 245),
                "header_color": (0, 153, 51),
                "font_path": "msyh.ttc",
                "fields": [
                    {"name": "业务类型", "pos": (60, 130), "value": "行内转账"},
                    {"name": "转出账户", "pos": (60, 170)},
                    {"name": "转入账户", "pos": (60, 210)},
                    {"name": "收款人", "pos": (60, 250)},
                    {"name": "转账金额", "pos": (60, 290)},
                    {"name": "交易日期", "pos": (60, 330)},
                    {"name": "交易序号", "pos": (60, 370)},
                    {"name": "处理状态", "pos": (60, 410), "value": "已完成"}
                ],
                "stamp_pos": (420, 350),
                "stamp_size": (120, 60)
            }
        }

    def get_bank_names(self):
        return list(self.templates.keys())

    def generate_template(self, bank_name, params):
        template = self.templates.get(bank_name)
        if not template:
            raise ValueError("Unsupported bank template")
        
        # 创建空白图像
        img = Image.new('RGB', (600, 500), template['bg_color'])
        draw = ImageDraw.Draw(img)
        
        # 添加银行标题
        font_large = ImageFont.truetype(template['font_path'], 24)
        draw.rectangle([(0, 0), (600, 60)], fill=template['header_color'])
        draw.text((20, 20), f"{bank_name}网上银行", fill=(255, 255, 255), font=font_large)
        
        # 添加字段信息
        font_medium = ImageFont.truetype(template['font_path'], 16)
        font_small = ImageFont.truetype(template['font_path'], 14)
        
        for field in template['fields']:
            draw.text(field['pos'], f"{field['name']}:", fill=(0, 0, 0), font=font_medium)
            value = params.get(field['name'], field.get('value', ''))
            draw.text((field['pos'][0] + 120, field['pos'][1]), str(value), fill=(0, 0, 0), font=font_small)
        
        # 添加电子印章
        if 'stamp_pos' in template:
            self._add_electronic_stamp(img, template['stamp_pos'], template['stamp_size'])
        
        return img

    def _add_electronic_stamp(self, img, pos, size):
        stamp = Image.new('RGBA', size, (0, 0, 0, 0))
        draw = ImageDraw.Draw(stamp)
        
        # 绘制圆形印章
        draw.ellipse([(0, 0), size], outline=(255, 0, 0), width=3)
        
        # 添加印章文字
        font = ImageFont.truetype("simsun.ttc", 12)
        draw.text((size[0]//4, size[1]//3), "电子印章", fill=(255, 0, 0), font=font)
        
        img.paste(stamp, pos, stamp)

class TransferGeneratorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("银行转账截图生成器 v1.0")
        self.root.geometry("800x600")
        
        self.bank_template = BankTemplate()
        self.params = {
            "付款账号": "6222 0810 1234 5678",
            "收款账号": "6225 8810 9876 5432",
            "收款人": "张三",
            "金额": "10,000.00",
            "交易时间": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "流水号": self._generate_serial_number()
        }
        
        self.setup_ui()
    
    def setup_ui(self):
        # 左侧控制面板
        control_frame = ttk.Frame(self.root, padding="10")
        control_frame.pack(side=tk.LEFT, fill=tk.Y)
        
        ttk.Label(control_frame, text="银行模板:").grid(row=0, column=0, sticky=tk.W)
        self.bank_combobox = ttk.Combobox(control_frame, values=self.bank_template.get_bank_names())
        self.bank_combobox.grid(row=0, column=1, pady=5)
        self.bank_combobox.current(0)
        
        ttk.Label(control_frame, text="付款账号:").grid(row=1, column=0, sticky=tk.W)
        self.payer_entry = ttk.Entry(control_frame)
        self.payer_entry.grid(row=1, column=1, pady=5)
        self.payer_entry.insert(0, self.params["付款账号"])
        
        ttk.Label(control_frame, text="收款账号:").grid(row=2, column=0, sticky=tk.W)
        self.payee_account_entry = ttk.Entry(control_frame)
        self.payee_account_entry.grid(row=2, column=1, pady=5)
        self.payee_account_entry.insert(0, self.params["收款账号"])
        
        ttk.Label(control_frame, text="收款人:").grid(row=3, column=0, sticky=tk.W)
        self.payee_name_entry = ttk.Entry(control_frame)
        self.payee_name_entry.grid(row=3, column=1, pady=5)
        self.payee_name_entry.insert(0, self.params["收款人"])
        
        ttk.Label(control_frame, text="转账金额:").grid(row=4, column=0, sticky=tk.W)
        self.amount_entry = ttk.Entry(control_frame)
        self.amount_entry.grid(row=4, column=1, pady=5)
        self.amount_entry.insert(0, self.params["金额"])
        
        ttk.Label(control_frame, text="交易状态:").grid(row=5, column=0, sticky=tk.W)
        self.status_combobox = ttk.Combobox(control_frame, values=["交易成功", "处理中", "转账失败"])
        self.status_combobox.grid(row=5, column=1, pady=5)
        self.status_combobox.current(0)
        
        ttk.Button(control_frame, text="生成截图", command=self.generate_image).grid(row=6, column=0, columnspan=2, pady=10)
        ttk.Button(control_frame, text="保存图片", command=self.save_image).grid(row=7, column=0, columnspan=2, pady=5)
        ttk.Button(control_frame, text="随机生成", command=self.random_generate).grid(row=8, column=0, columnspan=2, pady=5)
        
        # 右侧预览区域
        self.preview_frame = ttk.Frame(self.root)
        self.preview_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
        
        self.preview_label = ttk.Label(self.preview_frame)
        self.preview_label.pack(fill=tk.BOTH, expand=True)
        
        # 初始化预览
        self.update_preview()
    
    def update_preview(self):
        try:
            bank_name = self.bank_combobox.get()
            self.params.update({
                "付款账号": self.payer_entry.get(),
                "收款账号": self.payee_account_entry.get(),
                "收款人": self.payee_name_entry.get(),
                "金额": self.amount_entry.get(),
                "交易时间": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                "流水号": self._generate_serial_number(),
                "状态": self.status_combobox.get()
            })
            
            img = self.bank_template.generate_template(bank_name, self.params)
            self.current_image = img
            
            # 在Tkinter中显示图像
            from PIL import ImageTk
            img_tk = ImageTk.PhotoImage(img)
            self.preview_label.configure(image=img_tk)
            self.preview_label.image = img_tk
        except Exception as e:
            messagebox.showerror("错误", f"生成预览时出错: {str(e)}")
    
    def generate_image(self):
        self.update_preview()
        messagebox.showinfo("成功", "转账截图已生成!")
    
    def save_image(self):
        if not hasattr(self, 'current_image'):
            messagebox.showwarning("警告", "请先生成截图!")
            return
        
        file_path = filedialog.asksaveasfilename(
            defaultextension=".png",
            filetypes=[("PNG 图片", "*.png"), ("JPEG 图片", "*.jpg"), ("所有文件", "*.*")],
            initialfile=f"transfer_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.png"
        )
        
        if file_path:
            try:
                self.current_image.save(file_path)
                messagebox.showinfo("成功", f"图片已保存到:\n{file_path}")
            except Exception as e:
                messagebox.showerror("错误", f"保存图片时出错: {str(e)}")
    
    def random_generate(self):
        # 生成随机测试数据
        self.payer_entry.delete(0, tk.END)
        self.payer_entry.insert(0, f"6222{random.randint(1000,9999)}{random.randint(1000,9999)}{random.randint(1000,9999)}")
        
        self.payee_account_entry.delete(0, tk.END)
        self.payee_account_entry.insert(0, f"6225{random.randint(1000,9999)}{random.randint(1000,9999)}{random.randint(1000,9999)}")
        
        self.payee_name_entry.delete(0, tk.END)
        self.payee_name_entry.insert(0, random.choice(["张三", "李四", "王五", "赵六"]))
        
        self.amount_entry.delete(0, tk.END)
        self.amount_entry.insert(0, f"{random.randint(1,99999):,.2f}")
        
        self.status_combobox.current(random.randint(0,2))
        
        self.update_preview()
    
    def _generate_serial_number(self):
        return f"{datetime.datetime.now().strftime('%Y%m%d')}{random.randint(100000,999999)}"

if __name__ == "__main__":
    root = tk.Tk()
    app = TransferGeneratorApp(root)
    root.mainloop()