feat: add login background darken factor

This commit is contained in:
Esing
2026-05-12 22:12:02 +08:00
parent edba6b80d3
commit 22c35119c0
8 changed files with 65 additions and 7 deletions

View File

@@ -143,6 +143,7 @@ const en = {
websiteTitle: 'Title', websiteTitle: 'Title',
loginBoxOpacity: 'Login Box Opacity', loginBoxOpacity: 'Login Box Opacity',
loginBackground: 'Background', loginBackground: 'Background',
backgroundDarken: 'Background Dim',
emailSetting: 'Email', emailSetting: 'Email',
receiveEmail: 'Receive Email', receiveEmail: 'Receive Email',
autoRefresh: 'Auto Refresh', autoRefresh: 'Auto Refresh',

View File

@@ -143,6 +143,7 @@ const zh = {
websiteTitle: '网站标题', websiteTitle: '网站标题',
loginBoxOpacity: '登录透明', loginBoxOpacity: '登录透明',
loginBackground: '登录背景', loginBackground: '登录背景',
backgroundDarken: '背景压暗',
emailSetting: '邮件设置', emailSetting: '邮件设置',
receiveEmail: '邮件接收', receiveEmail: '邮件接收',
autoRefresh: '自动刷新', autoRefresh: '自动刷新',

View File

@@ -6,6 +6,7 @@ export const useSettingStore = defineStore('setting', {
settings: { settings: {
r2Domain: '', r2Domain: '',
loginOpacity: 1.00, loginOpacity: 1.00,
loginDarkenFactor: 0,
}, },
lang: '', lang: '',
}), }),

View File

