v0.7.2 顶栏精简:移除常驻打卡与周记提示按钮,周记提醒改为周五至周日 toast 一次性提示

This commit is contained in:
root
2026-11-01 19:58:44 +08:00
parent d300fd9b96
commit 971853560a
9 changed files with 60 additions and 132 deletions
+7
View File
@@ -0,0 +1,7 @@
# v0.7.2 顶栏精简
## 优化
- 移除右上角常驻的「上班打卡」按钮:打卡在「详情」页当日面板与日历当日抽屉中操作,顶栏不再重复。
- 移除右上角常驻的「填写本周周记」提示按钮:改为周五至周日打开应用时 toast 提示一次,不占用常驻界面;设置页「周记提醒」开关继续有效。
- 顶栏仅保留页面标题与搜索,移动端搜索按钮右对齐。
- 清除相关死代码约 80 行(打卡三态、周记提示样式)。
@@ -1,2 +1,2 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./web-9h8A4HQx.js","./index-pe6VFzmc.js","./index-BiI44Vix.css"])))=>i.map(i=>d[i]); const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./web-Deo5OtIz.js","./index-ynPmf8i8.js","./index-COwenkhO.css"])))=>i.map(i=>d[i]);
import{r as s,_ as i}from"./index-pe6VFzmc.js";var t;(function(e){e.Documents="DOCUMENTS",e.Data="DATA",e.Library="LIBRARY",e.Cache="CACHE",e.External="EXTERNAL",e.ExternalStorage="EXTERNAL_STORAGE"})(t||(t={}));var a;(function(e){e.UTF8="utf8",e.ASCII="ascii",e.UTF16="utf16"})(a||(a={}));const E=s("Filesystem",{web:()=>i(()=>import("./web-9h8A4HQx.js"),__vite__mapDeps([0,1,2]),import.meta.url).then(e=>new e.FilesystemWeb)});export{t as Directory,a as Encoding,E as Filesystem}; import{r as s,_ as i}from"./index-ynPmf8i8.js";var t;(function(e){e.Documents="DOCUMENTS",e.Data="DATA",e.Library="LIBRARY",e.Cache="CACHE",e.External="EXTERNAL",e.ExternalStorage="EXTERNAL_STORAGE"})(t||(t={}));var a;(function(e){e.UTF8="utf8",e.ASCII="ascii",e.UTF16="utf16"})(a||(a={}));const E=s("Filesystem",{web:()=>i(()=>import("./web-Deo5OtIz.js"),__vite__mapDeps([0,1,2]),import.meta.url).then(e=>new e.FilesystemWeb)});export{t as Directory,a as Encoding,E as Filesystem};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -8,8 +8,8 @@
<link rel="icon" href="./icons/icon.svg" type="image/svg+xml" /> <link rel="icon" href="./icons/icon.svg" type="image/svg+xml" />
<link rel="apple-touch-icon" href="./icons/icon-192.png" /> <link rel="apple-touch-icon" href="./icons/icon-192.png" />
<title>实习工作日志</title> <title>实习工作日志</title>
<script type="module" crossorigin src="./assets/index-pe6VFzmc.js"></script> <script type="module" crossorigin src="./assets/index-ynPmf8i8.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-BiI44Vix.css"> <link rel="stylesheet" crossorigin href="./assets/index-COwenkhO.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "intern-log", "name": "intern-log",
"private": true, "private": true,
"version": "0.7.1", "version": "0.7.2",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
+18 -97
View File
@@ -15,11 +15,11 @@ import UserAdminView from './views/UserAdminView.vue'
import LoginView from './views/LoginView.vue' import LoginView from './views/LoginView.vue'
import { getSession, logoutUser, openUserDatabase, type Session } from './db/auth' import { getSession, logoutUser, openUserDatabase, type Session } from './db/auth'
import { autoSyncNow, enableRealtimeSync, ensureCloudBinding, stopRealtime } from './sync/engine' import { autoSyncNow, enableRealtimeSync, ensureCloudBinding, stopRealtime } from './sync/engine'
import { clockIn, getAttendance, getWorkRule, getWeeklyNote, searchLogItems, searchMemos, smartClockOut, type WorkRule } from './db/repo' import { getWorkRule, getWeeklyNote, searchLogItems, searchMemos } from './db/repo'
import { addDays, hhmm, todayStr, weekStart } from './lib/date' import { todayStr, weekStart } from './lib/date'
import { showToast, useToasts } from './lib/toast' import { showToast, useToasts } from './lib/toast'
import { attendanceChanged, focusDate, focusMemo, notifyAttendanceChanged } from './lib/bus' import { focusDate, focusMemo } from './lib/bus'
import { categoryLabel, type Attendance, type LogItem, type Memo } from './db/schema' import { categoryLabel, type LogItem, type Memo } from './db/schema'
const toasts = useToasts() const toasts = useToasts()
@@ -30,8 +30,7 @@ async function onLogin(s: Session) {
openUserDatabase(s.userId) openUserDatabase(s.userId)
location.hash = '#/calendar' location.hash = '#/calendar'
route.value = 'calendar' route.value = 'calendar'
await refreshClock() await checkWeeklyReminder()
await refreshTip()
startSyncTimer() startSyncTimer()
try { try {
await ensureCloudBinding() await ensureCloudBinding()
@@ -161,72 +160,24 @@ function pickLog(item: LogItem & { date: string }) { openLog(item); mobileSearch
function pickMemo(m: Memo) { openMemo(m); mobileSearch.value = false } function pickMemo(m: Memo) { openMemo(m); mobileSearch.value = false }
// ---- 工具栏打卡 ---- // ---- 周记提醒:周五至周日打开应用时 toast 提示一次,不占用常驻界面 ----
const today = ref(todayStr()) async function checkWeeklyReminder() {
const att = ref<Attendance | undefined>(undefined) try {
const yesterdayPending = ref(false) const rule = await getWorkRule()
if (rule.remind_weekly === 'off') return
async function refreshClock() {
att.value = await getAttendance(today.value)
yesterdayPending.value = false
const now = new Date()
if (now.getHours() < 4) {
const yRec = await getAttendance(addDays(today.value, -1))
yesterdayPending.value = !!(yRec && yRec.clock_in_at && !yRec.clock_out_at)
}
}
const hasActiveSession = computed(() => {
const a = att.value
if (a && a.clock_in_at && !a.clock_out_at) return true
return yesterdayPending.value && !(a && a.clock_in_at)
})
const clockDone = computed(() => {
const a = att.value
return !!(a && a.clock_in_at && a.clock_out_at)
})
const clockLabel = computed(() => {
const a = att.value
if (hasActiveSession.value) return '下班打卡'
if (clockDone.value) return '已打卡 ' + hhmm(a?.clock_in_at) + ' - ' + hhmm(a?.clock_out_at)
return '上班打卡'
})
async function doClock() {
if (hasActiveSession.value) {
try { await smartClockOut() } catch { /* 没有进行中的打卡 */ }
} else {
await clockIn(today.value)
}
await refreshClock()
notifyAttendanceChanged()
}
// 任何视图发生的考勤变更(含今日面板、日历抽屉)都实时同步到顶栏
watch(attendanceChanged, () => {
if (session.value) refreshClock()
})
// ---- 周记提醒 ----
const weekTip = ref(false)
async function refreshTip() {
const rule: WorkRule = await getWorkRule()
if (rule.remind_weekly === 'off') { weekTip.value = false; return }
const wd = new Date().getDay() const wd = new Date().getDay()
if (wd === 5 || wd === 6 || wd === 0) { if (wd !== 5 && wd !== 6 && wd !== 0) return
const note = await getWeeklyNote(weekStart(today.value)) const note = await getWeeklyNote(weekStart(todayStr()))
weekTip.value = !note || (!note.highlights && !note.challenges && !note.plan_next) if (note && (note.highlights || note.challenges || note.plan_next)) return
} else { showToast('本周周记还没写,可在「总结」页填写')
weekTip.value = false } catch { /* 提醒检查失败不影响使用 */ }
}
} }
onMounted(async () => { onMounted(async () => {
window.addEventListener('keydown', onGlobalKey) window.addEventListener('keydown', onGlobalKey)
if (session.value) { if (session.value) {
openUserDatabase(session.value.userId) openUserDatabase(session.value.userId)
await refreshClock() await checkWeeklyReminder()
await refreshTip()
startSyncTimer() startSyncTimer()
} }
}) })
@@ -287,17 +238,7 @@ onMounted(async () => {
<div v-else class="gs-empty muted">无匹配结果</div> <div v-else class="gs-empty muted">无匹配结果</div>
</div> </div>
</div> </div>
<span class="flex1"></span>
<div class="topbar-actions">
<button v-if="weekTip" class="week-tip" @click="nav('report')">
<span class="dot" style="background: var(--warn)"></span>
填写本周周记
</button>
<button class="btn btn-primary" :disabled="clockDone" @click="doClock">
<Icon :name="clockDone ? 'check-circle' : 'clock'" :size="14" />
<span class="num">{{ clockLabel }}</span>
</button>
</div>
</header> </header>
<main class="content"> <main class="content">
<div class="content-inner"> <div class="content-inner">
@@ -507,8 +448,6 @@ onMounted(async () => {
} }
.title { font-size: 15px; font-weight: 600; white-space: nowrap; } .title { font-size: 15px; font-weight: 600; white-space: nowrap; }
.topbar-actions { display: flex; align-items: center; gap: 8px; }
.gsearch { position: relative; width: 320px; max-width: 38vw; } .gsearch { position: relative; width: 320px; max-width: 38vw; }
.gs-icon { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--text-3); } .gs-icon { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--text-3); }
.gs-input { .gs-input {
@@ -554,21 +493,6 @@ onMounted(async () => {
.gs-date { font-size: 12px; flex: none; } .gs-date { font-size: 12px; flex: none; }
.gs-empty { padding: 10px; font-size: 12px; text-align: center; } .gs-empty { padding: 10px; font-size: 12px; text-align: center; }
.week-tip {
display: inline-flex;
align-items: center;
gap: 6px;
border: 1px solid var(--warn);
color: var(--warn);
background: var(--bg-page);
border-radius: 999px;
height: 28px;
padding: 0 10px;
font-size: 12px;
cursor: pointer;
white-space: nowrap;
}
.week-tip:hover { background: #FDF4EC; }
.content { flex: 1; overflow: auto; } .content { flex: 1; overflow: auto; }
.content-inner { max-width: 1280px; margin: 0 auto; padding: 20px 24px 48px; } .content-inner { max-width: 1280px; margin: 0 auto; padding: 20px 24px 48px; }
@@ -752,10 +676,7 @@ onMounted(async () => {
.gsearch { display: none; } .gsearch { display: none; }
.gsearch .gs-panel { display: none; } .gsearch .gs-panel { display: none; }
.mob-search-btn { display: flex; } .mob-search-btn { display: flex; }
.topbar-actions { margin-left: auto; gap: 6px; } .mob-search-btn { margin-left: auto; }
.week-tip { height: 28px; max-width: 118px; padding: 0 8px; white-space: nowrap; overflow: hidden; }
.topbar-actions .btn { padding: 0 12px; height: 34px; }
.topbar-actions .btn .num { font-size: 12px; }
.tabbar { display: flex; } .tabbar { display: flex; }
.tab-btn { height: 56px; font-size: 11px; } .tab-btn { height: 56px; font-size: 11px; }