KKingzor commited on
Commit
bfb9026
·
verified ·
1 Parent(s): 3de18db

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +60 -37
app.py CHANGED
@@ -4,77 +4,100 @@ import numpy as np
4
  import pandas as pd
5
  from PIL import Image
6
 
7
- # 建立 PaddleOCR 實例
8
  ocr = PaddleOCR(use_angle_cls=True, lang='ch')
9
 
10
  # 權限密碼
11
  ADMIN_PASSWORD = "admin123"
12
 
13
- # 儲存 DataFrame
14
- global_df = pd.DataFrame(columns=["門市", "日期", "時段", "人員"])
15
-
16
- # 工時換算(可依需求更改)
17
  TIME_SLOTS = {
18
  "早(07-15)": 8,
19
  "早(06-14)": 8,
 
20
  "晚(15-23)": 8,
 
21
  "晚(18-23)": 5,
22
  "夜(23-07)": 8,
23
- "晚(17-25)": 8,
24
- "早(08-18)": 10,
25
- "晚(18-23)": 5
26
  }
27
 
 
 
 
 
 
28
  def extract_info_from_text(text):
29
- """
30
- 模擬從 OCR 文本解析結構化資料,可依實際格式進階開發
31
- """
32
  import re
33
  rows = []
34
  for line in text.splitlines():
35
  match = re.findall(r"(安學|天期|永華東|鎮山|頂美)\s*(\d+月\d+日)\s*(早.*?|晚.*?|夜.*?)\s*([^\s]+)", line)
36
  for m in match:
37
- rows.append({"門市": m[0], "日期": m[1], "時段": m[2], "人員": m[3]})
 
 
 
 
 
 
 
 
 
 
 
 
38
  return pd.DataFrame(rows)
39
 
 
 
40
  def admin_upload(pwd, image):
41
  if pwd != ADMIN_PASSWORD:
42
  return "❌ 密碼錯誤", None
43
 
44
- img_np = np.array(image)
45
- result = ocr.ocr(img_np, cls=True)
46
- full_text = "\n".join([line[1][0] for line in result[0]])
47
 
48
- df = extract_info_from_text(full_text)
 
49
 
50
- global global_df
51
- global_df = pd.concat([global_df, df], ignore_index=True)
52
 
53
- return "✅ OCR 辨識完成", df
54
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  def query_by_staff(staff_name):
56
  df = global_df[global_df["人員"] == staff_name]
57
  if df.empty:
58
  return f"未找到 {staff_name} 的值班紀錄", None
59
  return "", df
60
 
 
 
61
  def calc_total_hours(staff_name):
62
  df = global_df[global_df["人員"] == staff_name]
63
- total = 0
64
- for _, row in df.iterrows():
65
- time_label = row["時段"]
66
- for key, val in TIME_SLOTS.items():
67
- if key in time_label:
68
- total += val
69
  return f"{staff_name} 一週總值班時數為:{total} 小時"
70
 
71
- # 建立 Gradio 介面
 
72
  with gr.Blocks() as demo:
73
- gr.Markdown("## 📋 排班表 OCR 辨識系統")
74
 
75
- with gr.Tab("🔐 管理者上傳 (admin123)"):
76
- admin_pwd = gr.Textbox(label="輸入管理者密碼", type="password")
77
- admin_img = gr.Image(type="pil", label="上傳排班表圖片")
78
  admin_btn = gr.Button("辨識並儲存")
79
  admin_status = gr.Textbox(label="狀態")
80
  admin_df = gr.Dataframe()
@@ -83,9 +106,9 @@ with gr.Blocks() as demo:
83
  inputs=[admin_pwd, admin_img],
84
  outputs=[admin_status, admin_df])
85
 
86
- with gr.Tab("🔍 查詢值班紀錄"):
87
  staff_input = gr.Textbox(label="輸入人員姓名")
88
- staff_btn = gr.Button("查詢每日紀錄")
89
  staff_status = gr.Textbox(label="狀態")
90
  staff_result = gr.Dataframe()
91
 
@@ -93,13 +116,13 @@ with gr.Blocks() as demo:
93
  inputs=staff_input,
94
  outputs=[staff_status, staff_result])
95
 
96
- with gr.Tab("📊 整週總時數"):
97
- staff_total = gr.Textbox(label="輸入人員姓名")
98
  total_btn = gr.Button("計算總時數")
99
- total_output = gr.Textbox(label="總時數")
100
 
101
  total_btn.click(fn=calc_total_hours,
102
- inputs=staff_total,
103
- outputs=total_output)
104
 
105
  demo.launch()
 
4
  import pandas as pd
5
  from PIL import Image
6
 
