代码拉取完成,页面将自动刷新
同步操作将从 liufeixiang/fx_sys 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
from nicegui import ui
import sqlite3
import datetime
from decimal import Decimal
from openpyxl import Workbook,load_workbook
from openpyxl.styles import PatternFill
from openpyxl.formatting.rule import CellIsRule
from openpyxl.utils import get_column_letter
sq=sqlite3.connect('FX.db')
c=sq.cursor()
#数据库表创建
def db_create():
#用户列表
c.execute('''create table if not exists user(
id integer primary key autoincrement,
name text,
password text,
department text,
role text)''')
#单号信息列表 finishtime createtime
c.execute('''create table if not exists sn(
id integer primary key autoincrement,
infoid int,
mohao text,
type text,
duanbie text,
ctime text,
ftime text,
op text,
state text,
beizhu text)''')
#实际数据存储列表
c.execute('''create table if not exists sdata(
id integer primary key autoincrement,
infoid int,
dimid int,
snid int,
value text,
role text)''')
#数据尺寸库列表
c.execute('''create table if not exists data(
id integer primary key autoincrement,
infoid int,
faino text,
cpkno text,
type text,
tool text,
normal text,
tolu text,
toll text,
remark text,
location text,
dimtype text,
creater text,
beizhu text)''')
#维护表单列表
c.execute('''create table if not exists info(
id integer primary key autoincrement,
mohao text,
liaohao text,
tuhao text,
duanbie text,
sipno text,
sipver text,
cav int,
freq int,
creater text,
build text,
customer text,
beizhu text)''')
#log日志表单
c.execute('''create table if not exists log(
id integer primary key autoincrement,
time text,
tab text,
func text,
op text,
content text)''')
sq.commit()
db_create()#创建数据库
#控制图用的系数换算*_*有点尴尬
def get_a2(num):
A2=0
if num==2:
A2=1.88
elif num==3:
A2=1.023
elif num==4:
A2=0.729
elif num==5:
A2=0.577
elif num==6:
A2=0.483
elif num==7:
A2=0.149
elif num==8:
A2=0.373
elif num==9:
A2=0.337
elif num==10:
A2=0.308
elif num==11:
A2=0.285
elif num==12:
A2=0.266
elif num==13:
A2=0.249
elif num==14:
A2=0.235
elif num==15:
A2=0.223
elif num==16:
A2=0.212
elif num==17:
A2=0.203
elif num==18:
A2=0.194
elif num==19:
A2=0.187
elif num==20:
A2=0.18
elif num==21:
A2=0.173
elif num==22:
A2=0.167
elif num==23:
A2=0.162
elif num==24:
A2=0.157
elif num==25:
A2=0.153
return A2
def get_d3(num):
D3=0
if num==2:
D3=""
elif num==3:
D3=""
elif num==4:
D3=""
elif num==5:
D3=""
elif num==6:
D3=""
elif num==7:
D3=0.076
elif num==8:
D3=0.136
elif num==9:
D3=0.184
elif num==10:
D3=0.223
elif num==11:
D3=0.256
elif num==12:
D3=0.283
elif num==13:
D3=0.307
elif num==14:
D3=0.328
elif num==15:
D3=0.347
elif num==16:
D3=0.363
elif num==17:
D3=0.738
elif num==18:
D3=0.391
elif num==19:
D3=0.403
elif num==20:
D3=0.415
elif num==21:
D3=0.425
elif num==22:
D3=0.434
elif num==23:
D3=0.443
elif num==24:
D3=0.451
elif num==25:
D3=0.459
return D3
def get_d4(num):
D4=0
if num==2:
D4=3.276
elif num==3:
D4=2.574
elif num==4:
D4=2.282
elif num==5:
D4=2.114
elif num==6:
D4=2.004
elif num==7:
D4=1.924
elif num==8:
D4=1.864
elif num==9:
D4=1.816
elif num==10:
D4=1.777
elif num==11:
D4=1.744
elif num==12:
D4=1.717
elif num==13:
D4=1.693
elif num==14:
D4=1.672
elif num==15:
D4=1.653
elif num==16:
D4=1.637
elif num==17:
D4=1.622
elif num==18:
D4=1.608
elif num==19:
D4=1.597
elif num==20:
D4=1.585
elif num==21:
D4=1.575
elif num==22:
D4=1.566
elif num==23:
D4=1.557
elif num==24:
D4=1.548
elif num==25:
D4=1.541
return D4
######全局变量 重要
if_log_in = False##是否登录
authority=""##权限
USER_NAME=""##用户名
LOCAL_PAGE=""#定义当前页面
##################
c.execute("INSERT INTO user (name,password,department,role) VALUES (?,?,?,?)", ('FX',"123","QE","管理员"))#数据库新建保证有一个管理员,后续注释或删除掉
sq.commit()
def quit():
# 显示退出成功的通知
ui.notify('退出成功')
# 修改全局变量
global if_log_in, USER_NAME, authority
#增加退出信息入log表
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "NA", "quit", USER_NAME,"退出登录"))
sq.commit()
if_log_in = False
USER_NAME = ""
authority = ""
# 导航到登录页面
ui.navigate.to('/login')
###################################################登录页面####################################################################
@ui.page('/login')
def page_login():
# 设置主色调
ui.colors(primary="#1A6F78")
# 设置页面背景色
ui.query('body').style('background-color: #7DB9DE')
# 设置页面头部
with ui.header(elevated=True).style('background-color: #1A5F68').classes('items-center'):
# 设置页面标题链接
ui.link('FX智能数据系统','#').style("color: white;text-decoration:none;font-size:20px")
# 设置页面底部
with ui.footer().style('background-color: #1A5F58'):
# 设置版权信息
ui.label('Copyright © 2024 Feixiang Technology Co., Ltd. All Rights Reserved')
# 设置页面标题
ui.page_title('FX智能数据系统-系统登录')
# 定义密码检查函数
async def check_password()->None:
# 获取用户名和密码
user_name = user.value
pw = password.value
# 查询用户是否存在
QUERY="SELECT * FROM user WHERE name=?"
c.execute(QUERY, (user_name,))
if c.fetchone() is None:
ui.notify('用户不存在')
else:
# 查询用户名和密码是否匹配
c.execute("SELECT * FROM user WHERE name=? AND password=?", (user_name,pw))
if c.fetchone() is None:
ui.notify('密码错误')
else:
# 定义全局变量
global if_log_in, USER_NAME, authority # 定义全局变量
if_log_in = True
USER_NAME=user_name
authority=c.execute("SELECT role FROM user WHERE name=?", (user_name,)).fetchone()[0]
ui.notify('登陆成功')
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "NA", "login", USER_NAME,"登录系统"))
sq.commit()
if authority=='管理员':
ui.notify('欢迎回家,尊贵的管理员')
ui.navigate.to('/')
# 设置登录页面布局
with ui.column().style('display:grid;place-items:center;width:100%;padding:0px'):
# 设置图片
ui.image('https://www.helloimg.com/i/2024/12/20/6765674af01ce.png').style("width:300px")
# 设置用户名输入框
user=ui.input('用户名').style('width:300px;')
# 设置密码输入框
password=ui.input('密码', password=True, password_toggle_button=True).style('width:300px')
# 设置登录按钮
ui.button('登录', on_click=check_password).style('width:300px;')
###################################################欢迎页面####################################################################
@ui.page('/')
def page_index():
# 设置全局变量LOCAL_PAGE的值为"index"
global LOCAL_PAGE
LOCAL_PAGE="index"
# 调用page_layout函数,进行页面布局
page_layout()
# 设置页面标题为'FX智能数据系统'
ui.page_title('FX智能数据系统')
# 显示通知,内容为'欢迎来到FX智能数据系统'
ui.notify('欢迎来到FX智能数据系统')
# 显示标签,内容为'欢迎来到FX智能数据系统'
ui.label('欢迎来到FX智能数据系统').style('font-size:50px;color:white;font-weight:bold;margin:50px')
with ui.row().style('width:100%'):
with ui.column().style('width:24%'):
ui.image('https://s21.ax1x.com/2024/12/21/pAObP9x.jpg')
ui.label('资料管理').style("font-size:30px;color:#FFFFFF;font-weight:bold")
ui.label('''创建字段丰富的资料,包含客户名,制程段别,SIP编号,版本控制。''').style('color:#DBD0E6;font-size:20px')
ui.label('可根据资料创建多笔尺寸资料,涵盖多项参数,供后续数据处理。').style('color:#DBD0E6;font-size:20px')
with ui.column().style('width:24%'):
ui.image('https://s21.ax1x.com/2024/12/21/pAObkjO.jpg')
ui.label('单号管理').style("font-size:30px;color:#FFFFFF;font-weight:bold")
ui.label('''便捷的单号创建流程,可进行巡检和委托量测申请。''').style('color:#DBD0E6;font-size:20px')
ui.label('一键排程,提供数据上传模板,根据上传模板快速提交量测数据。').style('color:#DBD0E6;font-size:20px')
ui.label('直观的Highcharts图表,By制程段别显示当前量测任务状态。').style('color:#DBD0E6;font-size:20px')
with ui.column().style('width:24%'):
ui.image('https://s21.ax1x.com/2024/12/21/pAObEuD.jpg')
ui.label('数据导出').style("font-size:30px;color:#FFFFFF;font-weight:bold")
ui.label('''基于Openpyxl强大的Excel导出功能,可实现单笔或多笔批量导出。''').style('color:#DBD0E6;font-size:20px')
ui.label('尺寸超出规格的数据会高亮显示,醒目直观。').style('color:#DBD0E6;font-size:20px')
with ui.column().style('width:24%'):
ui.image('https://s21.ax1x.com/2024/12/21/pAObVDe.jpg')
ui.label('图表生成').style("font-size:30px;color:#FFFFFF;font-weight:bold")
ui.label('''专业的控制图生成工具,依据ASTM-STP-15D标准。''').style('color:#DBD0E6;font-size:20px')
ui.label('通过选择日期区间,自动By尺寸生成X-Bar Chart和R Chart。').style('color:#DBD0E6;font-size:20px')
###################################################维护页面####################################################################
@ui.page('/sheet')
def page_sheet():
# 设置全局变量LOCAL_PAGE的值为"sheet"
global LOCAL_PAGE
LOCAL_PAGE="sheet"
# 调用page_layout函数
page_layout()
# 初始化local_info为None
local_info=None
# 定义dim_fresh函数,用于刷新尺寸数据
def dim_fresh()->None:
global local_info
# 清空dim_row列表
dim_row.clear()
# 执行SQL查询,获取指定infoid的数据
c.execute("SELECT * FROM data WHERE infoid=?", (str(local_info),))
# 获取查询结果
data = c.fetchall()
# 遍历查询结果
for row in data:
# 创建一个字典x,存储每行数据
x={
'Id': row[0],
'FAI编号': row[2],
'CPK编号': row[3],
'数据类型': row[4],
'检验工具': row[5],
'标准值': row[6],
'规格上公差': row[7],
'规格下公差': row[8],
'项目说明': row[9],
'图档位置': row[10],
'尺寸类型': row[11],
'录入单位': row[12],
'备注信息': row[13]
}
# 将字典x添加到dim_row列表中
dim_row.append(x)
# 定义info_fresh函数,用于刷新信息数据
def info_fresh()->None:
# 清空info_row列表
info_row.clear()
# 执行SQL查询,获取所有信息数据
c.execute("SELECT * FROM info")
# 获取查询结果
data = c.fetchall()
# 遍历查询结果
for row in data:
# 创建一个字典x,存储每行数据
x={
'id': row[0],
'模号': row[1],
'FX料号': row[2],
'图号': row[3],
'制程段': row[4],
'SIP编号': row[5],
'SIP版本': row[6],
'穴数': row[7],
'巡检频率': row[8],
'SIP制作人': row[9],
'Build阶段': row[10],
'客户': row[11],
'备注': row[12]
}
# 将字典x添加到info_row列表中
info_row.append(x)
# 定义异步函数new_info,用于新增信息数据
async def new_info()->None:
# 执行SQL插入操作
c.execute("INSERT INTO info (mohao,liaohao,tuhao,duanbie,sipno,sipver,cav,freq,creater,build,customer,beizhu) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)", ("","","","","","",0,0,"","","",""))
# 提交事务
sq.commit()
# 刷新信息数据
info_fresh()
# 更新信息表格
info_grid.update()
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "info", "create", USER_NAME,"增加一条空白记录"))
sq.commit()
# 定义异步函数delete_info,用于删除信息数据
async def delete_info()->None:
# 获取选中的信息行
select_info=await info_grid.get_selected_row()
# 如果选中了行
if select_info:
# 执行SQL删除操作
c.execute("DELETE FROM info WHERE id=?", (select_info['id'],))
# 提交事务
sq.commit()
# 刷新信息数据
info_fresh()
# 更新信息表格
info_grid.update()
# 显示通知
ui.notification('删除成功')
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "info", "delete", USER_NAME,"删除了id为{}的记录".format(select_info['id'])))
sq.commit()
else:
# 显示未选择行的通知
ui.notification('未选择行')
# 定义异步函数fresh_info,用于更新信息数据
async def fresh_info()->None:
# 获取选中的信息行
select_info=await info_grid.get_selected_row()
# 如果选中了行
if select_info:
# 执行SQL更新操作
c.execute("UPDATE info SET mohao=?,liaohao=?,tuhao=?,duanbie=?,sipno=?,sipver=?,cav=?,freq=?,creater=?,build=?,customer=?,beizhu=? WHERE id=?", (select_info['模号'],select_info['FX料号'],select_info['图号'],select_info['制程段'],select_info['SIP编号'],select_info['SIP版本'],select_info['穴数'],select_info['巡检频率'],select_info['SIP制作人'],select_info['Build阶段'],select_info['客户'],select_info['备注'],select_info['id']))
# 提交事务
sq.commit()
# 刷新信息数据
info_fresh()
# 更新信息表格
info_grid.update()
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "info", "update", USER_NAME,"更新了id为{}的记录".format(select_info['id'])))
sq.commit()
# 定义异步函数new_item,用于新增尺寸数据
async def new_item()->None:
global local_info
# 执行SQL插入操作
c.execute("INSERT INTO data (infoid,faino,cpkno,type,tool,normal,tolu,toll,remark,location,dimtype,creater,beizhu) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)", (local_info,'','','','','','','','','','','',''))
# 提交事务
sq.commit()
# 刷新尺寸数据
dim_fresh()
# 更新尺寸表格
dim_grid.update()
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "data", "create", USER_NAME,"增加了一条空白记录"))
sq.commit()
# 定义异步函数fresh_item,用于更新尺寸数据
async def fresh_item()->None:
# 获取选中的尺寸行
selected=await dim_grid.get_selected_row()
# 如果选中了行
if selected:
# 执行SQL更新操作
c.execute("UPDATE data SET faino=?,cpkno=?,type=?,tool=?,normal=?,tolu=?,toll=?,remark=?,location=?,dimtype=?,creater=?,beizhu=? WHERE id=?", (selected['FAI编号'],selected['CPK编号'],selected['数据类型'],selected['检验工具'],selected['标准值'],selected['规格上公差'],selected['规格下公差'],selected['项目说明'],selected['图档位置'],selected['尺寸类型'],selected['录入单位'],selected['备注信息'],selected['Id']))
# 提交事务
sq.commit()
# 刷新尺寸数据
dim_fresh()
# 更新尺寸表格
dim_grid.update()
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "data", "update", USER_NAME,"更新了id为{}的记录".format(selected['Id'])))
sq.commit()
# 定义异步函数delete_item,用于删除尺寸数据
async def delete_item()->None:
# 获取选中的尺寸行
select_item=await dim_grid.get_selected_row()
# 如果选中了行
if select_item:
# 执行SQL删除操作
c.execute("DELETE FROM data WHERE id=?", (select_item['Id'],))
# 提交事务
sq.commit()
# 刷新尺寸数据
dim_fresh()
# 更新尺寸表格
dim_grid.update()
# 显示通知
ui.notification('删除成功')
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "data", "delete", USER_NAME,"删除了id为{}的记录".format(select_item['Id'])))
sq.commit()
else:
# 显示未选择行的通知
ui.notification('未选择行')
# 定义异步函数load_info,用于加载信息数据
async def load_info()->None:
# 设置全局变量local_info的值
global local_info
# 获取选中的信息行
select_info=await info_grid.get_selected_row()
# 如果选中了行
if select_info:
# 设置local_info的值
local_info=select_info['id']
# 显示通知
ui.notification('已加载'+str(local_info))
# 刷新尺寸数据
dim_fresh()
# 更新尺寸表格
dim_grid.update()
########################################################################页面初始化
# 设置页面标题
ui.page_title('FX智能数据系统-资料维护')
###########################################################################资料维护
# 显示标签“已维护资料”
ui.label('已维护资料')
# 定义信息表格的列定义
info_col=[
{'field': 'id'},
{'field': '模号'},
{'field': 'FX料号'},
{'field': '图号'},
{'field': '制程段'},
{'field': 'SIP编号'},
{'field': 'SIP版本'},
{'field': '穴数'},
{'field': '巡检频率'},
{'field': 'SIP制作人'},
{'field': 'Build阶段'},
{'field': '客户'},
{'field': '备注'}
]
# 初始化info_row列表
info_row=[]
# 刷新信息数据
info_fresh()
# 创建信息表格
info_grid = ui.aggrid({
'columnDefs': info_col,
'rowData': info_row,
'rowSelection':'single',
'pagination':True,
'paginationPageSize':7,
'defaultColDef':{'editable': True},
}
)
# 创建一行布局,并设置宽度为100%
with ui.row().style('width:100%'):
# 创建“新增”按钮,并绑定new_info函数
ui.button('新增',on_click=new_info)
# 创建“更新”按钮,并绑定fresh_info函数
ui.button('更新',on_click=fresh_info)
# 创建“删除”按钮,并绑定delete_info函数
ui.button('删除',on_click=delete_info)
# 创建“加载”按钮,并绑定load_info函数
ui.button('加载',on_click=load_info)
##################################################################################尺寸清单维护
# 显示标签“尺寸清单”
ui.label('尺寸清单')
# 定义尺寸表格的列定义
dim_col=[
{'field':"Id"},
{'field': 'FAI编号'},
{'field': 'CPK编号'},
{'field': '数据类型'},
{'field': '检验工具'},
{'field': '标准值'},
{'field': '规格上公差'},
{'field': '规格下公差'},
{'field': '项目说明'},
{'field': '图档位置'},
{'field': '尺寸类型'},
{'field': '录入单位'},
{'field': '备注信息'}
]
# 初始化dim_row列表
dim_row=[]
# 创建尺寸表格
dim_grid=ui.aggrid(
{'columnDefs': dim_col,
'rowData': dim_row,
'rowSelection':'single',
'pagination':True,
'paginationPageSize':7,
'defaultColDef':{'editable': True},
}
)
# 创建一行布局,并设置宽度为100%
with ui.row().style('width:100%'):
# 创建“新增”按钮,并绑定new_item函数
ui.button('新增',on_click=new_item)
# 创建“更新”按钮,并绑定fresh_item函数
ui.button('更新',on_click=fresh_item)
# 创建“删除”按钮,并绑定delete_item函数
ui.button('删除',on_click=delete_item)
###################################################巡检页面####################################################################
@ui.page('/daily')
def page_daily():
global LOCAL_PAGE
LOCAL_PAGE='daily'
page_layout()
# 创建巡检投单函数
def creat_daily_sn()->None:
if len(mo.value)==0:
ui.notify('请输入模号')
else:
# 根据模号和段别去查询info表中对应的数据
c.execute("SELECT * FROM info WHERE mohao=? AND duanbie=?", (mo.value, duan.value))
info_data = c.fetchone()
if info_data is not None:
# 将查询到的数据赋值给相应的变量
liao.value = info_data[2]
sipv.value = info_data[6]
qtyy.value = info_data[7]
# 频率
freq = int(info_data[8])
infoid = info_data[0]
now_t = timeee.value
now_t_str = str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S"))
now_t_s = now_t_str[:10]
# 在sn表中用infoid对应infoid字段查询sn表中对应的数据
c.execute("SELECT * FROM sn WHERE infoid=?", (infoid,))
sn_data = c.fetchall()
if len(sn_data) == 0:
# 如果sn表中没有对应的数据,则插入新的数据
c.execute("INSERT INTO sn (infoid,mohao,type,duanbie,ctime,ftime,op,state,beizhu) VALUES (?,?,?,?,?,?,?,?,?)", (infoid, mo.value, "巡检", duan.value, now_t_str, "NA", "NA", "待量测", now_t))
sq.commit()
ui.notify('创建成功')
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "sn", "create", USER_NAME,"增加一笔巡检单号"))
sq.commit()
else:
# 如果sn表中有对应的数据,则进行进一步的判断
taken_num = 0
for sn_d in sn_data:
ctime = sn_d[5][:10]
if ctime == now_t_s:
taken_num += 1
if taken_num >= freq:
# 如果投测次数已经达到最大次数,则通知用户
ui.notify('今日已达到最大投测次数')
else:
# 查询今天这个节点是否有投测,如果有,也不能投
c.execute("SELECT * FROM sn WHERE infoid=? and beizhu=?", (infoid, now_t))
sn_data = c.fetchall()
if len(sn_data) == 0:
# 如果没有投测记录,则插入新的数据
c.execute("INSERT INTO sn (infoid,mohao,type,duanbie,ctime,ftime,op,state,beizhu) VALUES (?,?,?,?,?,?,?,?,?)", (infoid, mo.value, "巡检", duan.value, now_t_str, "NA", "NA", "待量测", now_t))
sq.commit()
ui.notify('创建成功')
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "sn", "create", USER_NAME,"增加一条空白记录"))
sq.commit()
else:
if_resist = False
for sn_d in sn_data:
ctime = sn_d[5][:10]
if ctime == now_t_s:
if_resist = True
break
if if_resist: # 该日期该节点已经投了
ui.notify('今日该节点已投测')
else:
# 如果今天该节点没有投测,则插入新的数据
c.execute("INSERT INTO sn (infoid,mohao,type,duanbie,ctime,ftime,op,state,beizhu) VALUES (?,?,?,?,?,?,?,?,?)", (infoid, mo.value, "巡检", duan.value, now_t_str, "NA", "NA", "待量测", now_t))
sq.commit()
ui.notify('创建成功')
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "sn", "create", USER_NAME,"增加一条空白记录"))
sq.commit()
else:
# 如果没有找到对应的信息,则通知用户
ui.notify('没有找到对应的信息')
# 设置页面标题
ui.page_title('FX智能数据系统-巡检投测')
# 设置页面标签
ui.label('巡检投测')
# 创建输入表单
with ui.row().style("width:100%"):
# 模号输入框
mo=ui.input(label="模号",placeholder="请输入模号").style("width:15%")
# FX料号输入框
liao=ui.input(label="FX料号",placeholder="无需输入,自动带出").style("width:15%")
# 投测段别选择框
duan=ui.select(options=["冲压","电镀","成型","装配"],label="投测段别",value="成型").style("width:15%")
# 投测节点选择框
timeee=ui.select(options=["08:00","10:00","12:00","14:00","16:00","18:00","20:00","22:00","00:00","02:00","04:00","06:00"],label="投测节点",value="08:00").style("width:15%")
# SIP版本输入框
sipv=ui.input(label="SIP版本",placeholder="无需输入,自动带出").style("width:15%")
# 投测数量输入框
qtyy=ui.input(label="投测数量",placeholder="无需输入,自动带出").style("width:15%")
# 创建投单按钮
ui.button(text="投单",on_click=creat_daily_sn).style("width:20%")
###################################################委托页面####################################################################
@ui.page('/request')
def page_request():
global LOCAL_PAGE
LOCAL_PAGE='request'
page_layout()
# 定义一个内部函数,用于创建请求序列号
def create_request_sn()->None:
if len(mo.value)==0:
# 提示用户输入模号
ui.notify('请输入模号')
elif len(qtyy.value)==0:
# 提示用户输入投测数量
ui.notify('请输入投测数量')
else:
# 根据模号和段别去查询info表中对应的数据
c.execute("SELECT * FROM info WHERE mohao=? AND duanbie=?", (mo.value, duan.value))
infos = c.fetchone()
if infos is None:
# 提示没有找到对应的信息
ui.notify('没有找到对应的信息')
else:
# 获取info表中对应数据的ID
infoid = infos[0]
# 设置物料值
liao.value = infos[2]
# 设置客户值
kehu.value = infos[11]
# 获取当前时间字符串
now_t_str = str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S"))
# 构建备注信息
beizhu_info = "投测数量:" + qtyy.value
# 向sn表中插入数据
c.execute("INSERT INTO sn (infoid,mohao,type,duanbie,ctime,ftime,op,state,beizhu) VALUES (?,?,?,?,?,?,?,?,?)", (infoid, mo.value, leixing.value, duan.value, now_t_str, "NA", "NA", "待量测", beizhu_info))
# 提交事务
sq.commit()
# 提示创建成功
ui.notify('创建成功')
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "sn", "create", USER_NAME,"增加一笔{}单号".format(leixing.value)))
sq.commit()
# 设置页面标题
ui.page_title('FX智能数据系统-委托量测')
# 显示标签
ui.label('委托量测')
# 创建一个行布局,并设置宽度为100%
with ui.row().style("width:100%"):
# 模号输入框
mo = ui.input(label="模号", placeholder="请输入模号").style("width:15%")
# FX料号输入框
liao = ui.input(label="FX料号", placeholder="无需输入,自动带出").style("width:15%")
# 投测段别选择框
duan = ui.select(options=["冲压", "电镀", "成型", "装配"], label="投测段别", value="成型").style("width:15%")
# 投测类型选择框
leixing = ui.select(options=["FAI", "CPK", "尺寸确认", "其他"], label="投测类型", value="尺寸确认").style("width:15%")
# 投测数量输入框
qtyy = ui.input(label="投测数量", placeholder="请输入投测数量").style("width:15%")
# 客户输入框
kehu = ui.input(label="客户", placeholder="无需输入,自动带出").style("width:15%")
# 投单按钮,点击时调用create_request_sn函数
ui.button(text="投单", on_click=create_request_sn).style("width:20%")
###################################################查询页面####################################################################
@ui.page('/query')
def page_query():
global LOCAL_PAGE
LOCAL_PAGE='query'
page_layout()
def xbar_chart():
if len(mohaoid.value)==0:
ui.notify('请输入模号')
else:
stime=date1.value#开始时间
etime=date2.value#结束时间
if len(stime)!=0 and len(etime)!=0:
d1=datetime.date(year=int(stime[:4]),month=int(stime[5:7]),day=int(stime[-2:]))
d2=datetime.date(year=int(etime[:4]),month=int(etime[5:7]),day=int(etime[-2:]))
if d1<=d2:
#在info表中根据mohaoid.value 对应mohao字段,duanbieid.value对应duanbie字段查询info表中对应的数据
c.execute("SELECT * FROM info WHERE mohao=? AND duanbie=?", (mohaoid.value,duanbieid.value))
infos=c.fetchone()
if infos is None:
ui.notify('没有找到对应的信息')
else:
info_id=infos[0]
sub_num=infos[7]#子组大小
A2=get_a2(sub_num)
D3=get_d3(sub_num)
D4=get_d4(sub_num)
#在sn表中根据info_id对应infoid字段,“已量测”对应state字段查询sn表中对应的数据
c.execute("SELECT * FROM sn WHERE infoid=? AND state=?", (info_id,'已量测'))
sn_data=c.fetchall()
if len(sn_data)==0:
ui.notify('没有找到对应的数据')
else:
sn_list=[]
for i in sn_data:
ct=i[5][:10]
cts=datetime.date(year=int(ct[:4]),month=int(ct[5:7]),day=int(ct[-2:]))
if cts>=d1 and cts<=d2:
sn_list.append([i[0],ct])#收集满足条件的单号和日期
#根据info_id对应infoid字段,"数值型"对应type字段查询data表中对应的数据
c.execute("SELECT * FROM data WHERE infoid=? AND type=?", (info_id,'数值型'))
data_data=c.fetchall()
if len(data_data)==0:
ui.notify('没有找到对应的数据')
else:
data_list=[]
for i_data in data_data:
data_list.append([i_data[0],i_data[2],Decimal(i_data[6])+Decimal(i_data[7]),Decimal(i_data[6])-Decimal(i_data[8])])#收集尺寸id,fai_no和尺寸上/下限
for dim in data_list:#By尺寸进行控制图绘制
dim_id=dim[0]
dim_fai=dim[1]
dim_usl=dim[2]
dim_lsl=dim[3]
date_list=[]
for sn in sn_list:
if sn[1] not in date_list:
date_list.append(sn[1])#先限定好日期
x_data=[]
r_data=[]
#开始By日期收集尺寸数据
for ddate in date_list:
local_date_data=[]
for sn in sn_list:
if sn[1]==ddate:#是想要的日期
#根据snid对应字段和dim_id对应字段在sdata里查询对应数据
c.execute("SELECT * FROM sdata WHERE snid=? AND dimid=?", (sn[0],dim_id))
local_data=c.fetchall()
if len(local_data)==0:
1
else:
#收集尺寸数据
for ld in local_data:
local_dim_data=float(ld[4])
local_date_data.append(local_dim_data)
avg=round(sum(local_date_data)/len(local_date_data),5)
rg=round(max(local_date_data)-min(local_date_data),5)
x_data.append(avg)
r_data.append(rg)
x_avg=round(sum(x_data)/len(x_data),5)
r_avg=round(sum(r_data)/len(r_data),5)
UCL=round(x_avg+2*A2*r_avg,5)
LCL=round(x_avg-2*A2*r_avg,5)
RUCL=round(D4*r_avg,5)
if sub_num>=7:
RLCL=round(D3*r_avg,5)
else:
RLCL=""
UCL_LIST=[]
LCL_LIST=[]
RUCL_LIST=[]
RLCL_LIST=[]
USL_LIST=[]
LSL_LIST=[]
CL_LIST=[]
RCL_LIST=[]
for i in range(len(x_data)):
UCL_LIST.append(UCL)
LCL_LIST.append(LCL)
RUCL_LIST.append(RUCL)
RLCL_LIST.append(RLCL)
USL_LIST.append(dim_usl)
LSL_LIST.append(dim_lsl)
CL_LIST.append(x_avg)
RCL_LIST.append(r_avg)
y_title="FAI"+dim_fai
with ui.row().style("width:100%"):
ui.highchart({
'title':{'text':'FX智能数据系统-尺寸控制图X-Bar Chart'},
'subtitle':{'text':y_title},
'chart':{'type':'line'},
'xAxis':{'categories': date_list},
'yAxis':{'title':y_title},
'series':[
{
'name':'UCL',
'color':'green',
'data':UCL_LIST,
'marker':{'symbol':'circle'},
},
{
'name':'LCL',
'color':'green',
'data':LCL_LIST,
'marker':{'symbol':'circle'},
},
{
'name':'USL',
'color':'red',
'data':USL_LIST,
'marker':{'symbol':'square'},
},
{
'name':'LSL',
'color':'red',
'data':LSL_LIST,
'marker':{'symbol':'square'},
},
{
'name':'CL',
'color':'black',
'marker':{'symbol':'circle'},
'data':CL_LIST
},
{
'name':y_title,
'color':'blue',
'data':x_data,
'marker':{'symbol':'diamond'},
},
]}
).style("width:49%")
if sub_num>=7:
ui.highchart({
'title':{'text':'FX智能数据系统-尺寸控制图R Chart'},
'subtitle':{'text':y_title},
'chart':{'type':'line'},
'xAxis':{'categories': date_list},
'yAxis':{'title':y_title},
'series':[
{
'name':'UCL',
'color':'green',
'marker':{'symbol':'circle'},
'data':RUCL_LIST
},
{
'name':'LCL',
'color':'green',
'marker':{'symbol':'circle'},
'data':RLCL_LIST
},
{
'name':'CL',
'color':'black',
'marker':{'symbol':'circle'},
'data':RCL_LIST
},
{
'name':y_title,
'color':'blue',
'marker':{'symbol':'diamond'},
'data':r_data
},
]}
).style("width:49%")
else:
ui.highchart({
'title':{'text':'FX智能数据系统-尺寸控制图R Chart'},
'subtitle':{'text':y_title},
'chart':{'type':'line'},
'xAxis':{'categories': date_list},
'yAxis':{'title':y_title},
'series':[
{
'name':'UCL',
'color':'green',
'marker':{'symbol':'circle'},
'data':RUCL_LIST
},
{
'name':'CL',
'color':'black',
'marker':{'symbol':'circle'},
'data':RCL_LIST
},
{
'name':y_title,
'marker':{'symbol':'diamond'},
'color':'blue',
'data':r_data
},
]}
).style("width:49%")
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "NA", "query", USER_NAME,"查看了日期为{}-{}的控制图".format(d1,d2)))
sq.commit()
else:
ui.notify('开始时间不能大于结束时间')
else:
ui.notify('请输入开始时间和结束时间')
def export_data():
if len(sn_id.value)!=0:#如果有填单号,则默认只查询对应单号的数据
c.execute("SELECT * FROM sdata WHERE snid=?", (sn_id.value,))
data=c.fetchall()
if data is not None:
datas=[]
for i in data:
#FAI序号,data
datas.append([i[2],i[4]])
c.execute("SELECT * FROM sdata WHERE snid=?", (sn_id.value,))
infos=c.fetchone()
if infos is not None:
local_info_id=infos[1]
local_sn_id=infos[3]
c.execute("SELECT * FROM info WHERE id=?", (local_info_id,))
info_info=c.fetchone()
mohao=info_info[1]
liaohao=info_info[2]
build=info_info[10]
c.execute("SELECT * FROM sn WHERE id=?", (local_sn_id,))
sn_info=c.fetchone()
st=sn_info[5]
ft=sn_info[6]
op=sn_info[7]
c.execute("SELECT * FROM data WHERE infoid=?", (local_info_id,))
datalist=c.fetchall()
data_list=[]
for j in datalist:
cpkno=j[3]
faino=j[2]
dimno=j[0]
nor=j[6]
tolu=j[7]
toll=j[8]
if j[4]=="数值型":
usl=Decimal(nor)+Decimal(tolu)
lsl=Decimal(nor)-Decimal(toll)
else:
usl=''
lsl=''
data_list.append([faino,cpkno,nor,tolu,toll,usl,lsl,dimno])
wb=Workbook()
ws=wb.active
#基础信息写入
ws.title='数据查询结果'
ws.append(['模号','料号','BUILD',"Note:低于规格下限蓝色填充标识,高于规格上限红色填充标识"])
ws.append([mohao,liaohao,build])
ws.append(['开始日期','结束日期','操作人'])
ws.append([st,ft,op])
ws.append(['单号'])
ws.cell(5,2).value="FAI序号"
ws.cell(6,2).value="CPK序号"
ws.cell(7,2).value="标准值"
ws.cell(8,2).value="上公差"
ws.cell(9,2).value="下公差"
ws.cell(10,2).value="规格上限"
ws.cell(11,2).value="规格下限"
for d in range(len(data_list)):#写入编号
ws.cell(5,d+3).value=data_list[d][0]
ws.cell(6,d+3).value=data_list[d][1]
ws.cell(7,d+3).value=data_list[d][2]
ws.cell(8,d+3).value=data_list[d][3]
ws.cell(9,d+3).value=data_list[d][4]
ws.cell(10,d+3).value=data_list[d][5]
ws.cell(11,d+3).value=data_list[d][6]
ok_row=12
for iii in range(len(datas)):#循环写入数据
if str(datas[iii][0])==str(data_list[d][7]):
ws.cell(ok_row,d+3).value=float(datas[iii][1])
if d==0:
ws.cell(ok_row,2).value=ok_row-11
ws.cell(ok_row,1).value=local_sn_id
ok_row+=1
red_fill=PatternFill(start_color='F2A0A1',end_color='F2A0A1',fill_type='solid')
blue_fill=PatternFill(start_color='A0D8EF',end_color='A0D8EF',fill_type='solid')
max_col=ws.max_column+1
for col in range(3,max_col):
max=ws.cell(10,col).value
min=ws.cell(11,col).value
if max is not None and min is not None:
g_rule=CellIsRule(operator="greaterThan",formula=[str(max)],fill=red_fill)
l_rule=CellIsRule(operator="lessThan",formula=[str(min)],fill=blue_fill)
col_letter=get_column_letter(col)
f_str=col_letter+str(12)+":"+col_letter+str(ws.max_row)
ws.conditional_formatting.add(f_str,g_rule)
ws.conditional_formatting.add(f_str,l_rule)
ws.column_dimensions['A'].width = 12
ws.column_dimensions['B'].width = 12
wb.save('Export_data.xlsx')
ui.download('Export_data.xlsx', 'Export_data.xlsx')
ui.notify('已成功导出数据')
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "NA", "query", USER_NAME,"下载了snid为{}的实际数据".format(local_sn_id)))
sq.commit()
else:
ui.notify('未查询到量测数据')
else:
ui.notify('未查询到单号信息')
else:#未使用单号,则使用模号查询数据
stime=date1.value#开始时间
etime=date2.value#结束时间
if len(stime)!=0 and len(etime)!=0:
d1=datetime.date(year=int(stime[:4]),month=int(stime[5:7]),day=int(stime[-2:]))
d2=datetime.date(year=int(etime[:4]),month=int(etime[5:7]),day=int(etime[-2:]))
if d1<=d2:
mohao_=mohaoid.value
if len(mohao_) != 0:
duanbie=duanbieid.value
c.execute("SELECT * FROM info WHERE mohao=? AND duanbie=?", (mohao_,duanbie))
infolist=c.fetchone()
if infolist is not None:
info_id=infolist[0]
c.execute("SELECT * FROM sn WHERE infoid=? AND state='已量测'", (info_id,))
if c.fetchone() is not None:
sn_list=c.fetchall()
sn_ids=[]
for sn in sn_list:
stime=sn[5][:10]#获取投测时间
stime_d=datetime.date(year=int(stime[:4]), month=int(stime[5:7]), day=int(stime[-2:]))
if d1<=stime_d<=d2:
sn_ids.append([sn[0],stime])#存入满足日期的单号和对应日期
#开始根据单号查询数据
datas=[]
for ids in sn_ids:
c.execute("SELECT * FROM sdata WHERE snid=?", (ids[0],))
if c.fetchone is not None:
data=c.fetchall()
for i in data:
#FAI序号,data,单号,日期
datas.append([i[2],i[4],ids[0],ids[1]])
c.execute("SELECT * FROM data WHERE infoid=?", (info_id,))
datalist=c.fetchall()
data_list=[]
for j in datalist:
cpkno=j[3]
faino=j[2]
dimno=j[0]
nor=j[6]
tolu=j[7]
toll=j[8]
if j[4]=="数值型":
usl=Decimal(nor)+Decimal(tolu)
lsl=Decimal(nor)-Decimal(toll)
else:
usl=''
lsl=''
data_list.append([faino,cpkno,nor,tolu,toll,usl,lsl,dimno])
c.execute("SELECT * FROM info WHERE id=?", (info_id,))
info_info=c.fetchone()
mohao=info_info[1]
liaohao=info_info[2]
build=info_info[10]
wb=Workbook()
ws=wb.active
#基础信息写入
ws.title='数据查询结果'
ws.append(['模号','料号','BUILD',"Note:低于规格下限蓝色填充标识,高于规格上限红色填充标识"])
ws.append([mohao,liaohao,build])
ws.append(['开始日期','结束日期',"查询者"])
ws.append([d1,d2,USER_NAME])
ws.append(['单号','日期'])
ws.cell(5,3).value="FAI序号"
ws.cell(6,3).value="CPK序号"
ws.cell(7,3).value="标准值"
ws.cell(8,3).value="上公差"
ws.cell(9,3).value="下公差"
ws.cell(10,3).value="规格上限"
ws.cell(11,3).value="规格下限"
ws.merge_cells(start_row=5, start_column=1, end_row=11, end_column=1)
ws.merge_cells(start_row=5, start_column=2, end_row=11, end_column=2)
for d in range(len(data_list)):#写入编号
ws.cell(5,d+4).value=data_list[d][0]
ws.cell(6,d+4).value=data_list[d][1]
ws.cell(7,d+4).value=data_list[d][2]
ws.cell(8,d+4).value=data_list[d][3]
ws.cell(9,d+4).value=data_list[d][4]
ws.cell(10,d+4).value=data_list[d][5]
ws.cell(11,d+4).value=data_list[d][6]
ok_row=12
for iii in range(len(datas)):#循环写入数据
if str(datas[iii][0])==str(data_list[d][7]):
ws.cell(ok_row,d+4).value=float(datas[iii][1])
if d==0:
ws.cell(ok_row,3).value=ok_row-11
ws.cell(ok_row,1).value=datas[iii][2]
ws.cell(ok_row,2).value=datas[iii][3]
ok_row+=1
red_fill=PatternFill(start_color='F2A0A1',end_color='F2A0A1',fill_type='solid')
blue_fill=PatternFill(start_color='A0D8EF',end_color='A0D8EF',fill_type='solid')
max_col=ws.max_column+1
for col in range(4,max_col):
max=ws.cell(10,col).value
min=ws.cell(11,col).value
if max is not None and min is not None:
g_rule=CellIsRule(operator="greaterThan",formula=[str(max)],fill=red_fill)
l_rule=CellIsRule(operator="lessThan",formula=[str(min)],fill=blue_fill)
col_letter=get_column_letter(col)
f_str=col_letter+str(12)+":"+col_letter+str(ws.max_row)
ws.conditional_formatting.add(f_str,g_rule)
ws.conditional_formatting.add(f_str,l_rule)
ws.column_dimensions['A'].width = 12
ws.column_dimensions['B'].width = 12
wb.save('Export_data.xlsx')
ui.download('Export_data.xlsx', 'Export_data.xlsx')
ui.notify('已成功导出数据')
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "NA", "query", USER_NAME,"下载了日期为{}-{}的实际数据".format(d1,d2)))
sq.commit()
else:
ui.notify('该模号该制程没有量测完成的单子')
else:
ui.notify('未查询到该模号该制程资料')
else:
ui.notify('请输入模号')
else:
ui.notify('开始时间不能大于结束时间')
else:
ui.notification('请输入开始时间和结束时间')
ui.page_title('FX智能数据系统-数据查询')
ui.label("数据查询")
with ui.row():
sn_id=ui.input(label="单号",placeholder="请输入单号").style("width:18%")
mohaoid=ui.input(label="模号",placeholder="请输入模号").style("width:18%")
duanbieid=ui.select(label="段别",options=["成型","冲压","电镀","装配"],value="成型").style("width:18%")
with ui.input('开始日期').style("width:18%") as date1:
with ui.menu().props('no-parent-event') as menu:
with ui.date().bind_value(date1):
with ui.row().classes('justify-end'):
ui.button('Close', on_click=menu.close).props('flat')
with date1.add_slot('append'):
ui.icon('edit_calendar').on('click', menu.open).classes('cursor-pointer')
with ui.input('结束日期').style("width:18%") as date2:
with ui.menu().props('no-parent-event') as menu2:
with ui.date().bind_value(date2):
with ui.row().classes('justify-end'):
ui.button('Close', on_click=menu2.close).props('flat')
with date2.add_slot('append'):
ui.icon('edit_calendar').on('click', menu2.open).classes('cursor-pointer')
ui.button(text="查询并导出数据",on_click=export_data)
ui.button(text="查询并生成图表",on_click=xbar_chart)
ui.label("")
###################################################进度页面####################################################################
@ui.page('/schedule')
def page_schedule():
global LOCAL_PAGE
LOCAL_PAGE='schedule'
page_layout()
#上传模板下载
async def download_template():
select_sn=await sche_grid.get_selected_row()
if select_sn:
#获取需要上传的尺寸列表,根据单号的id去查对应的infoid,然后再根据infoid去data表查询对应的尺寸清单,然后再将尺寸清单的数据插入到尺寸表中
c.execute("SELECT infoid FROM sn WHERE id=?", (select_sn['id'],))
infoid=c.fetchone()[0]
c.execute("SELECT * FROM data WHERE infoid=?", (infoid,))
data=c.fetchall()
wb=Workbook()
ws=wb.active
ws.title='模板'
ws.append(['FAI序号','CPK序号','项目id','维护资料id','量测单号','产品1','产品2','产品3','产品4','产品5','产品6','产品7','产品8','产品9','产品10','产品11','产品12','产品13','产品14','产品15','产品16`','产品17','产品18','产品19','产品20','产品21','产品22','产品23','产品24','产品25','产品26','产品27','产品28','产品29','产品30','产品31','产品32'])
datalist=[]#得到尺寸信息列表,直接生成对应模板文件
for i in data:
ws.append([i[2],i[3],i[0],infoid,select_sn['id']])
wb.save('template.xlsx')
ui.download(src='template.xlsx')
ui.notification('下载成功')
else:
ui.notification('未选择任何行')
#单号加排程
async def update_sn():
select_sn=await sche_grid.get_selected_row()
if select_sn:
if select_sn['单号状态']=='待量测':
c.execute("UPDATE sn SET state='已排程' WHERE id=?", (select_sn['id'],))
sq.commit()
sche_fresh()
sche_grid.update()
ui.notification('排程成功')
fresh_chart()
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "sn", "update", USER_NAME,"更新了id为{}的记录为:已排程".format(select_sn['id'])))
sq.commit()
else:
ui.notification('已排程,请勿重复操作')
else:
ui.notification('未选择任何行')
#删除单号
async def delete_sn():
select_sn=await sche_grid.get_selected_row()
if select_sn:
if authority=="管理员":
c.execute("DELETE FROM sn WHERE id=?", (select_sn['id'],))
sq.commit()
sche_fresh()
sche_grid.update()
ui.notify('删除成功')
fresh_chart()
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "sn", "delete", USER_NAME,"删除了id为{}的记录".format(select_sn['id'])))
sq.commit()
else:
ui.notify('无权限')
else:
ui.notify('未选择任何行')
#添加数据
async def adddata_sn():
def up_file(content,filename):
path=""
fullpath=path+filename
with open(fullpath,'wb') as f:
f.write(content)
ui.notify('上传成功')
up_box.remove(up_box)
#获取需要上传的尺寸列表,根据单号的id去查对应的infoid,然后再根据infoid去data表查询对应的尺寸清单,然后再将尺寸清单的数据插入到尺寸表中
c.execute("SELECT infoid FROM sn WHERE id=?", (select_sn['id'],))
infoid=c.fetchone()[0]
c.execute("SELECT * FROM data WHERE infoid=?", (infoid,))
data=c.fetchall()
datalist=[]#得到尺寸信息列表,供后续比对
for i in data:
datalist.append([str(i[2]),str(i[3]),str(i[0])])#FAI序号,CPK序号,dim_id
#判断文件格式,如果是xlsx格式excel,则解析,如果是其他格式,则提示错误
if filename.endswith('.xlsx'):
c_wb=load_workbook(fullpath)
c_ws=c_wb.active
new_datalist=[]
for i_row in range(2,c_ws.max_row+1):
new_datalist.append([str(c_ws.cell(i_row,1).value),c_ws.cell(i_row,2).value,str(c_ws.cell(i_row,3).value)])
#判断datalist和new_datalist是否完全相同,如果相同,则继续下一个,如果不同,则提示错误
if datalist == new_datalist:#确定是相同的表单
for i_row in range(2,c_ws.max_row+1):
local_dimid=str(c_ws.cell(i_row,3).value)
for i_col in range(6,c_ws.max_column+1):
if c_ws.cell(i_row,i_col).value is not None:
c.execute('INSERT INTO sdata (infoid,dimid,snid,value,role) VALUES (?,?,?,?,?)', (infoid,local_dimid,select_sn['id'],str(c_ws.cell(i_row,i_col).value),'All'))
sq.commit()
ui.notify('上传成功')
#获取当前时间,转换为"2024/12/18-18:05:02"格式字符串
now = str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S"))
c.execute("UPDATE sn SET ftime=?,op=?,state=? WHERE id=?", (now,USER_NAME,"已量测",select_sn['id']))
sq.commit()
sche_fresh()
sche_grid.update()
fresh_chart()
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "sn", "update", USER_NAME,"更新了id为{}的记录为:已量测".format(select_sn['id'])))
sq.commit()
else:
ui.notify('请上传正确的尺寸清单')
else:
ui.notify('请上传xlsx格式excel文件')
select_sn=await sche_grid.get_selected_row()
if select_sn:
if select_sn['单号状态']=='已排程':
up_box=ui.upload(
auto_upload=True,
on_upload=lambda e: up_file(e.content.read(),e.name),
multiple=False
)
elif select_sn['单号状态']=='已量测':
ui.notification('已量测,请勿重复操作')
else:
ui.notification('请先进行排程')
else:
ui.notification('未选择任何行')
#刷新页面表单数据
def sche_fresh():
sche_row.clear()
c.execute("SELECT * FROM sn")
data = c.fetchall()
for row in data:
x={
'id': row[0],
'模号': row[2],
'投测类型': row[3],
'制程段别': row[4],
'投单时间': row[5],
'完成时间': row[6],
'量测人员': row[7],
'单号状态': row[8],
'备注': row[9]
}
sche_row.append(x)
def fresh_chart():
done_List=[0,0,0,0]
ongoing_list=[0,0,0,0]
ready_list=[0,0,0,0]
#在sn表中根据duanbie和state进行查询,duanbie为”成型“,state为”已量测“
#如果做其他看板按照类似的查询方法搞就行了,很easy
#已量测
c.execute("SELECT duanbie,COUNT(*) FROM sn WHERE duanbie='成型' AND state='已量测' GROUP BY duanbie")
data = c.fetchall()
if data is not None and len(data)!=0:
done_List[2]=data[0][1]
c.execute("SELECT duanbie,COUNT(*) FROM sn WHERE duanbie='电镀' AND state='已量测' GROUP BY duanbie")
data = c.fetchall()
if data is not None and len(data)!=0:
done_List[1]=data[0][1]
c.execute("SELECT duanbie,COUNT(*) FROM sn WHERE duanbie='装配' AND state='已量测' GROUP BY duanbie")
data = c.fetchall()
if data is not None and len(data)!=0:
done_List[3]=data[0][1]
c.execute("SELECT duanbie,COUNT(*) FROM sn WHERE duanbie='冲压' AND state='已量测' GROUP BY duanbie")
data = c.fetchall()
if data is not None and len(data)!=0:
done_List[0]=data[0][1]
#待量测
c.execute("SELECT duanbie,COUNT(*) FROM sn WHERE duanbie='成型' AND state='待量测' GROUP BY duanbie")
data = c.fetchall()
if data is not None and len(data)!=0:
ready_list[2]=data[0][1]
c.execute("SELECT duanbie,COUNT(*) FROM sn WHERE duanbie='电镀' AND state='待量测' GROUP BY duanbie")
data = c.fetchall()
if data is not None and len(data)!=0:
ready_list[1]=data[0][1]
c.execute("SELECT duanbie,COUNT(*) FROM sn WHERE duanbie='装配' AND state='待量测' GROUP BY duanbie")
data = c.fetchall()
if data is not None and len(data)!=0:
ready_list[3]=data[0][1]
c.execute("SELECT duanbie,COUNT(*) FROM sn WHERE duanbie='冲压' AND state='待量测' GROUP BY duanbie")
data = c.fetchall()
if data is not None and len(data)!=0:
ready_list[0]=data[0][1]
#已排程
c.execute("SELECT duanbie,COUNT(*) FROM sn WHERE duanbie='成型' AND state='已排程' GROUP BY duanbie")
data = c.fetchall()
if data is not None and len(data)!=0:
ongoing_list[2]=data[0][1]
c.execute("SELECT duanbie,COUNT(*) FROM sn WHERE duanbie='电镀' AND state='已排程' GROUP BY duanbie")
data = c.fetchall()
if data is not None and len(data)!=0:
ongoing_list[1]=data[0][1]
c.execute("SELECT duanbie,COUNT(*) FROM sn WHERE duanbie='装配' AND state='已排程' GROUP BY duanbie")
data = c.fetchall()
if data is not None and len(data)!=0:
ongoing_list[3]=data[0][1]
c.execute("SELECT duanbie,COUNT(*) FROM sn WHERE duanbie='冲压' AND state='已排程' GROUP BY duanbie")
data = c.fetchall()
if data is not None and len(data)!=0:
ongoing_list[0]=data[0][1]
chart.options["series"][0]['data']=ready_list#更新待量测
chart.options["series"][1]['data']=ongoing_list#更新已排程
chart.options["series"][2]['data']=done_List#更新已量测
chart.update()
ui.page_title('FX智能数据系统-量测进度')
ui.label('量测进度')
sche_col=[
{'field':'id'},
{'field':'模号'},
{'field':'投测类型'},
{'field':'制程段别'},
{'field':'投单时间'},
{'field':'完成时间'},
{'field':'量测人员'},
{'field':'单号状态'},
{'field':'备注'},
]
sche_row=[]
sche_fresh()
sche_grid = ui.aggrid({
'columnDefs': sche_col,
'rowData': sche_row,
'rowSelection':'single',
'pagination':True,
'paginationPageSize':7,
'defaultColDef':{'editable': False,'sortable': True,'filter': True,},
},
)
with ui.row().style('width:100%'):
ui.button('开始排程',on_click=update_sn)
ui.button('删除单号',on_click=delete_sn)
ui.button('上传数据',on_click=adddata_sn)
ui.button('模板下载',on_click=download_template)
chart = ui.highchart({
'title':{'text':'量测进度统计'},
'chart': {'type': 'bar'},
'xAxis': {'categories': ['冲压', '电镀','成型','装配']},
'yAxis': {'title': {'text': '数量'}},
'series': [
{'name': '待量测', 'data': [0.3, 0.4,0,0]},
{'name': '已排程', 'data': [0.3, 0.4,0,0]},
{'name': '已量测', 'data': [0.1, 0.2,0,0]},
],
}).classes('w-full h-64')
fresh_chart()
###################################################管理页面####################################################################
@ui.page('/manage')
def page_manage():
# 设置全局变量LOCAL_PAGE的值为'manage'
global LOCAL_PAGE
LOCAL_PAGE='manage'
# 调用page_layout函数进行页面布局
page_layout()
# 设置页面标题
ui.page_title('FX智能数据系统-后台管理')
# 人员管理模块
# 添加人员管理模块的标签
ui.label('人员管理')
def log_grid_fresh():
c.execute("SELECT * FROM log ORDER BY id DESC LIMIT 700")
data = c.fetchall()
for row in data:
x={
'id': row[0],
'时间': row[1],
'数据表': row[2],
'操作项': row[3],
'操作人': row[4],
'操作内容': row[5]
}
log_row.append(x)
# 定义fresh_grid函数,用于刷新表格数据
def fresh_grid():
# 清空表格数据
rows.clear()
# 执行SQL查询语句,从user表中查询所有数据
c.execute("SELECT * FROM user")
# 获取查询结果
data = c.fetchall()
# 遍历查询结果,将每行数据添加到rows列表中
for row in data:
x={
'id': row[0],
'name': row[1],
'password': row[2],
'department': row[3],
'role': row[4]
}
rows.append(x)
# 定义reset_sn函数,用于重置表单状态
async def reset_sn():
# 判断输入的单号是否为空
if len(sn_id.value)==0:
ui.notify('请输入单号')
else:
# 在sn表中查找sn_id是否存在
c.execute("SELECT * FROM sn WHERE id=?", (sn_id.value,))
data = c.fetchone()
# 如果查询结果为空,说明单号不存在
if data is None:
ui.notify('该单号不存在')
else:
# 在sn表中更新sn_id对应的状态为'待量测',ftime和op字段改为“NA”
c.execute("UPDATE sn SET state='待量测',ftime='NA',op='NA' WHERE id=?", (sn_id.value,))
sq.commit()
#在log表中加入一行数据,sn表更新了id为sn_id.value的条目为待量测
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "sn", "update", USER_NAME,"更新了id为{}的记录为:待量测".format(sn_id.value)))
sq.commit()
# 在sdata表中删除sn_id对应的所有数据
c.execute("DELETE FROM sdata WHERE snid=?", (sn_id.value,))
sq.commit()
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "sdata", "delete", USER_NAME,"删除了snid为{}的实际数据".format(sn_id.value)))
sq.commit()
ui.notify('重置成功')
log_grid_fresh()
log_grid.update()
# 清空输入的单号
sn_id.value=''
# 定义异步函数update_row,用于更新表格中的一行数据
async def update_row():
# 获取选中的行数据
select_row=await grid.get_selected_row()
# 判断是否选中了行数据
if select_row:
# 执行SQL更新语句,更新user表中的数据
c.execute("UPDATE user SET name=?,password=?,department=?,role=? WHERE id=?", (select_row['name'],select_row['password'],select_row['department'],select_row['role'],select_row['id']))
sq.commit()
# 刷新表格数据
fresh_grid()
# 更新表格显示
ui.update(grid)
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "user", "update", USER_NAME,"更新了id为{}的记录".format(select_row['id'])))
sq.commit()
log_grid_fresh()
log_grid.update()
else:
# 如果没有选中行数据,提示用户选择一行
ui.notify('请选择一行')
# 定义异步函数delete_row,用于删除表格中的一行数据
async def delete_row():
# 获取选中的行数据
select_row = await grid.get_selected_row()
# 判断是否选中了行数据
if select_row:
# 执行SQL删除语句,删除user表中的一行数据
c.execute("DELETE FROM user WHERE id=?", (select_row['id'],))
sq.commit()
# 刷新表格数据
fresh_grid()
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "user", "delete", USER_NAME,"删除了id为{}的记录".format(select_row['id'])))
sq.commit()
# 更新表格显示
ui.update(grid)
log_grid_fresh()
log_grid.update()
else:
# 如果没有选中行数据,提示用户选择一行
ui.notify('请选择一行')
# 定义异步函数add_row,用于在表格中添加一行新数据
async def add_row():
# 执行SQL插入语句,向user表中插入一行新数据
c.execute("INSERT INTO user (name,password,department,role) VALUES (?,?,?,?)", ('FX复杂一点','fx666369369','','普通用户'))
sq.commit()
# 刷新表格数据
fresh_grid()
# 更新表格显示
ui.update(grid)
c.execute("INSERT INTO log (time,tab,func,op,content) VALUES (?,?,?,?,?)", (str(datetime.datetime.now().strftime("%Y/%m/%d-%H:%M:%S")), "user", "create", USER_NAME,"增加一条空白记录"))
sq.commit()
log_grid_fresh()
log_grid.update()
# 定义表格的列定义
columns=[
{'field': 'id'},
{'field': 'name'},
{'field': 'password'},
{'field': 'department'},
{'field': 'role'}
]
# 初始化表格数据列表
rows=[]
# 调用fresh_grid函数刷新表格数据
fresh_grid()
# 创建ag-Grid表格
grid = ui.aggrid({
'columnDefs': columns,
'rowData': rows,
'rowSelection':'single',
'pagination':True,
'paginationPageSize':7,
'defaultColDef':{'editable': True},
}
)
# 创建一行,并设置样式为宽度100%
with ui.row().style('width:100%'):
# 创建新增按钮,并绑定add_row函数
ui.button('新增',on_click=add_row)
# 创建更新按钮,并绑定update_row函数
ui.button('更新',on_click=update_row)
# 创建删除按钮,并绑定delete_row函数
ui.button('删除',on_click=delete_row)
# 添加表单状态重置的标签
ui.label('表单状态重置')
# 创建一行,并设置样式为宽度100%
with ui.row().style('width:100%'):
# 创建输入框,用于输入单号,并设置占位符和样式
sn_id=ui.input(label='单号',placeholder="请输入单号").style('width:20%')
# 创建重置状态按钮,并绑定reset_sn函数,同时设置按钮样式
ui.button("重置状态",on_click=reset_sn).style("width:20%")
log_col=[
{'field': 'id','maxWidth':100},
{'field': '时间','maxWidth':150},
{'field': '数据表','maxWidth':80},
{'field': '操作项','maxWidth':150},
{'field': '操作人'},
{'field': '操作内容'}
]
log_row=[]
log_grid_fresh()
log_grid = ui.aggrid({
'columnDefs': log_col,
'rowData': log_row,
'rowSelection':'single',
'pagination':True,
'paginationPageSize':7,
}
)
###################################################关于页面####################################################################
@ui.page('/about')
def page_about():
global LOCAL_PAGE
LOCAL_PAGE="about"
page_layout()
ui.page_title('FX智能数据系统-关于系统')
ui.label('关于系统')
ui.label('''
FX智能数据系统是基于Python语言,nicegui库开发的Web数据管理系统,主要用了如下库:nicegui(负责页面),sqlite3(负责数据库),openpyxl(负责excel文件操作),highcharts(负责图表生成),decimal(提供计算精度),datetime(用于日期计算模块)。
页面配色受网友启发和引导。
未来也许会做的:数据导出增强,数据图表增加类型,数据上传可分段分部门上传
''')
ui.label('本系统由Feixiang Technology开发,主要功能包括:')
ui.label('''1. 登录页面
可以通过用户名、密码查询user表中信息进行登录操作。登录后获取人员权限等级,并显示用户名称。
''')
ui.label('''2. 资料维护
仅有管理员可进行维护操作,分两个模块,涉及两张表:
2.1资料创建维护
在info表中创建唯一特征资料编号,并存储相应的资料内容。
2.2尺寸数据信息维护
在data表中创建,根据snid绑定一系列尺寸资料。
''')
ui.label('''3. 巡检投测
在sn表中创建唯一特征资料编号,并存储相应的尺寸数据。
''')
ui.label('''4. 委托量测
在sn表中创建唯一特征资料编号,并存储相应的尺寸数据。
''')
ui.label('''5. 量测进度
查询SN表中的数据并前台显示,可切换状态,上传数据,下载模板,同时调用了highcharts绘制进度图
''')
ui.label('''6. 数据查询
分两个模板,数据导出模块,和图表生成模块
6.1数据导出
分单号查询和by日期查询,有输入单号时,根据单号信息在sdata表中调取数据,并在info表和data表中获取一些参数,使用openpyxl生成excel文件,并下载。
单号未输入时,根据模号,段别,日期,查询对应的所有数据,同样在info表和data表中获取参数,使用openpyxl生成excel文件,并下载。
6.2图表生成
仅有by日期查询,根据模号,段别,在info表中查询infoid,再根据infoid在sn表中查询所有符合的sn,再根据日期筛选需要的sn单号,最后根据sn和日期去计算控制图所需的各种参数,并调用highcharts By FAI尺寸生成控制图。
''')
ui.label('''7. 后台管理
用户管理,进行用户创建修改删除操作
另有单号重置功能,会将单号恢复为“待量测”状态,同时删除sdata表中对应的所有尺寸数据。
''')
ui.label('更多信息请联系本人 WeChat:liufeixiang_6,或QQ群:526674805,微信群可拉')
###################################################模板页面####################################################################
def page_layout():
ui.colors(primary="#1A6F78")
ui.query('body').style('background-color: #7DB9DE')
if if_log_in == False:
ui.notify('请先登录')
ui.navigate.to('/login')
else:
ui.add_css('''
.custom_btn{
}
''')
with ui.header(elevated=True).style('background-color: #1A5F68').classes('items-center'):
ui.button(on_click=lambda: left_drawer.toggle(), icon='menu').props('flat color=white')
ui.link('FX智能数据系统','/').style("color: white;text-decoration:none;font-size:20px")
#ui.button(on_click=lambda: left_drawer.toggle(), icon='menu').props('flat color=white')
with ui.left_drawer(top_corner=True, bottom_corner=True).style('background-color: #1A4F48') as left_drawer:
ui.label(USER_NAME).style("width:100%;font-size:large;text-align: center;color:white")
if authority=="管理员":
sheet_btn=ui.button('资料维护', on_click=lambda: ui.navigate.to("/sheet")).style("width:100%")
daily_btn=ui.button('巡检投测', on_click=lambda: ui.navigate.to('/daily')).style("width:100%")
request_btn=ui.button('委托量测', on_click=lambda: ui.navigate.to('/request')).style("width:100%")
schedule_btn=ui.button('量测进度', on_click=lambda: ui.navigate.to('/schedule')).style("width:100%")
query_btn=ui.button('数据查询', on_click=lambda: ui.navigate.to('/query')).style("width:100%")
about_btn=ui.button('关于系统', on_click=lambda: ui.navigate.to('/about')).style("width:100%")
if authority=="管理员":
manage_btn=ui.button('后台管理', on_click=lambda: ui.navigate.to('/manage')).style("width:100%")
ui.button('退出登录', on_click=quit).style("width:100%")
if LOCAL_PAGE=="request":
request_btn.classes('custom_btn')
elif LOCAL_PAGE=="daily":
daily_btn.classes('custom_btn')
elif LOCAL_PAGE=="schedule":
schedule_btn.classes('custom_btn')
elif LOCAL_PAGE=="query":
query_btn.classes('custom_btn')
elif LOCAL_PAGE=="about":
about_btn.classes('custom_btn')
elif LOCAL_PAGE=="sheet":
sheet_btn.classes('custom_btn')
elif LOCAL_PAGE=="manage":
manage_btn.classes('custom_btn')
with ui.footer().style('background-color: #1A5F58'):
ui.label('Copyright © 2024 Feixiang Technology Co., Ltd. All Rights Reserved')
ui.run(favicon='http://1life2live.cn/usr/uploads/2024/12/927828336.ico',port=3030)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。