@@ -237,16 +237,27 @@ const loginOpacity = computed(() => {
return uiStore.dark ? `rgba(0, 0, 0, ${opacity})` : `rgba(255, 255, 255, ${opacity})` return uiStore.dark ? `rgba(0, 0, 0, ${opacity})` : `rgba(255, 255, 255, ${opacity})`
}) })
const loginDarkenFactor = computed(() => {
const factor = Number(settingStore.settings.loginDarkenFactor ?? 0)
if (Number.isNaN(factor)) return 0
return Math.min(1, Math.max(0, factor))
})
const hideLoginDomain = computed(() => settingStore.settings.loginDomain === 1) const hideLoginDomain = computed(() => settingStore.settings.loginDomain === 1)
const background = computed(() => { const background = computed(() => {
const bg = settingStore.settings.background
return settingStore.settings.background ? { if (!bg) return ''
'background-image': `url(${cvtR2Url(settingStore.settings.background)})`, const bgUrl = cvtR2Url(bg)
'background-repeat': 'no-repeat', return {
'background-size': 'cover', 'background-image': `
'background-position': 'center' linear-gradient(rgba(0, 0, 0, ${loginDarkenFactor.value}), rgba(0, 0, 0, ${loginDarkenFactor.value})),
} : '' url(${bgUrl})
`,
'background-repeat': 'no-repeat, no-repeat',
'background-size': 'cover, cover',
'background-position': 'center, center'
}
}) })
const openSelect = () => { const openSelect = () => {

View File

@@ -120,6 +120,13 @@
</div> </div>
</div> </div>
</div> </div>
<div class="setting-item">
<div class="title-item"><span>{{ $t('backgroundDarken') }}</span></div>
<div>
<el-input-number size="small" v-model="loginDarkenFactor" @change="darkenChange" :precision="2"
:step="0.01" :max="1" :min="0"/>
</div>
</div>
</div> </div>
</div> </div>
@@ -855,6 +862,7 @@ const settingLoading = ref(false)
const clearS3Loading = ref(false) const clearS3Loading = ref(false)
const r2DomainInput = ref('') const r2DomainInput = ref('')
const loginOpacity = ref(0) const loginOpacity = ref(0)
const loginDarkenFactor = ref(0)
const minEmailPrefix = ref(0) const minEmailPrefix = ref(0)
const emailPrefixFilter = ref([]) const emailPrefixFilter = ref([])
const backgroundUrl = ref('') const backgroundUrl = ref('')
@@ -946,6 +954,7 @@ function getSettings() {
settingStore.domainList = settingData.domainList; settingStore.domainList = settingData.domainList;
resendTokenForm.domain = setting.value.domainList[0] resendTokenForm.domain = setting.value.domainList[0]
loginOpacity.value = setting.value.loginOpacity loginOpacity.value = setting.value.loginOpacity
loginDarkenFactor.value = normalizeFactor(setting.value.loginDarkenFactor)
minEmailPrefix.value = setting.value.minEmailPrefix minEmailPrefix.value = setting.value.minEmailPrefix
firstLoading.value = false firstLoading.value = false
backgroundUrl.value = setting.value.background?.startsWith('http') ? setting.value.background : '' backgroundUrl.value = setting.value.background?.startsWith('http') ? setting.value.background : ''
@@ -1231,6 +1240,19 @@ function doOpacityChange() {
editSetting(form, true) editSetting(form, true)
} }
function normalizeFactor(value) {
const factor = Number(value ?? 0)
if (Number.isNaN(factor)) return 0
return Math.min(1, Math.max(0, factor))
}
function doDarkenChange() {
if (!settingReady.value) return
const form = {}
form.loginDarkenFactor = normalizeFactor(loginDarkenFactor.value)
editSetting(form, true)
}
function resetEmailPrefix() { function resetEmailPrefix() {
minEmailPrefix.value = setting.value.minEmailPrefix minEmailPrefix.value = setting.value.minEmailPrefix
emailPrefixFilter.value = setting.value.emailPrefixFilter emailPrefixFilter.value = setting.value.emailPrefixFilter
@@ -1262,6 +1284,11 @@ const opacityChange = debounce(doOpacityChange, 1000, {
trailing: true trailing: true
}) })
const darkenChange = debounce(doDarkenChange, 1000, {
leading: false,
trailing: true
})
function saveBlackList() { function saveBlackList() {
let form = { let form = {
@@ -1494,6 +1521,7 @@ function editSetting(settingForm, refreshStatus = true) {
aiCodeFilterShow.value = false aiCodeFilterShow.value = false
}).catch((e) => { }).catch((e) => {
loginOpacity.value = setting.value.loginOpacity loginOpacity.value = setting.value.loginOpacity
loginDarkenFactor.value = normalizeFactor(setting.value.loginDarkenFactor)
setting.value = {...setting.value, ...JSON.parse(backup)} setting.value = {...setting.value, ...JSON.parse(backup)}
}).finally(() => { }).finally(() => {
settingLoading.value = false settingLoading.value = false

View File

@@ -24,6 +24,7 @@ export const setting = sqliteTable('setting', {
ruleEmail: text('rule_email').default('').notNull(), ruleEmail: text('rule_email').default('').notNull(),
ruleType: integer('rule_type').default(0).notNull(), ruleType: integer('rule_type').default(0).notNull(),
loginOpacity: integer('login_opacity').default(0.88), loginOpacity: integer('login_opacity').default(0.88),
loginDarkenFactor: integer('login_darken_factor').default(0),
resendTokens: text('resend_tokens').default("{}").notNull(), resendTokens: text('resend_tokens').default("{}").notNull(),
noticeTitle: text('notice_title').default('').notNull(), noticeTitle: text('notice_title').default('').notNull(),
noticeContent: text('notice_content').default('').notNull(), noticeContent: text('notice_content').default('').notNull(),

View File

@@ -29,10 +29,19 @@ const dbInit = {
await this.v2_8DB(c); await this.v2_8DB(c);
await this.v2_9DB(c); await this.v2_9DB(c);
await this.v3_0DB(c); await this.v3_0DB(c);
await this.v3_1DB(c);
await settingService.refresh(c); await settingService.refresh(c);
return c.text('success'); return c.text('success');
}, },
async v3_1DB(c) {
try {
await c.env.db.prepare(`ALTER TABLE setting ADD COLUMN login_darken_factor INTEGER NOT NULL DEFAULT 0;`).run();
} catch (e) {
console.warn(`跳过字段:${e.message}`);
}
},
async v3_0DB(c) { async v3_0DB(c) {
try { try {
await c.env.db.batch([ await c.env.db.batch([

View File

@@ -138,6 +138,11 @@ const settingService = {
params.aiCodeFilter = params.aiCodeFilter + ''; params.aiCodeFilter = params.aiCodeFilter + '';
} }
if (params.loginDarkenFactor !== undefined) {
const factor = Number(params.loginDarkenFactor);
params.loginDarkenFactor = Number.isNaN(factor) ? 0 : Math.min(1, Math.max(0, factor));
}
params.resendTokens = JSON.stringify(resendTokens); params.resendTokens = JSON.stringify(resendTokens);
await orm(c).update(setting).set({ ...params }).returning().get(); await orm(c).update(setting).set({ ...params }).returning().get();
await this.refresh(c); await this.refresh(c);
@@ -214,6 +219,7 @@ const settingService = {
siteKey: settingRow.siteKey, siteKey: settingRow.siteKey,
background: settingRow.background, background: settingRow.background,
loginOpacity: settingRow.loginOpacity, loginOpacity: settingRow.loginOpacity,
loginDarkenFactor: settingRow.loginDarkenFactor,
domainList: settingRow.loginDomain === 1 && !token ? [] : settingRow.domainList, domainList: settingRow.loginDomain === 1 && !token ? [] : settingRow.domainList,
regKey: settingRow.regKey, regKey: settingRow.regKey,
regVerifyOpen: settingRow.regVerifyOpen, regVerifyOpen: settingRow.regVerifyOpen,