7
+ # 初始化 OCR
8
  ocr = PaddleOCR(use_angle_cls=True, lang='ch')
9
 
10
  # 權限密碼
11
  ADMIN_PASSWORD = "admin123"
12
 
13
+ # 排班工時對照表
 
 
 
14
  TIME_SLOTS = {
15
  "早(07-15)": 8,
16
  "早(06-14)": 8,
17
+ "早(08-18)": 10,
18
  "晚(15-23)": 8,
19
+ "晚(17-25)": 8,
20
  "晚(18-23)": 5,
21
  "夜(23-07)": 8,
 
 
 
22
  }
23
 
24
+ # 全域 DataFrame
25
+ global_df = pd.DataFrame(columns=["醫院", "日期", "時段", "人員", "工時"])
26
+
27
+
28
+ # OCR 文本解析為 DataFrame
29
  def extract_info_from_text(text):
 
 
 
30
  import re
31
  rows = []
32
  for line in text.splitlines():
33
  match = re.findall(r"(安學|天期|永華東|鎮山|頂美)\s*(\d+月\d+日)\s*(早.*?|晚.*?|夜.*?)\s*([^\s]+)", line)
34
  for m in match:
35
+ 時段 = m[2]
36
+ 工時 = 0
37
+ for k in TIME_SLOTS:
38
+ if k in 時段:
39
+ 工時 = TIME_SLOTS[k]
40
+ break
41
+ rows.append({
42
+ "醫院": m[0],
43
+ "日期": m[1],
44
+ "時段": 時段,
45
+ "人員": m[3],
46
+ "工時": 工時
47
+ })
48
  return pd.DataFrame(rows)
49
 
50
+
51
+ # 管理員上傳 + OCR 辨識
52
  def admin_upload(pwd, image):
53
  if pwd != ADMIN_PASSWORD:
54
  return "❌ 密碼錯誤", None
55
 
56
+ try:
57
+ img_np = np.array(image)
58
+ result = ocr.ocr(img_np)
59
 
60
+ if not result or not result[0]:
61
+ return "❌ OCR 未辨識出任何文字", None
62
 
63
+ full_text = "\n".join([line[1][0] for line in result[0] if line and line[1]])
 
64
 
65
+ df = extract_info_from_text(full_text)
66
 
67
+ if df.empty:
68
+ return "⚠️ 無法解析表格內容", None
69
+
70
+ global global_df
71
+ global_df = pd.concat([global_df, df], ignore_index=True)
72
+
73
+ return "✅ OCR 辨識完成並儲存", df
74
+
75
+ except Exception as e:
76
+ return f"❌ 發生錯誤:{str(e)}", None
77
+
78
+
79
+ # 查詢人員排班紀錄
80
  def query_by_staff(staff_name):
81
  df = global_df[global_df["人員"] == staff_name]
82
  if df.empty:
83
  return f"未找到 {staff_name} 的值班紀錄", None
84
  return "", df
85
 
86
+
87
+ # 查詢人員總工時
88
  def calc_total_hours(staff_name):
89
  df = global_df[global_df["人員"] == staff_name]
90
+ total = df["工時"].sum()
 
 
 
 
 
91
  return f"{staff_name} 一週總值班時數為:{total} 小時"
92
 
93
+
94
+ # Gradio 介面
95
  with gr.Blocks() as demo:
96
+ gr.Markdown("## 🏥 醫院值班表 OCR 辨識系統")
97
 
98
+ with gr.Tab("🔐 管理員上傳"):
99
+ admin_pwd = gr.Textbox(label="輸入密碼", type="password")
100
+ admin_img = gr.Image(type="pil", label="上傳排班圖片")
101
  admin_btn = gr.Button("辨識並儲存")
102
  admin_status = gr.Textbox(label="狀態")
103
  admin_df = gr.Dataframe()
 
106
  inputs=[admin_pwd, admin_img],
107
  outputs=[admin_status, admin_df])
108
 
109
+ with gr.Tab("📋 查詢個人紀錄"):
110
  staff_input = gr.Textbox(label="輸入人員姓名")
111
+ staff_btn = gr.Button("查詢紀錄")
112
  staff_status = gr.Textbox(label="狀態")
113
  staff_result = gr.Dataframe()
114
 
 
116
  inputs=staff_input,
117
  outputs=[staff_status, staff_result])
118
 
119
+ with gr.Tab("⏱️ 查詢總時數"):
120
+ total_input = gr.Textbox(label="輸入人員姓名")
121
  total_btn = gr.Button("計算總時數")
122
+ total_result = gr.Textbox(label="總時數")
123
 
124
  total_btn.click(fn=calc_total_hours,
125
+ inputs=total_input,
126
+ outputs=total_result)
127
 
128
  demo.launch()