feat: add Space aggregate login
This commit is contained in:
@@ -20,3 +20,19 @@ export async function executeScheduleNow() {
|
||||
const { data } = await api.post('/schedule/execute', {})
|
||||
return data
|
||||
}
|
||||
|
||||
export async function fetchSocialLoginConfig() {
|
||||
const { data } = await api.get('/social-login/config')
|
||||
return data
|
||||
}
|
||||
|
||||
export async function updateSocialLoginConfig(payload) {
|
||||
const { data } = await api.post('/social-login/config', payload || {})
|
||||
systemConfigGetter.clear()
|
||||
return data
|
||||
}
|
||||
|
||||
export async function testSocialLoginConfig(payload) {
|
||||
const { data } = await api.post('/social-login/test', payload || {})
|
||||
return data
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
import { fetchSystemConfig, updateSystemConfig } from '../api/system'
|
||||
import { fetchSocialLoginConfig, fetchSystemConfig, testSocialLoginConfig, updateSocialLoginConfig, updateSystemConfig } from '../api/system'
|
||||
import { fetchKdocsQr, fetchKdocsStatus, clearKdocsLogin } from '../api/kdocs'
|
||||
import { fetchProxyConfig, testProxy, updateProxyConfig } from '../api/proxy'
|
||||
import { getCachedKdocsStatus, preloadKdocsStatus, updateCachedKdocsStatus } from '../utils/kdocsStatusCache'
|
||||
@@ -22,6 +22,21 @@ const autoApproveEnabled = ref(false)
|
||||
const autoApproveHourlyLimit = ref(10)
|
||||
const autoApproveVipDays = ref(7)
|
||||
|
||||
const socialLoginEnabled = ref(false)
|
||||
const socialLoginEndpoint = ref('https://www.spacezs.cn/connect.php')
|
||||
const socialLoginAppid = ref('')
|
||||
const socialLoginAppkey = ref('')
|
||||
const socialLoginAppkeyMasked = ref('')
|
||||
const socialLoginAppkeyConfigured = ref(false)
|
||||
const socialLoginProviders = ref(['wx'])
|
||||
const socialLoginSaving = ref(false)
|
||||
const socialLoginTesting = ref(false)
|
||||
const socialProviderOptions = [
|
||||
{ label: 'QQ', value: 'qq' },
|
||||
{ label: '微信', value: 'wx' },
|
||||
{ label: '支付宝', value: 'alipay' },
|
||||
]
|
||||
|
||||
const kdocsEnabled = ref(false)
|
||||
const kdocsDocUrl = ref('')
|
||||
const kdocsDefaultUnit = ref('')
|
||||
@@ -83,9 +98,10 @@ function setKdocsHint(message) {
|
||||
async function loadAll() {
|
||||
loading.value = true
|
||||
try {
|
||||
const [system, proxy] = await Promise.all([
|
||||
const [system, proxy, social] = await Promise.all([
|
||||
fetchSystemConfig(),
|
||||
fetchProxyConfig(),
|
||||
fetchSocialLoginConfig(),
|
||||
])
|
||||
|
||||
maxConcurrentGlobal.value = system.max_concurrent_global ?? 2
|
||||
@@ -112,6 +128,16 @@ async function loadAll() {
|
||||
kdocsRowEnd.value = system.kdocs_row_end ?? 0
|
||||
kdocsAdminNotifyEnabled.value = (system.kdocs_admin_notify_enabled ?? 0) === 1
|
||||
kdocsAdminNotifyEmail.value = system.kdocs_admin_notify_email || ''
|
||||
|
||||
socialLoginEnabled.value = (social.social_login_enabled ?? 0) === 1
|
||||
socialLoginEndpoint.value = social.social_login_endpoint || 'https://www.spacezs.cn/connect.php'
|
||||
socialLoginAppid.value = social.social_login_appid || ''
|
||||
socialLoginAppkey.value = ''
|
||||
socialLoginAppkeyMasked.value = social.social_login_appkey_masked || ''
|
||||
socialLoginAppkeyConfigured.value = Boolean(social.social_login_appkey_configured)
|
||||
socialLoginProviders.value = Array.isArray(social.social_login_providers) && social.social_login_providers.length
|
||||
? social.social_login_providers
|
||||
: ['wx']
|
||||
} catch {
|
||||
// handled by interceptor
|
||||
} finally {
|
||||
@@ -233,6 +259,78 @@ async function saveAutoApprove() {
|
||||
}
|
||||
}
|
||||
|
||||
function socialLoginPayload() {
|
||||
return {
|
||||
social_login_enabled: socialLoginEnabled.value ? 1 : 0,
|
||||
social_login_endpoint: socialLoginEndpoint.value.trim() || 'https://www.spacezs.cn/connect.php',
|
||||
social_login_appid: socialLoginAppid.value.trim(),
|
||||
social_login_appkey: socialLoginAppkey.value.trim(),
|
||||
social_login_providers: socialLoginProviders.value,
|
||||
}
|
||||
}
|
||||
|
||||
function validateSocialLoginForm() {
|
||||
if (!socialLoginEnabled.value) return true
|
||||
if (!socialLoginProviders.value.length) {
|
||||
ElMessage.error('请选择至少一种登录方式')
|
||||
return false
|
||||
}
|
||||
if (!socialLoginEndpoint.value.trim()) {
|
||||
ElMessage.error('请输入聚合接口地址')
|
||||
return false
|
||||
}
|
||||
if (!socialLoginAppid.value.trim()) {
|
||||
ElMessage.error('请输入 APPID')
|
||||
return false
|
||||
}
|
||||
if (!socialLoginAppkey.value.trim() && !socialLoginAppkeyConfigured.value) {
|
||||
ElMessage.error('请输入 APPKEY')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
async function saveSocialLogin() {
|
||||
if (!validateSocialLoginForm()) return
|
||||
socialLoginSaving.value = true
|
||||
try {
|
||||
const res = await updateSocialLoginConfig(socialLoginPayload())
|
||||
const cfg = res?.config || {}
|
||||
socialLoginAppkey.value = ''
|
||||
socialLoginAppkeyMasked.value = cfg.social_login_appkey_masked || socialLoginAppkeyMasked.value
|
||||
socialLoginAppkeyConfigured.value = Boolean(cfg.social_login_appkey_configured)
|
||||
ElMessage.success(res?.message || '聚合登录配置已保存')
|
||||
} catch {
|
||||
// handled by interceptor
|
||||
} finally {
|
||||
socialLoginSaving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function onTestSocialLogin() {
|
||||
if (!validateSocialLoginForm()) return
|
||||
socialLoginTesting.value = true
|
||||
try {
|
||||
const url = new URL(window.location.href)
|
||||
url.pathname = '/login'
|
||||
url.search = ''
|
||||
url.hash = ''
|
||||
const provider = socialLoginProviders.value[0] || 'wx'
|
||||
const res = await testSocialLoginConfig({
|
||||
...socialLoginPayload(),
|
||||
provider,
|
||||
redirect_uri: url.toString(),
|
||||
})
|
||||
await ElMessageBox.alert(res?.success ? '连接正常' : '测试完成', '聚合登录测试', {
|
||||
confirmButtonText: '知道了',
|
||||
})
|
||||
} catch {
|
||||
// handled by interceptor
|
||||
} finally {
|
||||
socialLoginTesting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function saveKdocsConfig() {
|
||||
const payload = {
|
||||
kdocs_enabled: kdocsEnabled.value ? 1 : 0,
|
||||
@@ -459,6 +557,43 @@ onMounted(loadAll)
|
||||
<el-button type="primary" @click="saveAutoApprove">保存注册设置</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card shadow="never" :body-style="{ padding: '16px' }" class="card section-card social-card">
|
||||
<h3 class="section-title">聚合登录</h3>
|
||||
<div class="section-sub app-muted">QQ、微信、支付宝快捷登录</div>
|
||||
|
||||
<el-form label-width="122px">
|
||||
<el-form-item label="启用">
|
||||
<el-switch v-model="socialLoginEnabled" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="登录方式">
|
||||
<el-checkbox-group v-model="socialLoginProviders">
|
||||
<el-checkbox v-for="item in socialProviderOptions" :key="item.value" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="接口地址">
|
||||
<el-input v-model="socialLoginEndpoint" placeholder="https://www.spacezs.cn/connect.php" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="APPID">
|
||||
<el-input v-model="socialLoginAppid" placeholder="Space APPID" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="APPKEY">
|
||||
<el-input v-model="socialLoginAppkey" type="password" show-password placeholder="留空则保持当前密钥" />
|
||||
<div v-if="socialLoginAppkeyConfigured" class="help">当前:{{ socialLoginAppkeyMasked }}</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="row-actions">
|
||||
<el-button type="primary" :loading="socialLoginSaving" @click="saveSocialLogin">保存聚合登录</el-button>
|
||||
<el-button :loading="socialLoginTesting" @click="onTestSocialLogin">测试连接</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<el-card shadow="never" :body-style="{ padding: '16px' }" class="card kdocs-card">
|
||||
@@ -743,6 +878,12 @@ onMounted(loadAll)
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1201px) {
|
||||
.social-card {
|
||||
grid-column: span 3;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.config-grid {
|
||||
grid-template-columns: 1fr;
|
||||
|
||||
Reference in New Issue
Block a user