mirror of
https://github.com/ZeroCatDev/Classworks.git
synced 2025-12-07 21:13:11 +00:00
feat: 添加设备认证对话框的预配置支持,优化自动认证逻辑
This commit is contained in:
parent
9aae9601f6
commit
7f166ffddc
@ -153,7 +153,9 @@
|
|||||||
max-width="500"
|
max-width="500"
|
||||||
>
|
>
|
||||||
<DeviceAuthDialog
|
<DeviceAuthDialog
|
||||||
|
ref="deviceAuthDialog"
|
||||||
:show-cancel="true"
|
:show-cancel="true"
|
||||||
|
:preconfig="deviceAuthPreconfig"
|
||||||
@success="handleAuthSuccess"
|
@success="handleAuthSuccess"
|
||||||
@cancel="showDeviceAuthDialog = false"
|
@cancel="showDeviceAuthDialog = false"
|
||||||
/>
|
/>
|
||||||
@ -184,13 +186,25 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, onMounted, watch } from 'vue'
|
||||||
import { getSetting, setSetting } from '@/utils/settings'
|
import { getSetting, setSetting } from '@/utils/settings'
|
||||||
import DeviceAuthDialog from './auth/DeviceAuthDialog.vue'
|
import DeviceAuthDialog from './auth/DeviceAuthDialog.vue'
|
||||||
import TokenInputDialog from './auth/TokenInputDialog.vue'
|
import TokenInputDialog from './auth/TokenInputDialog.vue'
|
||||||
import AlternativeCodeDialog from './auth/AlternativeCodeDialog.vue'
|
import AlternativeCodeDialog from './auth/AlternativeCodeDialog.vue'
|
||||||
import FirstTimeGuide from './auth/FirstTimeGuide.vue'
|
import FirstTimeGuide from './auth/FirstTimeGuide.vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
preconfig: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
namespace: null,
|
||||||
|
authCode: null,
|
||||||
|
autoOpen: false,
|
||||||
|
autoExecute: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['done'])
|
const emit = defineEmits(['done'])
|
||||||
|
|
||||||
// 控制显示:仅首页且无 kvToken(且 provider 不是 kv-local)显示
|
// 控制显示:仅首页且无 kvToken(且 provider 不是 kv-local)显示
|
||||||
@ -202,10 +216,25 @@ const showDeviceAuthDialog = ref(false)
|
|||||||
const showTokenDialog = ref(false)
|
const showTokenDialog = ref(false)
|
||||||
const showAlternativeCodeDialog = ref(false)
|
const showAlternativeCodeDialog = ref(false)
|
||||||
|
|
||||||
|
// 设备认证对话框引用
|
||||||
|
const deviceAuthDialog = ref(null)
|
||||||
|
|
||||||
const provider = computed(() => getSetting('server.provider'))
|
const provider = computed(() => getSetting('server.provider'))
|
||||||
const isKvProvider = computed(() => provider.value === 'kv-server' || provider.value === 'classworkscloud')
|
const isKvProvider = computed(() => provider.value === 'kv-server' || provider.value === 'classworkscloud')
|
||||||
const kvToken = computed(() => getSetting('server.kvToken'))
|
const kvToken = computed(() => getSetting('server.kvToken'))
|
||||||
|
|
||||||
|
// 设备认证预配置数据
|
||||||
|
const deviceAuthPreconfig = computed(() => {
|
||||||
|
if (props.preconfig?.namespace) {
|
||||||
|
return {
|
||||||
|
namespace: props.preconfig.namespace,
|
||||||
|
password: props.preconfig.authCode || '',
|
||||||
|
autoExecute: props.preconfig.autoExecute || false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
})
|
||||||
|
|
||||||
const evaluateVisibility = () => {
|
const evaluateVisibility = () => {
|
||||||
const path = window.location.pathname
|
const path = window.location.pathname
|
||||||
const onHome = path === '/' || path === '/index' || path === '/index.html'
|
const onHome = path === '/' || path === '/index' || path === '/index.html'
|
||||||
@ -213,6 +242,21 @@ const evaluateVisibility = () => {
|
|||||||
visible.value = onHome && need
|
visible.value = onHome && need
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 监听预配数据变化,自动打开设备认证对话框
|
||||||
|
watch(
|
||||||
|
() => props.preconfig,
|
||||||
|
(newPreconfig) => {
|
||||||
|
if (newPreconfig?.autoOpen && newPreconfig?.namespace && visible.value) {
|
||||||
|
console.log('检测到预配数据,自动打开设备认证对话框')
|
||||||
|
// 延迟一下确保组件已完全挂载
|
||||||
|
setTimeout(() => {
|
||||||
|
showDeviceAuthDialog.value = true
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
evaluateVisibility()
|
evaluateVisibility()
|
||||||
})
|
})
|
||||||
@ -231,8 +275,16 @@ const handleAutoAuthorize = () => {
|
|||||||
window.location.href = url
|
window.location.href = url
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleAuthSuccess = () => {
|
const handleAuthSuccess = (tokenData) => {
|
||||||
showDeviceAuthDialog.value = false
|
showDeviceAuthDialog.value = false
|
||||||
|
console.log('认证成功:', tokenData)
|
||||||
|
|
||||||
|
// 如果是通过预配数据成功的,显示成功消息
|
||||||
|
if (props.preconfig?.namespace) {
|
||||||
|
// 可以在这里添加成功提示
|
||||||
|
console.log(`预配数据认证成功: ${props.preconfig.namespace}`)
|
||||||
|
}
|
||||||
|
|
||||||
evaluateVisibility()
|
evaluateVisibility()
|
||||||
emit('done')
|
emit('done')
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,14 +100,18 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
import { getSetting, setSetting } from '@/utils/settings'
|
import { getSetting, setSetting } from '@/utils/settings'
|
||||||
import axios from '@/axios/axios'
|
import axios from '@/axios/axios'
|
||||||
|
|
||||||
defineProps({
|
const props = defineProps({
|
||||||
showCancel: {
|
showCancel: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
preconfig: {
|
||||||
|
type: Object,
|
||||||
|
default: null
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -120,6 +124,30 @@ const form = ref({
|
|||||||
const authenticating = ref(false)
|
const authenticating = ref(false)
|
||||||
const error = ref('')
|
const error = ref('')
|
||||||
|
|
||||||
|
// 监听预配置数据变化
|
||||||
|
watch(
|
||||||
|
() => props.preconfig,
|
||||||
|
(newPreconfig) => {
|
||||||
|
if (newPreconfig) {
|
||||||
|
console.log('应用预配置数据:', newPreconfig)
|
||||||
|
form.value.namespace = newPreconfig.namespace || ''
|
||||||
|
form.value.password = newPreconfig.password || ''
|
||||||
|
|
||||||
|
// 如果启用自动执行且有命名空间,自动尝试认证
|
||||||
|
if (newPreconfig.autoExecute && newPreconfig.namespace) {
|
||||||
|
console.log('检测到自动执行标志且有命名空间,自动执行认证')
|
||||||
|
// 延迟一下确保UI已更新
|
||||||
|
setTimeout(() => {
|
||||||
|
authenticate()
|
||||||
|
}, 300)
|
||||||
|
} else if (newPreconfig.namespace) {
|
||||||
|
console.log('预配置数据已填入,等待手动认证')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
const authenticate = async () => {
|
const authenticate = async () => {
|
||||||
if (!form.value.namespace || authenticating.value) return
|
if (!form.value.namespace || authenticating.value) return
|
||||||
error.value = ''
|
error.value = ''
|
||||||
|
|||||||
@ -43,7 +43,11 @@
|
|||||||
</template>
|
</template>
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
<!-- 初始化选择卡片,仅在首页且需要授权时显示;不影响顶栏 -->
|
<!-- 初始化选择卡片,仅在首页且需要授权时显示;不影响顶栏 -->
|
||||||
<init-service-chooser v-if="shouldShowInit" @done="settingsTick++" />
|
<init-service-chooser
|
||||||
|
v-if="shouldShowInit"
|
||||||
|
:preconfig="preconfigData"
|
||||||
|
@done="settingsTick++"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- 学生姓名管理组件 -->
|
<!-- 学生姓名管理组件 -->
|
||||||
<StudentNameManager
|
<StudentNameManager
|
||||||
@ -797,6 +801,13 @@ export default {
|
|||||||
$offKvChanged: null,
|
$offKvChanged: null,
|
||||||
$offConnect: null,
|
$offConnect: null,
|
||||||
debouncedRealtimeRefresh: null,
|
debouncedRealtimeRefresh: null,
|
||||||
|
// 预配数据
|
||||||
|
preconfigData: {
|
||||||
|
namespace: null,
|
||||||
|
authCode: null,
|
||||||
|
autoOpen: false,
|
||||||
|
autoExecute: false
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1203,6 +1214,9 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async initializeData() {
|
async initializeData() {
|
||||||
|
// 解析预配数据
|
||||||
|
this.parsePreconfigData();
|
||||||
|
|
||||||
const configApplied = await this.parseUrlConfig();
|
const configApplied = await this.parseUrlConfig();
|
||||||
|
|
||||||
const urlParams = new URLSearchParams(window.location.search);
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
@ -2232,6 +2246,64 @@ export default {
|
|||||||
currentDate.setDate(currentDate.getDate() + offset);
|
currentDate.setDate(currentDate.getDate() + offset);
|
||||||
this.handleDateSelect(currentDate);
|
this.handleDateSelect(currentDate);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 解析预配数据
|
||||||
|
parsePreconfigData() {
|
||||||
|
try {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const namespace = urlParams.get("namespace");
|
||||||
|
const authCode = urlParams.get("authCode") || urlParams.get("auth_code");
|
||||||
|
const autoExecute = urlParams.get("autoExecute") || urlParams.get("auto_execute");
|
||||||
|
|
||||||
|
if (namespace) {
|
||||||
|
this.preconfigData.namespace = namespace;
|
||||||
|
this.preconfigData.authCode = authCode;
|
||||||
|
this.preconfigData.autoOpen = true;
|
||||||
|
// 解析自动执行参数,支持 true/false、1/0、yes/no
|
||||||
|
this.preconfigData.autoExecute = this.parseBoolean(autoExecute);
|
||||||
|
|
||||||
|
console.log("检测到预配数据:", {
|
||||||
|
namespace: this.preconfigData.namespace,
|
||||||
|
hasAuthCode: !!this.preconfigData.authCode,
|
||||||
|
autoExecute: this.preconfigData.autoExecute
|
||||||
|
});
|
||||||
|
|
||||||
|
// 清理URL参数,避免重复处理
|
||||||
|
this.cleanupUrlParams(['namespace', 'authCode', 'auth_code', 'autoExecute', 'auto_execute']);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("解析预配数据失败:", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 解析布尔值参数
|
||||||
|
parseBoolean(value) {
|
||||||
|
if (!value) return false;
|
||||||
|
const lowerValue = value.toLowerCase();
|
||||||
|
return lowerValue === 'true' || lowerValue === '1' || lowerValue === 'yes';
|
||||||
|
},
|
||||||
|
|
||||||
|
// 清理URL参数
|
||||||
|
cleanupUrlParams(params) {
|
||||||
|
try {
|
||||||
|
const url = new URL(window.location);
|
||||||
|
let hasChanged = false;
|
||||||
|
|
||||||
|
params.forEach(param => {
|
||||||
|
if (url.searchParams.has(param)) {
|
||||||
|
url.searchParams.delete(param);
|
||||||
|
hasChanged = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (hasChanged) {
|
||||||
|
// 使用 replaceState 避免创建新的历史记录
|
||||||
|
window.history.replaceState({}, document.title, url.toString());
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("清理URL参数失败:", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user