from tkinter import *
from tkinter import filedialog, messagebox
from PIL import Image, ImageDraw, ImageFont, ImageTk
import os

# 证件尺寸设置 宽x高
CARD_WIDTH = 600
CARD_HEIGHT = 400
# 配色
BG_COLOR = (30, 80, 180)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (230, 230, 230)

class StudentCardGenerator:
    def __init__(self, root):
        self.root = root
        self.root.title("学生证件生成器")
        self.root.geometry("850x520")

        # 存储数据
        self.photo_path = ""
        self.preview_img = None

        # 左侧输入面板
        left_frame = Frame(root, padx=10, pady=10)
        left_frame.pack(side=LEFT, fill=Y)

        # 输入项标题
        Label(left_frame, text="学生信息填写", font=("黑体", 14, "bold")).pack(pady=5)

        # 姓名
        lab_name = Label(left_frame, text="姓名：", anchor=W)
        lab_name.pack(fill=X)
        self.name_var = StringVar()
        Entry(left_frame, textvariable=self.name_var, width=25).pack(pady=2)

        # 学号
        lab_id = Label(left_frame, text="学号：", anchor=W)
        lab_id.pack(fill=X)
        self.id_var = StringVar()
        Entry(left_frame, textvariable=self.id_var, width=25).pack(pady=2)

        # 班级
        lab_class = Label(left_frame, text="班级：", anchor=W)
        lab_class.pack(fill=X)
        self.class_var = StringVar()
        Entry(left_frame, textvariable=self.class_var, width=25).pack(pady=2)

        # 专业
        lab_major = Label(left_frame, text="专业：", anchor=W)
        lab_major.pack(fill=X)
        self.major_var = StringVar()
        Entry(left_frame, textvariable=self.major_var, width=25).pack(pady=2)

        # 学校
        lab_school = Label(left_frame, text="学校：", anchor=W)
        lab_school.pack(fill=X)
        self.school_var = StringVar()
        Entry(left_frame, textvariable=self.school_var, width=25).pack(pady=2)

        # 性别
        lab_gender = Label(left_frame, text="性别：", anchor=W)
        lab_gender.pack(fill=X)
        self.gender_var = StringVar()
        Entry(left_frame, textvariable=self.gender_var, width=25).pack(pady=2)

        # 选择照片按钮
        Button(left_frame, text="选择学生照片", command=self.select_photo, bg="#5599ff", fg="white").pack(pady=8, fill=X)
        self.photo_label = Label(left_frame, text="未选择照片", fg="red")
        self.photo_label.pack()

        # 功能按钮
        Button(left_frame, text="预览证件", command=self.show_preview, bg="#22aa55", fg="white", height=2).pack(pady=5, fill=X)
        Button(left_frame, text="保存证件图片", command=self.save_card, bg="#ff7722", fg="white", height=2).pack(pady=5, fill=X)

        # 右侧预览面板
        right_frame = Frame(root, padx=10, pady=10)
        right_frame.pack(side=RIGHT, fill=BOTH, expand=True)
        Label(right_frame, text="证件预览", font=("黑体", 14, "bold")).pack()
        self.preview_panel = Label(right_frame, relief=SOLID, bd=1)
        self.preview_panel.pack(pady=10)

    def select_photo(self):
        path = filedialog.askopenfilename(
            title="选择照片",
            filetypes=[("图片文件", "*.jpg;*.png;*.jpeg")]
        )
        if path:
            self.photo_path = path
            self.photo_label.config(text=os.path.basename(path), fg="green")

    def create_card_image(self):
        # 创建画布
        img = Image.new("RGB", (CARD_WIDTH, CARD_HEIGHT), BG_COLOR)
        draw = ImageDraw.Draw(img)

        # 加载字体（兼容Windows/Mac/Linux）
        try:
            font_big = ImageFont.truetype("simhei.ttf", 32)
            font_mid = ImageFont.truetype("simhei.ttf", 22)
            font_small = ImageFont.truetype("simhei.ttf", 18)
        except:
            font_big = ImageFont.load_default(size=32)
            font_mid = ImageFont.load_default(size=22)
            font_small = ImageFont.load_default(size=18)

        # 标题
        title = "学生学生证"
        tw = draw.textlength(title, font=font_big)
        draw.text(((CARD_WIDTH - tw) / 2, 20), title, font=font_big, fill=WHITE)

        # 白色信息底板
        draw.rectangle([30, 80, CARD_WIDTH - 30, CARD_HEIGHT - 30], fill=WHITE)

        # 绘制照片区域
        photo_box = [50, 100, 220, 340]
        draw.rectangle(photo_box, outline=BLACK, width=2)
        if self.photo_path and os.path.exists(self.photo_path):
            try:
                p_img = Image.open(self.photo_path).convert("RGB")
                p_img = p_img.resize((170, 240), Image.Resampling.LANCZOS)
                img.paste(p_img, photo_box)
            except:
                draw.text((70, 200), "照片损坏", fill=BLACK, font=font_small)
        else:
            draw.text((75, 200), "无照片", fill=BLACK, font=font_small)

        # 文字信息起始坐标
        text_x = 250
        start_y = 110
        line_h = 40

        info_list = [
            f"姓名：{self.name_var.get()}",
            f"学号：{self.id_var.get()}",
            f"班级：{self.class_var.get()}",
            f"专业：{self.major_var.get()}",
            f"性别：{self.gender_var.get()}",
            f"学校：{self.school_var.get()}"
        ]

        for i, text in enumerate(info_list):
            draw.text((text_x, start_y + i * line_h), text, font=font_mid, fill=BLACK)

        # 底部水印
        draw.text((350, 350), "学生证件 · 校内通行凭证", font=font_small, fill=(100, 100, 100))
        return img

    def show_preview(self):
        # 校验必填项
        if not all([
            self.name_var.get(), self.id_var.get(), self.class_var.get(),
            self.major_var.get(), self.school_var.get(), self.gender_var.get()
        ]):
            messagebox.showwarning("提示", "请完整填写所有学生信息！")
            return

        card_img = self.create_card_image()
        # 缩放预览
        preview_show = card_img.resize((420, 280), Image.Resampling.LANCZOS)
        self.preview_img = ImageTk.PhotoImage(preview_show)
        self.preview_panel.config(image=self.preview_img)

    def save_card(self):
        if not all([
            self.name_var.get(), self.id_var.get(), self.class_var.get(),
            self.major_var.get(), self.school_var.get(), self.gender_var.get()
        ]):
            messagebox.showwarning("提示", "请完整填写所有学生信息！")
            return

        save_path = filedialog.asksaveasfilename(
            defaultextension=".png",
            filetypes=[("PNG图片", "*.png"), ("JPG图片", "*.jpg")],
            initialfile=f"{self.name_var.get()}_学生证"
        )
        if save_path:
            card_img = self.create_card_image()
            card_img.save(save_path)
            messagebox.showinfo("完成", f"证件已保存至：{save_path}")

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