新增邮件发送和管理员功能
This commit is contained in:
@@ -1,177 +1,486 @@
|
||||
<template>
|
||||
<div class="box">
|
||||
<div class="setting">
|
||||
<div class="title">网站设置</div>
|
||||
<div class="setting-item">
|
||||
<div><span>用户注册</span></div>
|
||||
<div>
|
||||
<el-switch @change="change" :before-change="beforeChange" :active-value="0" :inactive-value="1"
|
||||
v-model="setting.register"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div><span>添加邮箱</span></div>
|
||||
<div>
|
||||
<el-switch @change="change" :before-change="beforeChange" :active-value="0" :inactive-value="1"
|
||||
v-model="setting.addEmail"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="setting-item">
|
||||
<div><span>邮件接收</span></div>
|
||||
<div>
|
||||
<el-switch @change="change" :before-change="beforeChange" :active-value="0" :inactive-value="1"
|
||||
v-model="setting.receive"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div><span>注册验证</span></div>
|
||||
<div>
|
||||
<el-switch @change="change" :before-change="beforeChange" :active-value="0" :inactive-value="1"
|
||||
v-model="setting.registerVerify"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div><span>添加验证</span></div>
|
||||
<div>
|
||||
<el-switch @change="change" :before-change="beforeChange" :active-value="0" :inactive-value="1"
|
||||
v-model="setting.addEmailVerify"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<span>多号模式</span>
|
||||
<el-popover
|
||||
content="开启后账号栏出现一个用户可以添加多个邮箱"
|
||||
>
|
||||
<template #reference>
|
||||
<Icon class="warning" icon="fe:warning" width="20" height="20" />
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div>
|
||||
<el-switch @change="change" :before-change="beforeChange" :active-value="0" :inactive-value="1"
|
||||
v-model="setting.manyEmail"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item ">
|
||||
<div>
|
||||
<span>轮询刷新</span>
|
||||
<el-popover
|
||||
|
||||
content="轮询请求服务器获取最新邮件人多可能会超出免费额度"
|
||||
>
|
||||
<template #reference>
|
||||
<Icon class="warning" icon="fe:warning" width="20" height="20" />
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="item-select">
|
||||
<el-select
|
||||
@change="change"
|
||||
style="width: 80px;"
|
||||
v-model="setting.autoRefreshTime"
|
||||
placeholder="Select"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div class="title-item"><span>网站标题</span></div>
|
||||
<div class="email-title">
|
||||
<div>{{ setting.title }}</div>
|
||||
<div @click="editTitleShow = true">
|
||||
<Icon icon="iconamoon:edit-light" width="24" height="24"/>
|
||||
<div class="settings-container">
|
||||
<el-scrollbar class="scroll">
|
||||
<div class="card-grid">
|
||||
<!-- Website Settings Card -->
|
||||
<div class="settings-card">
|
||||
<div class="card-title">网站设置</div>
|
||||
<div class="card-content">
|
||||
<div class="setting-item">
|
||||
<div><span>用户注册</span></div>
|
||||
<div>
|
||||
<el-switch @change="change" :before-change="beforeChange" :active-value="0" :inactive-value="1"
|
||||
v-model="setting.register"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div><span>添加邮箱</span></div>
|
||||
<div>
|
||||
<el-switch @change="change" :before-change="beforeChange" :active-value="0" :inactive-value="1"
|
||||
v-model="setting.addEmail"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<span>多号模式</span>
|
||||
<el-tooltip effect="dark" content="开启后账号栏出现一个用户可以添加多个邮箱">
|
||||
<Icon class="warning" icon="fe:warning" width="20" height="20"/>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div>
|
||||
<el-switch @change="change" :before-change="beforeChange" :active-value="0" :inactive-value="1"
|
||||
v-model="setting.manyEmail"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<span>轮询刷新</span>
|
||||
<el-tooltip effect="dark" content="轮询请求服务器获取最新邮件">
|
||||
<Icon class="warning" icon="fe:warning" width="20" height="20"/>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div>
|
||||
<el-select
|
||||
@change="change"
|
||||
style="width: 80px;"
|
||||
v-model="setting.autoRefreshTime"
|
||||
placeholder="Select"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div>
|
||||
<span>物理清空数据</span>
|
||||
<el-tooltip effect="dark" content="该操作会物理清空所有已被删除的数据">
|
||||
<Icon class="warning" icon="fe:warning" width="20" height="20"/>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div>
|
||||
<el-button class="opt-button" style="margin-top: 0" @click="physicsDeleteAllData" size="small"
|
||||
type="primary">
|
||||
<Icon icon="material-symbols:delete-outline-rounded" width="16" height="16"/>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Personalization Settings Card -->
|
||||
<div class="settings-card">
|
||||
<div class="card-title">个性化设置</div>
|
||||
<div class="card-content">
|
||||
<div class="setting-item">
|
||||
<div class="title-item"><span>网站标题</span></div>
|
||||
<div class="email-title">
|
||||
<span>{{ setting.title }}</span>
|
||||
<el-button class="opt-button" size="small" type="primary" @click="editTitleShow = true">
|
||||
<Icon icon="lsicon:edit-outline" width="16" height="16"/>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item personalized">
|
||||
<div><span>登录背景</span></div>
|
||||
<div>
|
||||
<el-image
|
||||
class="background"
|
||||
:src="cvtR2Url(setting.background)"
|
||||
:preview-src-list="[cvtR2Url(setting.background)]"
|
||||
show-progress
|
||||
fit="cover"
|
||||
>
|
||||
<template #error>
|
||||
<div class="error-image" @click="openCut">
|
||||
<Icon icon="ph:image" width="24" height="24"/>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<div class="background-btn">
|
||||
<el-button class="opt-button" size="small" type="primary" @click="openCut">
|
||||
<Icon icon="lsicon:edit-outline" width="16" height="16"/>
|
||||
</el-button>
|
||||
<el-button class="opt-button" size="small" type="primary" @click="delBackground">
|
||||
<Icon icon="material-symbols:delete-outline-rounded" width="16" height="16"/>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Email Sending Settings Card -->
|
||||
<div class="settings-card">
|
||||
<div class="card-title">邮件设置</div>
|
||||
<div class="card-content">
|
||||
<div class="setting-item">
|
||||
<div><span>邮件接收</span></div>
|
||||
<div>
|
||||
<el-switch @change="change" :before-change="beforeChange" :active-value="0" :inactive-value="1"
|
||||
v-model="setting.receive"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div><span>邮件发送</span></div>
|
||||
<div>
|
||||
<el-switch @change="change" :before-change="beforeChange" :active-value="0" :inactive-value="1"
|
||||
v-model="setting.send"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div><span>添加resend令牌</span></div>
|
||||
<div>
|
||||
<el-button class="opt-button" style="margin-top: 0" @click="openResendForm" size="small" type="primary">
|
||||
<Icon icon="material-symbols:add-rounded" width="16" height="16"/>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item token-item" v-for="(value, key, index) in setting.resendTokens" :key="index">
|
||||
<div><span>{{ key }}</span></div>
|
||||
<div><span>{{ value }}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- R2 Object Storage Card -->
|
||||
<div class="settings-card">
|
||||
<div class="card-title">R2对象存储</div>
|
||||
<div class="card-content">
|
||||
<div class="setting-item">
|
||||
<div><span>访问域名</span></div>
|
||||
<div class="r2domain">
|
||||
<span>{{ setting.r2Domain || '空' }}</span>
|
||||
<el-button class="opt-button" size="small" type="primary" @click="r2DomainShow = true">
|
||||
<Icon icon="lsicon:edit-outline" width="16" height="16"/>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Turnstile Verification Card -->
|
||||
<div class="settings-card">
|
||||
<div class="card-title">Turnstile 人机验证</div>
|
||||
<div class="card-content">
|
||||
<div class="setting-item">
|
||||
<div><span>注册验证</span></div>
|
||||
<div>
|
||||
<el-switch @change="change" :before-change="beforeChange" :active-value="0" :inactive-value="1"
|
||||
v-model="setting.registerVerify"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div><span>添加验证</span></div>
|
||||
<div>
|
||||
<el-switch @change="change" :before-change="beforeChange" :active-value="0" :inactive-value="1"
|
||||
v-model="setting.addEmailVerify"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div><span>siteKey</span></div>
|
||||
<div class="bot-verify">
|
||||
<span>{{ setting.siteKey || '空' }}</span>
|
||||
<el-button class="opt-button" size="small" type="primary" @click="turnstileShow = true">
|
||||
<Icon icon="lsicon:edit-outline" width="16" height="16"/>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<div><span>secretKey</span></div>
|
||||
<div class="bot-verify">
|
||||
<span> {{ setting.secretKey || '空' }} </span>
|
||||
<el-button class="opt-button" size="small" type="primary" @click="turnstileShow = true">
|
||||
<Icon icon="lsicon:edit-outline" width="16" height="16"/>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-card">
|
||||
<div class="card-title">关于</div>
|
||||
<div class="card-content">
|
||||
<div class="concerning-item">
|
||||
<span>版本:</span>
|
||||
<span>v1.1.0</span>
|
||||
</div>
|
||||
<div class="concerning-item">
|
||||
<span>交流:</span>
|
||||
<el-button @click="jumpTelegram">
|
||||
telegram
|
||||
<template #icon>
|
||||
<Icon icon="logos:telegram" width="30" height="30"/>
|
||||
</template>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog v-model="editTitleShow" title="修改标题" width="340" @close="editTitle = ''">
|
||||
<form>
|
||||
<el-input type="text" placeholder="网站标题" v-model="editTitle"/>
|
||||
<el-button type="primary" :loading="editTitleLoading" @click="saveTitle">保存</el-button>
|
||||
</form>
|
||||
</el-dialog>
|
||||
|
||||
|
||||
<!-- Dialogs remain the same -->
|
||||
<el-dialog v-model="editTitleShow" title="修改标题" width="340" @closed="editTitle = ''">
|
||||
<form>
|
||||
<el-input type="text" placeholder="网站标题" v-model="editTitle"/>
|
||||
<el-button type="primary" :loading="settingLoading" @click="saveTitle">保存</el-button>
|
||||
</form>
|
||||
</el-dialog>
|
||||
<el-dialog v-model="resendTokenFormShow" title="添加resend令牌" width="340" @closed="cleanResendTokenForm">
|
||||
<form>
|
||||
<el-select style="margin-bottom: 15px" v-model="resendTokenForm.domain" placeholder="Select">
|
||||
<el-option
|
||||
v-for="item in settingStore.domainList"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input type="text" placeholder="令牌" v-model="resendTokenForm.token"/>
|
||||
<el-button type="primary" :loading="settingLoading" @click="saveResendToken">保存</el-button>
|
||||
</form>
|
||||
</el-dialog>
|
||||
<el-dialog v-model="r2DomainShow" title="添加R2访问域名" width="340" @closed="r2DomainInput = ''">
|
||||
<form>
|
||||
<el-input type="text" placeholder="R2访问域名" v-model="r2DomainInput"/>
|
||||
<el-button type="primary" :loading="settingLoading" @click="saveR2domain">保存</el-button>
|
||||
</form>
|
||||
</el-dialog>
|
||||
<el-dialog v-model="turnstileShow" title="添加Turnstile密钥" width="340"
|
||||
@closed="turnstileForm.secretKey = '';turnstileForm.siteKey = ''">
|
||||
<form>
|
||||
<el-input type="text" placeholder="siteKey" v-model="turnstileForm.siteKey"/>
|
||||
<el-input type="text" style="margin-top: 15px" placeholder="secretKey" v-model="turnstileForm.secretKey"/>
|
||||
<el-button type="primary" :loading="settingLoading" @click="saveTurnstileKey">保存</el-button>
|
||||
</form>
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-model="cutShow"
|
||||
title="背景截图"
|
||||
class="cut-dialog"
|
||||
>
|
||||
<div class="cropper">
|
||||
<vueCropper
|
||||
ref="cropper"
|
||||
:img="cutImage"
|
||||
:fixedNumber="[16,9]"
|
||||
outputType="jpeg"
|
||||
:fixed="true"
|
||||
:centerBox="true"
|
||||
:full="true"
|
||||
:autoCrop="true"
|
||||
:outputSize="0.9"
|
||||
></vueCropper>
|
||||
</div>
|
||||
<div class="cut-button">
|
||||
<el-button type="primary" :loading="settingLoading" @click="saveBackground">保存</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {defineOptions} from "vue";
|
||||
import {ref} from 'vue'
|
||||
import {settingSet} from "@/request/setting.js";
|
||||
import {ElMessage} from "element-plus";
|
||||
import {defineOptions, nextTick, onMounted, reactive, ref} from "vue";
|
||||
import {physicsDeleteAll, setBackground, settingQuery, settingSet} from "@/request/setting.js";
|
||||
import {ElMessage, ElMessageBox} from "element-plus";
|
||||
import {useSettingStore} from "@/store/setting.js";
|
||||
import {useUserStore} from "@/store/user.js";
|
||||
import {useAccountStore} from "@/store/account.js";
|
||||
import {Icon} from "@iconify/vue";
|
||||
import {compressImage} from "@/utils/file-utils.js";
|
||||
import {cvtR2Url} from "@/utils/convert.js";
|
||||
import {storeToRefs} from "pinia";
|
||||
|
||||
defineOptions({
|
||||
name: 'sys-setting'
|
||||
})
|
||||
|
||||
const cropper = ref()
|
||||
const cutImage = ref('')
|
||||
const cutShow = ref(false)
|
||||
const accountStore = useAccountStore();
|
||||
const userStore = useUserStore();
|
||||
const editTitleShow = ref(false)
|
||||
const resendTokenFormShow = ref(false)
|
||||
const r2DomainShow = ref(false)
|
||||
const turnstileShow = ref(false)
|
||||
const settingStore = useSettingStore();
|
||||
let setting = ref(settingStore.settings)
|
||||
const {settings: setting} = storeToRefs(settingStore);
|
||||
const editTitle = ref('')
|
||||
const editTitleLoading = ref(false)
|
||||
const settingLoading = ref(false)
|
||||
const r2DomainInput = ref('')
|
||||
let backup = {}
|
||||
const resendTokenForm = reactive({
|
||||
domain: '',
|
||||
token: '',
|
||||
})
|
||||
const turnstileForm = reactive({
|
||||
siteKey: '',
|
||||
secretKey: ''
|
||||
})
|
||||
const options = [
|
||||
{
|
||||
label: '关闭',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: '3s',
|
||||
value: 3,
|
||||
},
|
||||
{
|
||||
label: '5s',
|
||||
value: 5,
|
||||
},
|
||||
{
|
||||
label: '7s',
|
||||
value: 7,
|
||||
},
|
||||
{
|
||||
label: '10s',
|
||||
value: 10,
|
||||
},
|
||||
{
|
||||
label: '15s',
|
||||
value: 15,
|
||||
},
|
||||
{
|
||||
label: '20s',
|
||||
value: 20,
|
||||
}
|
||||
{label: '关闭', value: 0},
|
||||
{label: '3s', value: 3},
|
||||
{label: '5s', value: 5},
|
||||
{label: '7s', value: 7},
|
||||
{label: '10s', value: 10},
|
||||
{label: '15s', value: 15},
|
||||
{label: '20s', value: 20}
|
||||
]
|
||||
|
||||
function beforeChange() {
|
||||
onMounted(() => {
|
||||
resendTokenForm.domain = settingStore.domainList[0];
|
||||
})
|
||||
|
||||
function physicsDeleteAllData() {
|
||||
ElMessageBox.prompt('此操作不可逆转, 输入 <b style="font-weight: bold">确认删除</b> 继续操作', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
dangerouslyUseHTMLString: true,
|
||||
title: '警告',
|
||||
type: 'warning',
|
||||
inputPattern: /^确认删除$/,
|
||||
inputErrorMessage: '请输入确认删除',
|
||||
}).then(() => {
|
||||
physicsDeleteAll().then(() => {
|
||||
ElMessage({
|
||||
message: "删除成功",
|
||||
type: "success",
|
||||
plain: true
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function delBackground() {
|
||||
ElMessageBox.confirm('确定要删除这个背景吗?', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
setting.value.background = null
|
||||
editSetting({background: null})
|
||||
})
|
||||
}
|
||||
|
||||
function saveTurnstileKey() {
|
||||
const settingForm = {}
|
||||
settingForm.siteKey = turnstileForm.siteKey
|
||||
settingForm.secretKey = turnstileForm.secretKey
|
||||
editSetting(settingForm)
|
||||
}
|
||||
|
||||
function saveBackground() {
|
||||
settingLoading.value = true
|
||||
cropper.value.getCropData(data => {
|
||||
setBackground(data).then(key => {
|
||||
setting.value.background = key
|
||||
cutShow.value = false
|
||||
ElMessage({
|
||||
message: "设置成功",
|
||||
type: "success",
|
||||
plain: true
|
||||
})
|
||||
}).finally(() => {
|
||||
settingLoading.value = false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function openCut() {
|
||||
const doc = document.createElement('input')
|
||||
doc.setAttribute('type', 'file')
|
||||
doc.setAttribute('accept', 'image/*')
|
||||
doc.click()
|
||||
doc.onchange = async (e) => {
|
||||
const image = await compressImage(e.target.files[0], 0.9)
|
||||
cutImage.value = URL.createObjectURL(image)
|
||||
cutShow.value = true
|
||||
}
|
||||
}
|
||||
|
||||
function saveR2domain() {
|
||||
const settingForm = {r2Domain: r2DomainInput.value}
|
||||
if (settingForm.r2Domain && !settingForm.r2Domain.startsWith('http')) {
|
||||
ElMessage({
|
||||
message: "域名必须以http或https开头",
|
||||
type: "error",
|
||||
plain: true
|
||||
})
|
||||
return;
|
||||
}
|
||||
editSetting(settingForm)
|
||||
}
|
||||
|
||||
function openResendForm() {
|
||||
resendTokenFormShow.value = true
|
||||
}
|
||||
|
||||
function saveResendToken() {
|
||||
const settingForm = {
|
||||
resendTokens: {}
|
||||
}
|
||||
const domain = resendTokenForm.domain.slice(1)
|
||||
settingForm.resendTokens[domain] = resendTokenForm.token
|
||||
editSetting(settingForm)
|
||||
}
|
||||
|
||||
function backupSetting() {
|
||||
const settingForm = {...setting.value}
|
||||
delete settingForm.resendTokens
|
||||
delete settingForm.siteKey
|
||||
delete settingForm.secretKey
|
||||
backup = JSON.stringify(setting.value)
|
||||
}
|
||||
|
||||
function cleanResendTokenForm() {
|
||||
resendTokenForm.token = ''
|
||||
}
|
||||
|
||||
function beforeChange() {
|
||||
if (settingLoading.value) return false
|
||||
backupSetting()
|
||||
return true
|
||||
}
|
||||
|
||||
function change() {
|
||||
editSetting(setting)
|
||||
function change(e) {
|
||||
const settingForm = {...setting.value}
|
||||
delete settingForm.siteKey
|
||||
delete settingForm.secretKey
|
||||
delete settingForm.resendTokens
|
||||
editSetting(settingForm, false)
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
settingQuery().then(setting => {
|
||||
settingStore.settings = setting;
|
||||
settingStore.domainList = setting.domainList;
|
||||
})
|
||||
}
|
||||
|
||||
function saveTitle() {
|
||||
backup = JSON.stringify(setting.value)
|
||||
setting.value.title = editTitle.value
|
||||
editSetting(setting)
|
||||
editSetting({title: editTitle.value})
|
||||
}
|
||||
|
||||
function editSetting(setting) {
|
||||
editTitleLoading.value = true
|
||||
settingSet(setting.value).then(() => {
|
||||
editTitleLoading.value = false
|
||||
function jumpTelegram() {
|
||||
const doc = document.createElement('a')
|
||||
doc.href = 'https://t.me/cloud_mail_tg'
|
||||
doc.target = '_blank'
|
||||
doc.click()
|
||||
}
|
||||
|
||||
|
||||
function editSetting(settingForm, refreshStatus = true) {
|
||||
if (settingLoading.value) return
|
||||
settingLoading.value = true
|
||||
settingSet(settingForm).then(() => {
|
||||
settingLoading.value = false
|
||||
ElMessage({
|
||||
message: "设置成功",
|
||||
type: "success",
|
||||
@@ -180,69 +489,256 @@ function editSetting(setting) {
|
||||
if (setting.value.manyEmail === 1) {
|
||||
accountStore.currentAccountId = userStore.user.accountId;
|
||||
}
|
||||
if (refreshStatus) {
|
||||
refresh()
|
||||
}
|
||||
editTitleShow.value = false
|
||||
r2DomainShow.value = false
|
||||
resendTokenFormShow.value = false
|
||||
turnstileShow.value = false
|
||||
}).catch(() => {
|
||||
editTitleLoading.value = false
|
||||
setting.value = JSON.parse(backup)
|
||||
setting.value = {...setting.value, ...JSON.parse(backup)}
|
||||
}).finally(() => {
|
||||
settingLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.box {
|
||||
.settings-container {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
padding: 40px 40px;
|
||||
.scroll {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
.card-grid {
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(420px, 1fr));
|
||||
padding: 20px;
|
||||
gap: 20px;
|
||||
@media (max-width: 500px) {
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
gap: 15px;
|
||||
padding: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.background {
|
||||
width: 230px;
|
||||
height: 120px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #e4e7ed;
|
||||
@media (max-width: 500px) {
|
||||
width: 140px;
|
||||
height: 79px;
|
||||
}
|
||||
}
|
||||
|
||||
.background-btn {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.settings-card {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #e4e7ed;
|
||||
transition: all 300ms;
|
||||
box-shadow: var(--el-box-shadow-light);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
padding: 10px 20px;
|
||||
border-bottom: 1px solid #e6e6e6;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.setting-item {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 10px;
|
||||
font-weight: bold;
|
||||
|
||||
> div:first-child {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.setting {
|
||||
font-size: 14px;
|
||||
> div:last-child {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
justify-items: flex-end;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.warning {
|
||||
margin-left: 5px;
|
||||
color: gray;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cropper {
|
||||
height: 397px;
|
||||
width: 705px;
|
||||
@media (max-width: 767px) {
|
||||
width: calc(100vw - 60px);
|
||||
height: calc((100vw - 60px) * 9 / 16);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.cut-dialog.el-dialog) {
|
||||
width: fit-content !important;
|
||||
height: fit-content !important;
|
||||
}
|
||||
|
||||
.error-image {
|
||||
background: #f5f7fa;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cut-button {
|
||||
padding-top: 15px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
|
||||
.el-button {
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
|
||||
.bot-verify {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
|
||||
span {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
margin-bottom: 40px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.setting-item {
|
||||
display: flex;
|
||||
gap: 140px;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
@media (max-width: 767px) {
|
||||
gap: 80px;
|
||||
}
|
||||
.el-button {
|
||||
width: 48px;
|
||||
margin: 0 0 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
>div:first-child {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.opt-button {
|
||||
width: fit-content !important;
|
||||
}
|
||||
|
||||
.r2domain {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
width: 48px;
|
||||
margin: 0 0 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.personalized {
|
||||
align-items: start;
|
||||
|
||||
> div:last-child {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
|
||||
.el-button {
|
||||
margin-left: 10px;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.warning {
|
||||
position: absolute;
|
||||
left: 65px;
|
||||
color: gray;
|
||||
.concerning-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
:deep(.el-button) {
|
||||
padding: 0 10px;
|
||||
|
||||
i {
|
||||
font-size: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
> span:first-child {
|
||||
font-weight: bold;
|
||||
padding-right: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.email-title {
|
||||
font-weight: normal !important;
|
||||
display: flex;
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
div:first-child {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
grid-template-columns: 1fr auto;
|
||||
|
||||
span {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.el-button {
|
||||
.token-item {
|
||||
padding-top: 0;
|
||||
|
||||
div:last-child {
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
form .el-button {
|
||||
margin-top: 15px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.el-switch {
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
|
||||
:deep(.el-button--small) {
|
||||
margin-top: 2px !important;
|
||||
margin-bottom: 2px !important;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
:deep(.el-select__wrapper) {
|
||||
min-height: 28px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user