你提供的代码没有完整,`chpwd` 方法里的 SQL 语句未写完。不过从现有的代码来看,这是一个使用 Python 和 PyQt5 开发的养老机构财务管理系统。以下是对代码的一些分析和建议:
### 代码功能概述
1. **数据库初始化**:`init_db` 函数创建三个表:`users`、`subjects` 和 `vouchers`,并插入一些初始数据。
2. **登录界面**:`LoginDialog` 类实现了一个简单的登录界面,用户输入账号和密码,验证通过后进入主界面。
3. **主界面**:`MainWindow` 类包含多个选项卡,分别用于凭证录入、凭证审核、会计科目管理、凭证查询、自动报表生成、导入导出和用户管理。
### 问题修正与优化
1. **`chpwd` 方法补充**:完成 `chpwd` 方法,实现修改密码的功能。
```python
def chpwd(self):
old = QInputDialog.getText(self, "旧密码", "")[0]
new = QInputDialog.getText(self, "新密码", "")[0]
conn = sqlite3.connect("finance_pro.db")
c = conn.cursor()
c.execute("SELECT id FROM users WHERE username=? AND password=?", (self.user, old))
res = c.fetchone()
if res:
c.execute("UPDATE users SET password=? WHERE id=?", (new, res[0]))
conn.commit()
QMessageBox.information(self, "成功", "密码修改成功")
else:
QMessageBox.warning(self, "错误", "旧密码错误")
conn.close()
```
2. **错误处理**:在 `save_voucher`、`import_sub` 和 `import_vou` 等方法中,异常处理可以更具体,例如捕获 `ValueError` 等特定异常。
3. **代码复用**:可以将数据库连接和关闭的操作封装成函数,减少代码重复。
### 完整代码示例
```python
import sys
import sqlite3
from datetime import datetime
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from openpyxl import Workbook, load_workbook
def init_db():
conn = sqlite3.connect("finance_pro.db")
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS users
(id INTEGER PRIMARY KEY, username TEXT, password TEXT, role TEXT)''')
c.execute("INSERT OR IGNORE INTO users VALUES (null,'admin','123456','管理员')")
c.execute("INSERT OR IGNORE INTO users VALUES (null,'user','123456','普通用户')")
c.execute('''CREATE TABLE IF NOT EXISTS subjects
(id INTEGER PRIMARY KEY,code TEXT,name TEXT,type TEXT,level INTEGER,parent TEXT)''')
subjects = [
("1001", "财政专户存款", "资产类", 1, ""),
("100101", "基本账户", "资产类", 2, "1001"),
("1002", "其他应收款", "资产类", 1, ""),
("100201", "职工借款", "资产类", 2, "1002"),
("1003", "固定资产", "资产类", 1, ""),
("100301", "房屋建筑", "资产类", 2, "1003"),
("1004", "库存物资", "资产类", 1, ""),
("100401", "食品物资", "资产类", 2, "1004"),
("2001", "其他应付款", "负债类", 1, ""),
("3001", "事业基金", "净资产类", 1, ""),
("4001", "财政补助收入", "收入类", 1, ""),
("400101", "运行经费", "收入类", 2, "4001"),
("5001", "事业支出", "支出类", 1, ""),
("500101", "人员工资", "支出类", 2, "5001"),
("500102", "办公费用", "支出类", 2, "5001"),
]
c.executemany("INSERT OR IGNORE INTO subjects VALUES (null,?,?,?,?,?)", subjects)
c.execute('''CREATE TABLE IF NOT EXISTS vouchers
(id INTEGER PRIMARY KEY,date TEXT,code TEXT,debit_sub TEXT,credit_sub TEXT,
money REAL,note TEXT,status TEXT,create_user TEXT)''')
conn.commit()
conn.close()
STYLE = """
QMainWindow{background-color:#f5f7fa;}
QDialog{background-color:#ffffff;}
QTabBar::tab:selected{background:#2c4a7d;color:white;}
QPushButton{background-color:#2c4a7d;color:white;border:none;padding:10px 14px;border-radius:6px;}
QHeaderView::section{background-color:#2c4a7d;color:white;}
"""
class LoginDialog(QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle("系统登录")
self.setFixedSize(480, 360)
self.setStyleSheet(STYLE)
self.init_ui()
def init_ui(self):
layout = QVBoxLayout()
layout.setAlignment(Qt.AlignCenter)
title = QLabel("用户登录")
title.setStyleSheet("font-size:24px;font-weight:bold;color:#2c4a7d;")
self.user = QLineEdit()
self.user.setPlaceholderText("账号")
self.pwd = QLineEdit()
self.pwd.setPlaceholderText("密码")
self.pwd.setEchoMode(QLineEdit.Password)
btn = QPushButton("登 录")
btn.clicked.connect(self.check)
layout.addWidget(title)
layout.addWidget(self.user)
layout.addWidget(self.pwd)
layout.addWidget(btn)
self.setLayout(layout)
def check(self):
u = self.user.text()
p = self.pwd.text()
conn = sqlite3.connect("finance_pro.db")
c = conn.cursor()
c.execute("SELECT role FROM users WHERE username=? AND password=?", (u, p))
res = c.fetchone()
conn.close()
if res:
self.current_role = res[0]
self.accept()
else:
QMessageBox.warning(self, "错误", "账号或密码错误")
class MainWindow(QMainWindow):
def __init__(self, username, role):
super().__init__()
self.user = username
self.role = role
self.setWindowTitle("养老机构财务管理系统")
self.setGeometry(100, 100, 1200, 800)
self.setStyleSheet(STYLE)
init_db()
self.init_ui()
def init_ui(self):
tabs = QTabWidget()
tabs.addTab(self.tab1_voucher(), "📝 凭证录入")
tabs.addTab(self.tab2_check(), "✅ 凭证审核")
tabs.addTab(self.tab3_subject(), "📊 会计科目")
tabs.addTab(self.tab4_query(), "🧾 凭证查询")
tabs.addTab(self.tab5_report(), "📈 自动报表")
tabs.addTab(self.tab6_import_export(), "📤 导入导出")
tabs.addTab(self.tab7_user(), "👤 用户管理")
self.setCentralWidget(tabs)
def tab1_voucher(self):
w = QWidget()
g = QFormLayout(w)
self.d = QDateEdit(QDate.currentDate())
self.code = QLineEdit()
self.debit = QComboBox()
self.credit = QComboBox()
self.money = QLineEdit()
self.note = QTextEdit()
self.refresh_subject_combo()
btn = QPushButton("保存凭证")
btn.clicked.connect(self.save_voucher)
g.addRow("日期", self.d)
g.addRow("凭证号", self.code)
g.addRow("借方科目", self.debit)
g.addRow("贷方科目", self.credit)
g.addRow("金额", self.money)
g.addRow("备注", self.note)
g.addRow("", btn)
return w
def refresh_subject_combo(self):
self.debit.clear()
self.credit.clear()
conn = sqlite3.connect("finance_pro.db")
c = conn.cursor()
c.execute("SELECT name FROM subjects ORDER BY code")
for i in c.fetchall():
self.debit.addItem(i[0])
self.credit.addItem(i[0])
conn.close()
def save_voucher(self):
try:
conn = sqlite3.connect("finance_pro.db")
c = conn.cursor()
c.execute('''INSERT INTO vouchers
(date,code,debit_sub,credit_sub,money,note,status,create_user)
VALUES (?,?,?,?,?,?,'未审核',?)''', (
self.d.date().toString("yyyy-MM-dd"),
self.code.text(),
self.debit.currentText(),
self.credit.currentText(),
float(self.money.text() or 0),
self.note.toPlainText(),
self.user
))
conn.commit()
conn.close()
QMessageBox.information(self, "成功", "已保存")
except ValueError:
QMessageBox.warning(self, "错误", "金额格式错误")
except Exception as e:
QMessageBox.warning(self, "错误", f"发生未知错误: {e}")
def tab2_check(self):
w = QWidget()
l = QVBoxLayout(w)
self.check_table = QTableWidget()
self.check_table.setColumnCount(8)
self.check_table.setHorizontalHeaderLabels(["日期", "凭证号", "借方", "贷方", "金额", "备注", "状态", "制单人"])
btn1 = QPushButton("刷新")
btn2 = QPushButton("审核选中")
btn3 = QPushButton("反审核")
btn1.clicked.connect(self.load_check)
btn2.clicked.connect(lambda: self.set_status("已审核"))
btn3.clicked.connect(lambda: self.set_status("未审核"))
l.addWidget(btn1)
l.addWidget(btn2)
l.addWidget(btn3)
l.addWidget(self.check_table)
self.load_check()
return w
def load_check(self):
self.check_table.setRowCount(0)
conn = sqlite3.connect("finance_pro.db")
c = conn.cursor()
c.execute("SELECT date,code,debit_sub,credit_sub,money,note,status,create_user FROM vouchers")
for i, r in enumerate(c.fetchall()):
self.check_table.insertRow(i)
for j in range(8):
self.check_table.setItem(i, j, QTableWidgetItem(str(r[j])))
conn.close()
def set_status(self, s):
row = self.check_table.currentRow()
if row < 0: return
code = self.check_table.item(row, 1).text()
conn = sqlite3.connect("finance_pro.db")
c = conn.cursor()
c.execute("UPDATE vouchers SET status=? WHERE code=?", (s, code))
conn.commit()
conn.close()
self.load_check()
def tab3_subject(self):
w = QWidget()
l = QVBoxLayout(w)
self.t_sub = QTableWidget()
self.t_sub.setColumnCount(5)
self.t_sub.setHorizontalHeaderLabels(["编码", "名称", "类型", "级次", "上级编码"])
btn = QPushButton("新增二级科目")
btn.clicked.connect(self.add_sub)
l.addWidget(btn)
l.addWidget(self.t_sub)
self.load_sub()
return w
def load_sub(self):
self.t_sub.setRowCount(0)
conn = sqlite3.connect("finance_pro.db")
c = conn.cursor()
c.execute("SELECT code,name,type,level,parent FROM subjects ORDER BY code")
for i, r in enumerate(c.fetchall()):
self.t_sub.insertRow(i)
for j in range(5):
self.t_sub.setItem(i, j, QTableWidgetItem(str(r[j])))
conn.close()
def add_sub(self):
code = QInputDialog.getText(self, "编码", "例:100102")[0]
name = QInputDialog.getText(self, "名称", "")[0]
parent = QInputDialog.getText(self, "上级编码", "例:1001")[0]
if not code or not name:
return
conn = sqlite3.connect("finance_pro.db")
c = conn.cursor()
c.execute("INSERT INTO subjects VALUES (null,?,?,?,2,?)", (code, name, "资产类", parent))
conn.commit()
conn.close()
self.load_sub()
self.refresh_subject_combo()
def tab4_query(self):
w = QWidget()
l = QVBoxLayout(w)
self.t_q = QTableWidget()
self.t_q.setColumnCount(8)
self.t_q.setHorizontalHeaderLabels(["日期", "凭证号", "借方", "贷方", "金额", "备注", "状态", "制单人"])
btn = QPushButton("刷新")
btn.clicked.connect(self.load_query)
l.addWidget(btn)
l.addWidget(self.t_q)
self.load_query()
return w
def load_query(self):
self.t_q.setRowCount(0)
conn = sqlite3.connect("finance_pro.db")
c = conn.cursor()
c.execute("SELECT date,code,debit_sub,credit_sub,money,note,status,create_user FROM vouchers")
for i, r in enumerate(c.fetchall()):
self.t_q.insertRow(i)
for j in range(8):
self.t_q.setItem(i, j, QTableWidgetItem(str(r[j])))
conn.close()
def tab5_report(self):
w = QWidget()
l = QVBoxLayout(w)
btn1 = QPushButton("导出科目余额表")
btn2 = QPushButton("导出收支汇总表")
btn1.clicked.connect(self.report_balance)
btn2.clicked.connect(self.report_summary)
l.addWidget(btn1)
l.addWidget(btn2)
return w
def report_balance(self):
wb = Workbook()
ws = wb.active
ws.append(["科目编码", "科目名称", "借方", "贷方", "余额"])
conn = sqlite3.connect("finance_pro.db")
c = conn.cursor()
c.execute("SELECT code,name FROM subjects")
for code, name in c.fetchall():
c.execute("SELECT IFNULL(SUM(money),0) FROM vouchers WHERE debit_sub=?", (name,))
j = c.fetchone()[0]
c.execute("SELECT IFNULL(SUM(money),0) FROM vouchers WHERE credit_sub=?", (name,))
d = c.fetchone()[0]
ws.append([code, name, j, d, j - d])
conn.close()
wb.save("余额表.xlsx")
QMessageBox.information(self, "成功", "已导出:余额表.xlsx")
def report_summary(self):
wb = Workbook()
ws = wb.active
ws.append(["项目", "收入", "支出", "结余"])
conn = sqlite3.connect("finance_pro.db")
c = conn.cursor()
c.execute("SELECT IFNULL(SUM(money),0) FROM vouchers WHERE credit_sub LIKE '%收入%'")
i = c.fetchone()[0]
c.execute("SELECT IFNULL(SUM(money),0) FROM vouchers WHERE debit_sub LIKE '%支出%'")
o = c.fetchone()[0]
ws.append(["合计", i, o, i - o])
conn.close()
wb.save("收支表.xlsx")
QMessageBox.information(self, "成功", "已导出:收支表.xlsx")
def tab6_import_export(self):
w = QWidget()
l = QVBoxLayout(w)
l.addWidget(QPushButton("导出科目", self.export_sub))
l.addWidget(QPushButton("导出凭证", self.export_vou))
l.addWidget(QPushButton("导入科目", self.import_sub))
l.addWidget(QPushButton("导入凭证", self.import_vou))
return w
def export_sub(self):
wb = Workbook()
conn = sqlite3.connect("finance_pro.db")
c = conn.cursor()
for r in c.execute("SELECT * FROM subjects"):
wb.active.append(r)
conn.close()
wb.save("科目导出.xlsx")
QMessageBox.information(self, "成功", "已导出")
def export_vou(self):
wb = Workbook()
conn = sqlite3.connect("finance_pro.db")