feat: 登录即自动绑定云端并同步,免手动配置
This commit is contained in:
@@ -78,7 +78,7 @@ async function submit() {
|
||||
{{ mode === 'login' ? '登录' : '创建并进入' }}
|
||||
</button>
|
||||
<div class="muted login-note">
|
||||
登录密码仅在本机用于身份校验,系统只保存密码的 PBKDF2 哈希;忘记密码将无法访问该用户数据
|
||||
登录后自动开启云端同步(密码会保存在本机用于云同步);系统只保存密码哈希,忘记密码将无法访问该用户数据
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -13,7 +13,8 @@ import { downloadCsv } from '../lib/csv'
|
||||
import { hhmm, parseDateStr, todayStr } from '../lib/date'
|
||||
import { computeDay } from '../domain/attendance'
|
||||
import { changeLoginPassword, deleteCurrentUser, getSession } from '../db/auth'
|
||||
import { getSyncLastTime, isSyncConfigured, registerCloudAccount, runSync, type SyncResult } from '../sync/engine'
|
||||
import { ensureCloudBinding, getSyncBase, getSyncLastTime, syncWithStoredConfig, type SyncResult } from '../sync/engine'
|
||||
import { getCloudCreds } from '../db/auth'
|
||||
import { showToast } from '../lib/toast'
|
||||
|
||||
const rule = ref<WorkRule>({ work_start: '09:00', work_end: '18:00', grace_minutes: 10, lunch_minutes: 60, remind_weekly: 'friday' })
|
||||
@@ -36,35 +37,30 @@ const newLoginPwd2 = ref('')
|
||||
const accError = ref('')
|
||||
const deleteAccConfirm = ref(false)
|
||||
const syncBase = ref('')
|
||||
const syncUser = ref('')
|
||||
const syncPwd = ref('')
|
||||
const cloudUser = ref('')
|
||||
const syncStatus = ref('')
|
||||
const syncError = ref('')
|
||||
const syncing = ref(false)
|
||||
const lastSync = ref('')
|
||||
|
||||
async function loadSyncInfo() {
|
||||
syncBase.value = await getSetting('sync_base_url', '')
|
||||
syncUser.value = await getSetting('sync_username', '')
|
||||
syncPwd.value = await getSetting('sync_password', '')
|
||||
syncBase.value = await getSyncBase()
|
||||
cloudUser.value = getCloudCreds()?.username || ''
|
||||
lastSync.value = await getSyncLastTime()
|
||||
}
|
||||
|
||||
async function saveSyncConfig() {
|
||||
await setSetting('sync_base_url', syncBase.value.trim())
|
||||
await setSetting('sync_username', syncUser.value.trim())
|
||||
await setSetting('sync_password', syncPwd.value)
|
||||
showToast('同步配置已保存')
|
||||
showToast('同步地址已保存')
|
||||
}
|
||||
|
||||
async function registerCloud() {
|
||||
async function rebindCloud() {
|
||||
syncError.value = ''
|
||||
try {
|
||||
await registerCloudAccount(syncBase.value, syncUser.value, syncPwd.value)
|
||||
await saveSyncConfig()
|
||||
showToast('云端账号已注册,可直接同步')
|
||||
await ensureCloudBinding()
|
||||
showToast('云端绑定已重建')
|
||||
} catch (e) {
|
||||
syncError.value = e instanceof Error ? e.message : '注册失败'
|
||||
syncError.value = e instanceof Error ? e.message : '绑定失败'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +70,7 @@ async function doSyncNow() {
|
||||
syncing.value = true
|
||||
try {
|
||||
await saveSyncConfig()
|
||||
const result: SyncResult = await runSync({ baseUrl: syncBase.value, username: syncUser.value, password: syncPwd.value })
|
||||
const result: SyncResult = await syncWithStoredConfig()
|
||||
lastSync.value = result.at
|
||||
syncStatus.value = '推送 ' + result.pushed + ' 条 · 拉取 ' + result.pulled + ' 条 · 删除 ' + result.removed + ' 条'
|
||||
showToast('同步完成')
|
||||
@@ -343,24 +339,15 @@ async function doImport() {
|
||||
|
||||
<div class="card section">
|
||||
<div class="section-title">多端数据同步</div>
|
||||
<div class="muted acc-line">在自建同步服务端注册云端账号后,手机(PWA)、桌面与网页端登录同一账号即可互通数据;密码库以密文同步,主密码永不出本机</div>
|
||||
<div class="ai-grid">
|
||||
<div class="rule-item">
|
||||
<label>同步服务地址</label>
|
||||
<input class="input" v-model="syncBase" placeholder="如 https://daywk.linyux.cn" />
|
||||
</div>
|
||||
<div class="rule-item">
|
||||
<label>云端用户名</label>
|
||||
<input class="input" v-model="syncUser" placeholder="云端账号用户名" />
|
||||
</div>
|
||||
<div class="rule-item">
|
||||
<label>云端密码(至少 6 位)</label>
|
||||
<input type="password" class="input" v-model="syncPwd" placeholder="云端账号密码" />
|
||||
</div>
|
||||
<div class="muted acc-line">云端账号:{{ cloudUser || '未绑定' }} · 登录即自动绑定并同步(变更实时推送 + 每 5 分钟兜底);密码库以密文同步,主密码永不出本机</div>
|
||||
<div class="rule-item">
|
||||
<label>同步服务地址(默认即可)</label>
|
||||
<input class="input" v-model="syncBase" placeholder="https://daywk.linyux.cn" />
|
||||
</div>
|
||||
<div class="rule-save">
|
||||
<button class="btn btn-sm" @click="registerCloud">注册云端账号</button>
|
||||
<button class="btn btn-sm" @click="saveSyncConfig">保存地址</button>
|
||||
<button class="btn btn-primary btn-sm" :disabled="syncing" @click="doSyncNow">{{ syncing ? '同步中' : '立即同步' }}</button>
|
||||
<button class="btn btn-sm" @click="rebindCloud">重建云端绑定</button>
|
||||
</div>
|
||||
<div v-if="syncStatus" class="muted acc-line">上次同步:{{ lastSync || '--' }} · {{ syncStatus }}</div>
|
||||
<div v-if="syncError" class="form-error">{{ syncError }}</div>
|
||||
|
||||
Reference in New Issue
Block a user