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
@@ -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]);
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};
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-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="apple-touch-icon" href="./icons/icon-192.png" />
<title>实习工作日志</title>
<script type="module" crossorigin src="./assets/index-pe6VFzmc.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-BiI44Vix.css">
<script type="module" crossorigin src="./assets/index-ynPmf8i8.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-COwenkhO.css">
</head>
<body>
<div id="app"></div>
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "intern-log",
"private": true,
"version": "0.7.1",
"version": "0.7.2",
"type": "module",
"scripts": {
"dev": "vite",
+19 -98
View File
@@ -15,11 +15,11 @@ import UserAdminView from './views/UserAdminView.vue'
import LoginView from './views/LoginView.vue'
import { getSession, logoutUser, openUserDatabase, type Session } from './db/auth'
import { autoSyncNow, enableRealtimeSync, ensureCloudBinding, stopRealtime } from './sync/engine'
import { clockIn, getAttendance, getWorkRule, getWeeklyNote, searchLogItems, searchMemos, smartClockOut, type WorkRule } from './db/repo'
import { addDays, hhmm, todayStr, weekStart } from './lib/date'
import { getWorkRule, getWeeklyNote, searchLogItems, searchMemos } from './db/repo'
import { todayStr, weekStart } from './lib/date'
import { showToast, useToasts } from './lib/toast'
import { attendanceChanged, focusDate, focusMemo, notifyAttendanceChanged } from './lib/bus'
import { categoryLabel, type Attendance, type LogItem, type Memo } from './db/schema'
import { focusDate, focusMemo } from './lib/bus'
import { categoryLabel, type LogItem, type Memo } from './db/schema'
const toasts = useToasts()
@@ -30,8 +30,7 @@ async function onLogin(s: Session) {
openUserDatabase(s.userId)
location.hash = '#/calendar'
route.value = 'calendar'
await refreshClock()
await refreshTip()
await checkWeeklyReminder()
startSyncTimer()
try {
await ensureCloudBinding()
@@ -161,72 +160,24 @@ function pickLog(item: LogItem & { date: string }) { openLog(item); mobileSearch
function pickMemo(m: Memo) { openMemo(m); mobileSearch.value = false }
// ---- 工具栏打卡 ----
const today = ref(todayStr())
const att = ref<Attendance | undefined>(undefined)
const yesterdayPending = ref(false)
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()
if (wd === 5 || wd === 6 || wd === 0) {
const note = await getWeeklyNote(weekStart(today.value))
weekTip.value = !note || (!note.highlights && !note.challenges && !note.plan_next)
} else {
weekTip.value = false
}
// ---- 周记提醒:周五至周日打开应用时 toast 提示一次,不占用常驻界面 ----
async function checkWeeklyReminder() {
try {
const rule = await getWorkRule()
if (rule.remind_weekly === 'off') return
const wd = new Date().getDay()
if (wd !== 5 && wd !== 6 && wd !== 0) return
const note = await getWeeklyNote(weekStart(todayStr()))
if (note && (note.highlights || note.challenges || note.plan_next)) return
showToast('本周周记还没写,可在「总结」页填写')
} catch { /* 提醒检查失败不影响使用 */ }
}
onMounted(async () => {
window.addEventListener('keydown', onGlobalKey)
if (session.value) {
openUserDatabase(session.value.userId)
await refreshClock()
await refreshTip()
await checkWeeklyReminder()
startSyncTimer()
}
})
@@ -287,17 +238,7 @@ onMounted(async () => {
<div v-else class="gs-empty muted">无匹配结果</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>
<main class="content">
<div class="content-inner">
@@ -507,8 +448,6 @@ onMounted(async () => {
}
.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; }
.gs-icon { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); color: var(--text-3); }
.gs-input {
@@ -554,21 +493,6 @@ onMounted(async () => {
.gs-date { font-size: 12px; flex: none; }
.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-inner { max-width: 1280px; margin: 0 auto; padding: 20px 24px 48px; }
@@ -752,10 +676,7 @@ onMounted(async () => {
.gsearch { display: none; }
.gsearch .gs-panel { display: none; }
.mob-search-btn { display: flex; }
.topbar-actions { margin-left: auto; gap: 6px; }
.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; }
.mob-search-btn { margin-left: auto; }
.tabbar { display: flex; }
.tab-btn { height: 56px; font-size: 11px; }