feat: 长期计划(目标→每日任务物化+进度条) / 详情页Markdown范围导出 / 记账与详情页改内容优先弹窗新增
This commit is contained in:
@@ -11,7 +11,7 @@ import { type Project } from '../db/schema'
|
||||
import { getLogCategories, setLogCategories, getLedgerCategories, setLedgerCategories } from '../db/categories'
|
||||
import { downloadText, } from '../lib/download'
|
||||
import { downloadCsv } from '../lib/csv'
|
||||
import { addDays, hhmm, parseDateStr, todayStr, weekStart } from '../lib/date'
|
||||
import { hhmm, parseDateStr, todayStr } from '../lib/date'
|
||||
import { computeDay } from '../domain/attendance'
|
||||
import { changeLoginPassword, deleteCurrentUser, getSession } from '../db/auth'
|
||||
import { ensureCloudBinding, getSyncLastTime, isSyncConfigured, syncWithStoredConfig, syncLastError, type SyncResult } from '../sync/engine'
|
||||
@@ -72,41 +72,6 @@ async function removeCat(kind: 'log' | 'expense' | 'income', index: number) {
|
||||
showToast('分类已删除')
|
||||
}
|
||||
|
||||
// ---- 工作详情范围导出 ----
|
||||
const expRange = ref<'day' | 'week' | 'month' | 'custom'>('day')
|
||||
const expStart = ref(todayStr())
|
||||
const expEnd = ref(todayStr())
|
||||
function rangeStartEnd(): { start: string; end: string; label: string } {
|
||||
const t = todayStr()
|
||||
if (expRange.value === 'day') return { start: expStart.value, end: expStart.value, label: expStart.value }
|
||||
if (expRange.value === 'week') { const ws = weekStart(expStart.value); return { start: ws, end: addDays(ws, 6), label: ws + ' ~ ' + addDays(ws, 6) } }
|
||||
if (expRange.value === 'month') { const y = expStart.value.slice(0, 4); const m = expStart.value.slice(5, 7); const last = new Date(Number(y), Number(m), 0).getDate(); return { start: y + '-' + m + '-01', end: y + '-' + m + '-' + last, label: y + '-' + m } }
|
||||
return { start: expStart.value, end: expEnd.value, label: expStart.value + ' ~ ' + expEnd.value }
|
||||
}
|
||||
async function doExportRange() {
|
||||
const { start, end, label } = rangeStartEnd()
|
||||
const found = await Promise.all([listLogItemsBetween(start, end), listProjects(true)])
|
||||
const items = found[0]
|
||||
const projects = found[1]
|
||||
const pmap = new Map<number, string>(projects.map(p => [p.id as number, p.name]))
|
||||
const rows: (string | number | null)[][] = [['日期', '分类', '项目', '内容', '耗时(分钟)', '成果', '待跟进', '收获', '备注']]
|
||||
for (const it of items) {
|
||||
rows.push([
|
||||
it.date,
|
||||
categoryLabel(it.category),
|
||||
it.project_id ? (pmap.get(it.project_id) || '') : '',
|
||||
it.content,
|
||||
it.minutes == null ? '' : it.minutes,
|
||||
it.is_milestone ? '是' : '',
|
||||
it.needs_followup ? '是' : '',
|
||||
it.takeaway || '',
|
||||
it.remark || ''
|
||||
])
|
||||
}
|
||||
const file = '工作详情_' + label.replace(/[~s]/g, '_') + '.csv'
|
||||
const p = await downloadCsv(file, rows)
|
||||
showToast(p ? '已导出:' + p : '已导出到系统下载目录(' + items.length + ' 条)')
|
||||
}
|
||||
const fileInput = ref<HTMLInputElement | null>(null)
|
||||
const pendingImport = ref<{ name: string; text: string } | null>(null)
|
||||
const importError = ref('')
|
||||
@@ -490,30 +455,6 @@ async function doImport() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card section">
|
||||
<div class="section-title">工作详情导出</div>
|
||||
<div class="seg">
|
||||
<button class="seg-btn" :class="{ active: expRange === 'day' }" @click="expRange = 'day'">当日</button>
|
||||
<button class="seg-btn" :class="{ active: expRange === 'week' }" @click="expRange = 'week'">当周</button>
|
||||
<button class="seg-btn" :class="{ active: expRange === 'month' }" @click="expRange = 'month'">当月</button>
|
||||
<button class="seg-btn" :class="{ active: expRange === 'custom' }" @click="expRange = 'custom'">自定义</button>
|
||||
</div>
|
||||
<div class="exp-dates">
|
||||
<template v-if="expRange === 'custom'">
|
||||
<input class="input" type="date" v-model="expStart" />
|
||||
<span class="muted">至</span>
|
||||
<input class="input" type="date" v-model="expEnd" />
|
||||
</template>
|
||||
<template v-else>
|
||||
<input class="input" type="date" v-model="expStart" />
|
||||
<span class="muted loc-note">{{ expRange === 'day' ? '导出该日' : expRange === 'week' ? '导出该日期所在一周' : '导出该日期所在月份' }}</span>
|
||||
</template>
|
||||
</div>
|
||||
<div class="rule-save">
|
||||
<button class="btn btn-primary btn-sm" @click="doExportRange">导出 CSV</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card section">
|
||||
<div class="section-title">数据备份</div>
|
||||
<div class="backup-row">
|
||||
|
||||
Reference in New Issue
Block a user