PY的vps成本管理器简单代码

V+变量
2024-12-15 / 0 评论 / 8 阅读 / 正在检测是否收录...

一直以来,本人有个痛点,就是手持太多vps。有月付的,年付的,半年的,季付的。 各种结算货币。完全无统一标准。导致财务管理困难。所以就诞生了这个工具
简单易用,只需要把如下代码保存到任意.py文件并且在cmd运行
即可。

python xx.py
程序会自动在相同目录创建vps_cost_config.json文件用作数据存储。

感谢:chatgpt

import tkinter as tk
from tkinter import messagebox, ttk  # 引入 ttk 组件,界面更美观
import json

# =============== 配置文件相关 ===============
CONFIG_FILE_PATH = "vps_cost_config.json"

default_exchange_rates = {'USD': 1, 'CNY': 7.1, 'EUR': 0.85}

def load_config():
    try:
        with open(CONFIG_FILE_PATH, 'r') as file:
            return json.load(file)
    except FileNotFoundError:
        return {'exchange_rates': default_exchange_rates, 'vps_list': []}

def save_config(config):
    with open(CONFIG_FILE_PATH, 'w') as file:
        json.dump(config, file, indent=4)

# =============== 功能函数 ===============
def update_exchange_rates():
    try:
        exchange_rates = {currency: float(var.get()) for currency, var in currency_rate_vars.items()}
        config['exchange_rates'] = exchange_rates
        save_config(config)
        update_vps_list()
        update_monthly_costs()
        messagebox.showinfo("成功", "汇率已更新并保存。")
    except ValueError:
        messagebox.showerror("错误", "请输入有效的数字汇率。")

def add_vps():
    try:
        name = vps_name_var.get()
        amount = float(amount_var.get())
        vps = {
            'name': name,
            'payment_cycle': payment_cycle_var.get(),
            'amount': amount,
            'currency': currency_var.get()
        }
        config['vps_list'].append(vps)
        save_config(config)
        update_vps_list()
        clear_vps_fields()
        update_monthly_costs()
    except ValueError:
        messagebox.showerror("错误", "请输入有效的费用。")

def delete_vps():
    selected = vps_listbox.curselection()
    if not selected:
        messagebox.showerror("错误", "请选择一个 VPS 项目删除。")
        return
    selected_name = vps_listbox.get(selected).split(' ')[0]
    config['vps_list'] = [v for v in config['vps_list'] if v['name'] != selected_name]
    save_config(config)
    update_vps_list()
    update_monthly_costs()

def update_vps_list():
    vps_listbox.delete(0, tk.END)
    for vps in config['vps_list']:
        vps_listbox.insert(tk.END, f"{vps['name']} ({vps['payment_cycle']}) - {vps['amount']} {vps['currency']}")

def update_monthly_costs():
    monthly_costs, total_cost = calculate_monthly_cost(config['vps_list'], config['exchange_rates'])
    monthly_cost_display.config(state="normal")
    monthly_cost_display.delete("1.0", tk.END)

    max_name_length = max(len(name) for name in monthly_costs.keys())  # 获取最长名字长度
    separator = '-' * 40  # 分隔符

    for name, cost in monthly_costs.items():
        # 价格右对齐,名字用固定宽度
        formatted_line = f"{name.ljust(max_name_length)} | {str(cost).rjust(8)} CNY\n"
        monthly_cost_display.insert(tk.END, formatted_line)

    monthly_cost_display.insert(tk.END, f"{separator}\n")
    monthly_cost_display.insert(tk.END, f"{'月度总成本'.ljust(max_name_length)} | {str(total_cost).rjust(8)} CNY")
    monthly_cost_display.config(state="disabled")

def calculate_monthly_cost(vps_list, rates):
    total_cost = 0.0
    costs = {}
    for vps in vps_list:
        amount = vps['amount'] / {'annual': 12, 'semi-annual': 6, 'quarterly': 3, 'monthly': 1}[vps['payment_cycle']]
        cost = round(amount * rates.get(vps['currency'], 1), 2)
        costs[vps['name']] = cost
        total_cost += cost
    return costs, round(total_cost, 2)

def clear_vps_fields():
    vps_name_var.set("")
    amount_var.set("")
    payment_cycle_var.set("annual")
    currency_var.set("USD")

# =============== 主窗口与布局 ===============
root = tk.Tk()
root.title("VPS 成本管理")
root.geometry("900x600")  # 窗口大小

config = load_config()

# =========== 左侧:汇率设置 ===========
left_frame = tk.LabelFrame(root, text="汇率设置", padx=10, pady=10)
left_frame.pack(fill="y", side="left", padx=10, pady=10)

currency_rate_vars = {}
for idx, (currency, rate) in enumerate(config['exchange_rates'].items()):
    tk.Label(left_frame, text=f"{currency} 汇率:").grid(row=idx, column=0, sticky="e", pady=5)
    rate_var = tk.StringVar(value=str(rate))
    currency_rate_vars[currency] = rate_var
    tk.Entry(left_frame, textvariable=rate_var, width=10).grid(row=idx, column=1, pady=5)
tk.Button(left_frame, text="更新汇率", command=update_exchange_rates).grid(columnspan=2, pady=10)

# =========== 中间:VPS 管理 ===========
middle_frame = tk.LabelFrame(root, text="VPS 管理", padx=10, pady=10)
middle_frame.pack(fill="both", expand=True, side="left", padx=10, pady=10)

vps_name_var, amount_var = tk.StringVar(), tk.StringVar()
payment_cycle_var, currency_var = tk.StringVar(value="annual"), tk.StringVar(value="USD")

# 输入框
tk.Label(middle_frame, text="名称:").grid(row=0, column=0, sticky="e")
tk.Entry(middle_frame, textvariable=vps_name_var).grid(row=0, column=1, pady=5)
tk.Label(middle_frame, text="费用:").grid(row=1, column=0, sticky="e")
tk.Entry(middle_frame, textvariable=amount_var).grid(row=1, column=1, pady=5)

tk.Label(middle_frame, text="周期:").grid(row=2, column=0, sticky="e")
ttk.Combobox(middle_frame, textvariable=payment_cycle_var, values=["annual", "semi-annual", "quarterly", "monthly"]).grid(row=2, column=1)

tk.Label(middle_frame, text="货币:").grid(row=3, column=0, sticky="e")
ttk.Combobox(middle_frame, textvariable=currency_var, values=["USD", "CNY", "EUR"]).grid(row=3, column=1)

tk.Button(middle_frame, text="添加 VPS", command=add_vps).grid(columnspan=2, pady=10)

# 列表框
vps_listbox = tk.Listbox(middle_frame, width=45, height=15)
vps_listbox.grid(row=5, columnspan=2, pady=10)
tk.Button(middle_frame, text="删除选中", command=delete_vps).grid(columnspan=2, pady=5)

# =========== 右侧:成本展示 ===========
right_frame = tk.LabelFrame(root, text="每月成本", padx=10, pady=10)
right_frame.pack(fill="y", side="right", padx=10, pady=10)

monthly_cost_display = tk.Text(right_frame, width=42, height=40, state="disabled")
monthly_cost_display.pack()

# 初始化显示
update_vps_list()
update_monthly_costs()
root.mainloop()
0

评论 (0)

取消