nicegui网页多用户数据隔离总结
python
import sqlite3
from nicegui import ui
# === 全局状态 ===
selected_user = None
sche_grid = None
# === 初始化数据库 ===
def init_db():
conn = sqlite3.connect('example.db')
cur = conn.cursor()
cur.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
name TEXT,
age INTEGER, -- 密码(数字形式)
role TEXT,
email TEXT,
phone TEXT -- 👈 新增电话字段
)
''')
# 安全添加缺失的列(兼容旧版本)
cur.execute("PRAGMA table_info(users)")
columns = [col[1] for col in cur.fetchall()]
if 'email' not in columns:
cur.execute('ALTER TABLE users ADD COLUMN email TEXT')
if 'phone' not in columns:
cur.execute('ALTER TABLE users ADD COLUMN phone TEXT')
# 插入初始数据(如果表为空)
cur.execute('SELECT COUNT(*) FROM users')
if cur.fetchone()[0] == 0:
# 注意:现在把手机号放到 phone,密码设为 123456
cur.executemany(
'INSERT INTO users (name, age, role, email, phone) VALUES (?, ?, ?, ?, ?)',
[('李建红', 123456, '一级经销商', 'lijianhong@example.com', '18682956289')]
)
conn.commit()
conn.close()
init_db()
# === 数据访问函数 ===
def load_users():
conn = sqlite3.connect('example.db')
conn.row_factory = sqlite3.Row
rows = conn.execute('SELECT * FROM users').fetchall()
conn.close()
return [
{
'id': int(r['id']),
'name': str(r['name']) if r['name'] else '',
'age': int(r['age']) if r['age'] is not None else 0, # 密码
'role': str(r['role']) if r['role'] else '',
'email': str(r['email']) if r['email'] else '',
'phone': str(r['phone']) if r['phone'] else ''
}
for r in rows
]
def get_user_by_id(user_id):
conn = sqlite3.connect('example.db')
conn.row_factory = sqlite3.Row
row = conn.execute('SELECT * FROM users WHERE id = ?', (user_id,)).fetchone()
conn.close()
if row:
return {
'id': int(row['id']),
'name': str(row['name']) if row['name'] else '',
'age': int(row['age']) if row['age'] is not None else 0,
'role': str(row['role']) if row['role'] else '',
'email': str(row['email']) if row['email'] else '',
'phone': str(row['phone']) if row['phone'] else ''
}
return None
def update_user(user_id, name, age, role, email, phone):
conn = sqlite3.connect('example.db')
conn.execute('UPDATE users SET name=?, age=?, role=?, email=?, phone=? WHERE id=?',
(name, age, role, email, phone, user_id))
conn.commit()
conn.close()
def insert_user(name, age, role, email='', phone=''):
conn = sqlite3.connect('example.db')
cur = conn.cursor()
cur.execute('INSERT INTO users (name, age, role, email, phone) VALUES (?, ?, ?, ?, ?)',
(name, age, role, email, phone))
conn.commit()
conn.close()
# === 编辑对话框 ===
edit_dialog = None
name_input = age_input = role_select = email_input = phone_input = None
current_editing_id = None
def open_edit_dialog_by_id(user_id):
global edit_dialog, name_input, age_input, role_select, email_input, phone_input, current_editing_id
user = get_user_by_id(user_id)
if not user:
ui.notify('❌ 用户不存在', type='negative')
return
current_editing_id = user_id
if edit_dialog:
edit_dialog.close()
with ui.dialog() as edit_dialog, ui.card():
ui.label(f'编辑用户 ID: {user_id}').classes('text-lg font-bold')
name_input = ui.input('用户名', value=user['name'])
age_input = ui.input('密码', value=str(user['age']))
role_select = ui.select(['厂商', '一级经销商', '二级经销商'], label='权限', value=user['role'])
email_input = ui.input('上一级账号', value=user['email'])
phone_input = ui.input('加密', value=user['phone'])
with ui.row():
ui.button('保存', on_click=confirm_update)
ui.button('取消', on_click=edit_dialog.close)
edit_dialog.open()
def confirm_update():
try:
new_age = int(age_input.value) if age_input.value.isdigit() else 0
except:
new_age = 0
new_data = {
'name': name_input.value or '',
'age': new_age,
'role': role_select.value or '',
'email': email_input.value or '',
'phone': phone_input.value or ''
}
user = get_user_by_id(current_editing_id)
lines = ['你确定要保存以下更改吗?', '\n原值 → 新值:']
for key, label in [('name', '用户名'), ('age', '密码'), ('role', '权限'), ('email', '上一级账号'), ('phone', '加密')]:
old = user[key]
new = new_data[key]
if old != new:
lines.append(f'• {label}: {old} → {new}')
else:
lines.append(f'• {label}: {old} (未变)')
message = '\n'.join(lines)
with ui.dialog() as d, ui.card():
ui.label(message).classes('whitespace-pre-line')
with ui.row():
ui.button('确认修改', on_click=lambda: [
do_update(new_data), d.close(), edit_dialog.close()
])
ui.button('取消', on_click=d.close)
d.open()
def do_update(new_data):
update_user(
current_editing_id,
new_data['name'],
new_data['age'],
new_data['role'],
new_data['email'],
new_data['phone']
)
refresh_table()
ui.notify('✅ 更新成功!')
# === 新增对话框 ===
add_dialog = None
add_name_input = add_age_input = add_role_select = add_email_input = add_phone_input = None
def open_add_dialog():
global add_dialog, add_name_input, add_age_input, add_role_select, add_email_input, add_phone_input
if add_dialog:
add_dialog.close()
with ui.dialog() as add_dialog, ui.card():
ui.label('新增用户').classes('text-lg font-bold')
add_name_input = ui.input('用户名', placeholder='请输入用户名')
add_age_input = ui.number('密码', value=123456, min=0, max=99999999)
add_role_select = ui.select(['厂商', '一级经销商', '二级经销商'], label='权限', value='二级经销商')
add_email_input = ui.input('上一级账号', placeholder='可选')
add_phone_input = ui.input('加密', placeholder='例如:13800138000')
with ui.row():
ui.button('提交', on_click=handle_add_submit)
ui.button('取消', on_click=add_dialog.close)
add_dialog.open()
def handle_add_submit():
name = add_name_input.value or ''
age = add_age_input.value if add_age_input.value is not None else 123456
role = add_role_select.value or '访客'
email = add_email_input.value or ''
phone = add_phone_input.value or ''
if not name.strip():
ui.notify('❌ 用户名不能为空', type='negative')
return
insert_user(name, age, role, email, phone)
add_dialog.close()
refresh_table()
ui.notify('✅ 新增用户成功!')
# === AG Grid 事件处理 ===
def on_cell_clicked(e):
global selected_user
selected_user = e.args.get('data', None)
# === 构建 AG Grid 表格 ===
def build_aggrid():
global sche_grid
users = load_users()
sche_col = [
{'headerName': 'ID', 'field': 'id', 'width': 70, 'sortable': True},
{'headerName': '用户名', 'field': 'name', 'width': 110, 'sortable': True},
{'headerName': '密码', 'field': 'age', 'width': 90, 'sortable': True},
{'headerName': '权限', 'field': 'role', 'width': 110, 'sortable': True},
{'headerName': '上一级账号', 'field': 'email', 'width': 160, 'sortable': True},
{'headerName': '加密', 'field': 'phone', 'width': 120, 'sortable': True}, # 👈 新增列
]
if sche_grid is None:
sche_grid = ui.aggrid({
'columnDefs': sche_col,
'rowData': users,
'rowSelection': 'single',
'animateRows': True,
'pagination': True,
'paginationPageSize': 10,
'defaultColDef': {
'editable': False,
'sortable': True,
'filter': False,
'resizable': True
},
'autoHeight': False
}).style('height: 600px; width: 90%; justify-self: start;')
sche_grid.on('cellClicked', on_cell_clicked)
else:
sche_grid.options['rowData'] = users
sche_grid.update()
def refresh_table():
build_aggrid()
def get_selected_user_id():
if selected_user is not None:
return selected_user.get('id')
return None
def handle_edit_selected():
user_id = get_selected_user_id()
if user_id is None:
ui.notify('❌ 请先点击表格中的某一行以选择用户', type='warning')
return
open_edit_dialog_by_id(user_id)
# === UI 布局 ===
with ui.column().classes('w-full items-start p-4'):
build_aggrid()
with ui.row().classes('mb-4 gap-2'):
ui.button('新增用户', on_click=open_add_dialog)
ui.button('编辑选中用户', on_click=handle_edit_selected)
ui.button('刷新', on_click=refresh_table).classes('mt-4')
# 启动应用
ui.run()
里插入图片描述](https://i-blog.csdnimg.cn/direct/e807f85fa51f40f09b3eb1f6069d73db.png)
这里插入图片描述](https://i-blog.csdnimg.cn/direct/062fb5d3d084456289c50b5590c2480b.png)

