feat: smooth report refresh and redesign system settings mobile UI

This commit is contained in:
2026-02-07 08:57:25 +08:00
parent 6eb0651e23
commit 121251a1f2
48 changed files with 388 additions and 391 deletions

View File

@@ -182,7 +182,7 @@ async function go(path) {
</el-main> </el-main>
</el-container> </el-container>
<el-drawer v-model="drawerOpen" size="240px" :with-header="false"> <el-drawer v-model="drawerOpen" size="min(82vw, 280px)" :with-header="false">
<div class="drawer-brand"> <div class="drawer-brand">
<div class="brand-title">后台管理</div> <div class="brand-title">后台管理</div>
<div class="brand-sub app-muted">知识管理平台</div> <div class="brand-sub app-muted">知识管理平台</div>
@@ -361,6 +361,10 @@ async function go(path) {
display: none; display: none;
} }
.admin-name strong {
display: none;
}
.layout-main { .layout-main {
padding: 12px; padding: 12px;
} }

View File

@@ -282,7 +282,7 @@ function manualRefresh() {
onMounted(() => { onMounted(() => {
refreshAll({ showLoading: false }) refreshAll({ showLoading: false })
refreshTimer = setInterval(() => refreshAll({ showLoading: false }), 1000) refreshTimer = setInterval(() => refreshAll({ showLoading: false }), 5000)
}) })
onUnmounted(() => { onUnmounted(() => {
@@ -343,14 +343,14 @@ onUnmounted(() => {
<div class="metrics-block"> <div class="metrics-block">
<div class="block-title">今日</div> <div class="block-title">今日</div>
<MetricGrid :items="taskTodayCards" :loading="refreshing" :min-width="120" /> <MetricGrid :items="taskTodayCards" :loading="loading" :min-width="120" />
</div> </div>
<div class="divider"></div> <div class="divider"></div>
<div class="metrics-block"> <div class="metrics-block">
<div class="block-title">累计</div> <div class="block-title">累计</div>
<MetricGrid :items="taskTotalCards" :loading="refreshing" :min-width="120" /> <MetricGrid :items="taskTotalCards" :loading="loading" :min-width="120" />
</div> </div>
</el-card> </el-card>
</el-col> </el-col>
@@ -456,13 +456,13 @@ onUnmounted(() => {
</div> </div>
</div> </div>
<MetricGrid :items="emailCards" :loading="refreshing" :min-width="132" /> <MetricGrid :items="emailCards" :loading="loading" :min-width="132" />
<div class="divider"></div> <div class="divider"></div>
<div class="metrics-block"> <div class="metrics-block">
<div class="block-title">类型统计</div> <div class="block-title">类型统计</div>
<MetricGrid :items="emailTypeCards" :loading="refreshing" :min-width="132" /> <MetricGrid :items="emailTypeCards" :loading="loading" :min-width="132" />
</div> </div>
</el-card> </el-card>
</el-col> </el-col>
@@ -481,7 +481,7 @@ onUnmounted(() => {
</div> </div>
</div> </div>
<MetricGrid :items="feedbackCards" :loading="refreshing" :min-width="145" /> <MetricGrid :items="feedbackCards" :loading="loading" :min-width="145" />
<div class="help app-muted">提示反馈处理越及时用户留存与满意度越高</div> <div class="help app-muted">提示反馈处理越及时用户留存与满意度越高</div>
</el-card> </el-card>
@@ -561,7 +561,7 @@ onUnmounted(() => {
<el-tag v-if="browserPoolStats?.server_time_cst" effect="light" type="info">{{ browserPoolStats.server_time_cst }}</el-tag> <el-tag v-if="browserPoolStats?.server_time_cst" effect="light" type="info">{{ browserPoolStats.server_time_cst }}</el-tag>
</div> </div>
<MetricGrid :items="browserPoolCards" :loading="refreshing" :min-width="120" /> <MetricGrid :items="browserPoolCards" :loading="loading" :min-width="120" />
<div class="divider"></div> <div class="divider"></div>

View File

@@ -2,35 +2,24 @@
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue' import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { fetchSystemConfig, updateSystemConfig, executeScheduleNow } from '../api/system' import { fetchSystemConfig, updateSystemConfig } from '../api/system'
import { fetchKdocsQr, fetchKdocsStatus, clearKdocsLogin } from '../api/kdocs' import { fetchKdocsQr, fetchKdocsStatus, clearKdocsLogin } from '../api/kdocs'
import { fetchProxyConfig, testProxy, updateProxyConfig } from '../api/proxy' import { fetchProxyConfig, testProxy, updateProxyConfig } from '../api/proxy'
const loading = ref(false) const loading = ref(false)
// 并发
const maxConcurrentGlobal = ref(2) const maxConcurrentGlobal = ref(2)
const maxConcurrentPerAccount = ref(1) const maxConcurrentPerAccount = ref(1)
const maxScreenshotConcurrent = ref(3) const maxScreenshotConcurrent = ref(3)
// 定时
const scheduleEnabled = ref(false)
const scheduleTime = ref('02:00')
const scheduleBrowseType = ref('应读')
const scheduleWeekdays = ref(['1', '2', '3', '4', '5', '6', '7'])
const scheduleScreenshotEnabled = ref(true)
// 代理
const proxyEnabled = ref(false) const proxyEnabled = ref(false)
const proxyApiUrl = ref('') const proxyApiUrl = ref('')
const proxyExpireMinutes = ref(3) const proxyExpireMinutes = ref(3)
// 自动审核
const autoApproveEnabled = ref(false) const autoApproveEnabled = ref(false)
const autoApproveHourlyLimit = ref(10) const autoApproveHourlyLimit = ref(10)
const autoApproveVipDays = ref(7) const autoApproveVipDays = ref(7)
// 金山文档上传
const kdocsEnabled = ref(false) const kdocsEnabled = ref(false)
const kdocsDocUrl = ref('') const kdocsDocUrl = ref('')
const kdocsDefaultUnit = ref('') const kdocsDefaultUnit = ref('')
@@ -42,6 +31,7 @@ const kdocsRowStart = ref(0)
const kdocsRowEnd = ref(0) const kdocsRowEnd = ref(0)
const kdocsAdminNotifyEnabled = ref(false) const kdocsAdminNotifyEnabled = ref(false)
const kdocsAdminNotifyEmail = ref('') const kdocsAdminNotifyEmail = ref('')
const kdocsStatus = ref({}) const kdocsStatus = ref({})
const kdocsQrOpen = ref(false) const kdocsQrOpen = ref(false)
const kdocsQrImage = ref('') const kdocsQrImage = ref('')
@@ -52,40 +42,10 @@ const kdocsClearLoading = ref(false)
const kdocsActionHint = ref('') const kdocsActionHint = ref('')
let kdocsPollingTimer = null let kdocsPollingTimer = null
const weekdaysOptions = [
{ label: '周一', value: '1' },
{ label: '周二', value: '2' },
{ label: '周三', value: '3' },
{ label: '周四', value: '4' },
{ label: '周五', value: '5' },
{ label: '周六', value: '6' },
{ label: '周日', value: '7' },
]
const weekdayNames = {
1: '周一',
2: '周二',
3: '周三',
4: '周四',
5: '周五',
6: '周六',
7: '周日',
}
const scheduleWeekdayDisplay = computed(() =>
(scheduleWeekdays.value || [])
.map((d) => weekdayNames[Number(d)] || d)
.join('、'),
)
const kdocsActionBusy = computed( const kdocsActionBusy = computed(
() => kdocsStatusLoading.value || kdocsQrLoading.value || kdocsClearLoading.value, () => kdocsStatusLoading.value || kdocsQrLoading.value || kdocsClearLoading.value,
) )
function normalizeBrowseType(value) {
if (String(value) === '注册前未读') return '注册前未读'
return '应读'
}
function setKdocsHint(message) { function setKdocsHint(message) {
if (!message) { if (!message) {
kdocsActionHint.value = '' kdocsActionHint.value = ''
@@ -108,17 +68,6 @@ async function loadAll() {
maxConcurrentPerAccount.value = system.max_concurrent_per_account ?? 1 maxConcurrentPerAccount.value = system.max_concurrent_per_account ?? 1
maxScreenshotConcurrent.value = system.max_screenshot_concurrent ?? 3 maxScreenshotConcurrent.value = system.max_screenshot_concurrent ?? 3
scheduleEnabled.value = (system.schedule_enabled ?? 0) === 1
scheduleTime.value = system.schedule_time || '02:00'
scheduleBrowseType.value = normalizeBrowseType(system.schedule_browse_type)
const weekdays = String(system.schedule_weekdays || '1,2,3,4,5,6,7')
.split(',')
.map((x) => x.trim())
.filter(Boolean)
scheduleWeekdays.value = weekdays.length ? weekdays : ['1', '2', '3', '4', '5', '6', '7']
scheduleScreenshotEnabled.value = (system.enable_screenshot ?? 1) === 1
autoApproveEnabled.value = (system.auto_approve_enabled ?? 0) === 1 autoApproveEnabled.value = (system.auto_approve_enabled ?? 0) === 1
autoApproveHourlyLimit.value = system.auto_approve_hourly_limit ?? 10 autoApproveHourlyLimit.value = system.auto_approve_hourly_limit ?? 10
autoApproveVipDays.value = system.auto_approve_vip_days ?? 7 autoApproveVipDays.value = system.auto_approve_vip_days ?? 7
@@ -171,63 +120,6 @@ async function saveConcurrency() {
} }
} }
async function saveSchedule() {
if (scheduleEnabled.value && (!scheduleWeekdays.value || scheduleWeekdays.value.length === 0)) {
ElMessage.error('请至少选择一个执行日期')
return
}
const payload = {
schedule_enabled: scheduleEnabled.value ? 1 : 0,
schedule_time: scheduleTime.value,
schedule_browse_type: scheduleBrowseType.value,
schedule_weekdays: (scheduleWeekdays.value || []).join(','),
enable_screenshot: scheduleScreenshotEnabled.value ? 1 : 0,
}
const screenshotText = scheduleScreenshotEnabled.value ? '截图' : '不截图'
const message = scheduleEnabled.value
? `确定启用定时任务吗?\n\n执行时间: 每天 ${payload.schedule_time}\n执行日期: ${scheduleWeekdayDisplay.value}\n浏览类型: ${payload.schedule_browse_type}\n截图: ${screenshotText}\n\n系统将自动执行所有账号的浏览任务`
: '确定关闭定时任务吗?'
try {
await ElMessageBox.confirm(message, '保存定时任务', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
try {
const res = await updateSystemConfig(payload)
ElMessage.success(res?.message || (scheduleEnabled.value ? '定时任务已启用' : '定时任务已关闭'))
} catch {
// handled by interceptor
}
}
async function runScheduleNow() {
const msg = `确定要立即执行定时任务吗?\n\n这将执行所有账号的浏览任务\n浏览类型: ${scheduleBrowseType.value}\n\n注意无视定时时间和执行日期配置立即开始执行`
try {
await ElMessageBox.confirm(msg, '立即执行', {
confirmButtonText: '立即执行',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
try {
const res = await executeScheduleNow()
ElMessage.success(res?.message || '定时任务已开始执行')
} catch {
// handled by interceptor
}
}
async function saveProxy() { async function saveProxy() {
if (proxyEnabled.value && !proxyApiUrl.value.trim()) { if (proxyEnabled.value && !proxyApiUrl.value.trim()) {
ElMessage.error('启用代理时API地址不能为空') ElMessage.error('启用代理时API地址不能为空')
@@ -248,6 +140,47 @@ async function saveProxy() {
} }
} }
async function onTestProxy() {
if (!proxyApiUrl.value.trim()) {
ElMessage.error('请先输入代理API地址')
return
}
try {
const res = await testProxy({ api_url: proxyApiUrl.value.trim() })
await ElMessageBox.alert(res?.message || '测试完成', '代理测试', { confirmButtonText: '知道了' })
} catch {
// handled by interceptor
}
}
async function saveAutoApprove() {
const hourly = Number(autoApproveHourlyLimit.value)
const vipDays = Number(autoApproveVipDays.value)
if (!Number.isFinite(hourly) || hourly < 1) {
ElMessage.error('每小时注册限制必须大于0')
return
}
if (!Number.isFinite(vipDays) || vipDays < 0) {
ElMessage.error('VIP天数不能为负数')
return
}
const payload = {
auto_approve_enabled: autoApproveEnabled.value ? 1 : 0,
auto_approve_hourly_limit: hourly,
auto_approve_vip_days: vipDays,
}
try {
const res = await updateSystemConfig(payload)
ElMessage.success(res?.message || '注册设置已保存')
} catch {
// handled by interceptor
}
}
async function saveKdocsConfig() { async function saveKdocsConfig() {
const payload = { const payload = {
kdocs_enabled: kdocsEnabled.value ? 1 : 0, kdocs_enabled: kdocsEnabled.value ? 1 : 0,
@@ -375,47 +308,6 @@ onBeforeUnmount(() => {
stopKdocsPolling() stopKdocsPolling()
}) })
async function onTestProxy() {
if (!proxyApiUrl.value.trim()) {
ElMessage.error('请先输入代理API地址')
return
}
try {
const res = await testProxy({ api_url: proxyApiUrl.value.trim() })
await ElMessageBox.alert(res?.message || '测试完成', '代理测试', { confirmButtonText: '知道了' })
} catch {
// handled by interceptor
}
}
async function saveAutoApprove() {
const hourly = Number(autoApproveHourlyLimit.value)
const vipDays = Number(autoApproveVipDays.value)
if (!Number.isFinite(hourly) || hourly < 1) {
ElMessage.error('每小时注册限制必须大于0')
return
}
if (!Number.isFinite(vipDays) || vipDays < 0) {
ElMessage.error('VIP天数不能为负数')
return
}
const payload = {
auto_approve_enabled: autoApproveEnabled.value ? 1 : 0,
auto_approve_hourly_limit: hourly,
auto_approve_vip_days: vipDays,
}
try {
const res = await updateSystemConfig(payload)
ElMessage.success(res?.message || '注册设置已保存')
} catch {
// handled by interceptor
}
}
onMounted(loadAll) onMounted(loadAll)
</script> </script>
@@ -423,124 +315,102 @@ onMounted(loadAll)
<div class="page-stack" v-loading="loading"> <div class="page-stack" v-loading="loading">
<div class="app-page-title"> <div class="app-page-title">
<h2>系统配置</h2> <h2>系统配置</h2>
<div> <div class="toolbar">
<el-button @click="loadAll">刷新</el-button> <el-button @click="loadAll">刷新</el-button>
</div> </div>
</div> </div>
<el-card shadow="never" :body-style="{ padding: '16px' }" class="card"> <div class="config-grid">
<h3 class="section-title">系统并发配置</h3> <el-card shadow="never" :body-style="{ padding: '16px' }" class="card section-card">
<h3 class="section-title">并发配置</h3>
<div class="section-sub app-muted">控制任务与截图的并发资源上限</div>
<el-form label-width="130px"> <el-form label-width="122px">
<el-form-item label="全局最大并发数"> <el-form-item label="全局最大并发数">
<el-input-number v-model="maxConcurrentGlobal" :min="1" :max="200" /> <el-input-number v-model="maxConcurrentGlobal" :min="1" :max="200" />
<div class="help">同时最多运行账号数浏览任务使用 API 方式资源占用较低</div> <div class="help">同时最多运行账号数浏览任务 API 执行资源占用较低</div>
</el-form-item> </el-form-item>
<el-form-item label="单账号最大并发数"> <el-form-item label="单账号最大并发数">
<el-input-number v-model="maxConcurrentPerAccount" :min="1" :max="50" /> <el-input-number v-model="maxConcurrentPerAccount" :min="1" :max="50" />
<div class="help">单个账号同时最多运行的任务数量建议设为 1</div> <div class="help">建议保持为 1避免同账号任务抢占</div>
</el-form-item> </el-form-item>
<el-form-item label="截图最大并发数"> <el-form-item label="截图最大并发数">
<el-input-number v-model="maxScreenshotConcurrent" :min="1" :max="50" /> <el-input-number v-model="maxScreenshotConcurrent" :min="1" :max="50" />
<div class="help">同时进行截图的最大数量wkhtmltoimage 资源占用较低可按需提高</div> <div class="help">截图资源占用较低可按机器性能逐步提高</div>
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-button type="primary" @click="saveConcurrency">保存并发配置</el-button> <div class="row-actions">
</el-card> <el-button type="primary" @click="saveConcurrency">保存并发配置</el-button>
</div>
</el-card>
<el-card shadow="never" :body-style="{ padding: '16px' }" class="card"> <el-card shadow="never" :body-style="{ padding: '16px' }" class="card section-card">
<h3 class="section-title">定时任务配</h3> <h3 class="section-title">代理设</h3>
<div class="section-sub app-muted">用于任务出网代理与连接有效期管理</div>
<el-form label-width="130px"> <el-form label-width="122px">
<el-form-item label="启用定时任务"> <el-form-item label="启用 IP 代理">
<el-switch v-model="scheduleEnabled" /> <el-switch v-model="proxyEnabled" />
<div class="help">开启后系统会按计划自动执行浏览任务</div> <div class="help">开启后浏览任务通过代理访问失败自动重试</div>
</el-form-item> </el-form-item>
<el-form-item v-if="scheduleEnabled" label="执行时间"> <el-form-item label="代理 API 地址">
<el-time-picker v-model="scheduleTime" value-format="HH:mm" format="HH:mm" /> <el-input v-model="proxyApiUrl" placeholder="http://api.xxx/Tools/IP.ashx?..." />
</el-form-item> <div class="help">API 应返回 `IP:PORT`123.45.67.89:8888</div>
</el-form-item>
<el-form-item v-if="scheduleEnabled" label="浏览类型"> <el-form-item label="有效期(分钟)">
<el-select v-model="scheduleBrowseType" style="width: 220px"> <el-input-number v-model="proxyExpireMinutes" :min="1" :max="60" />
<el-option label="注册前未读" value="注册前未读" /> </el-form-item>
<el-option label="应读" value="应读" /> </el-form>
</el-select>
</el-form-item>
<el-form-item v-if="scheduleEnabled" label="执行日期"> <div class="row-actions">
<el-checkbox-group v-model="scheduleWeekdays"> <el-button type="primary" @click="saveProxy">保存代理配置</el-button>
<el-checkbox v-for="w in weekdaysOptions" :key="w.value" :label="w.value"> <el-button @click="onTestProxy">测试代理</el-button>
{{ w.label }} </div>
</el-checkbox> </el-card>
</el-checkbox-group>
</el-form-item>
<el-form-item v-if="scheduleEnabled" label="定时任务截图"> <el-card shadow="never" :body-style="{ padding: '16px' }" class="card section-card">
<el-switch v-model="scheduleScreenshotEnabled" /> <h3 class="section-title">注册设置</h3>
<div class="help">开启后定时任务执行时会生成截图</div> <div class="section-sub app-muted">控制注册节流与新用户赠送 VIP</div>
</el-form-item>
</el-form>
<div class="row-actions"> <el-form label-width="122px">
<el-button type="primary" @click="saveSchedule">保存定时任务配置</el-button> <el-form-item label="注册赠送 VIP">
<el-button type="success" plain @click="runScheduleNow">立即执行</el-button> <el-switch v-model="autoApproveEnabled" />
<div class="help">开启后新用户注册成功自动赠送下方设定的 VIP 天数</div>
</el-form-item>
<el-form-item label="每小时注册限制">
<el-input-number v-model="autoApproveHourlyLimit" :min="1" :max="10000" />
</el-form-item>
<el-form-item label="赠送 VIP 天数">
<el-input-number v-model="autoApproveVipDays" :min="0" :max="999999" />
</el-form-item>
</el-form>
<div class="row-actions">
<el-button type="primary" @click="saveAutoApprove">保存注册设置</el-button>
</div>
</el-card>
</div>
<el-card shadow="never" :body-style="{ padding: '16px' }" class="card kdocs-card">
<div class="section-head">
<h3 class="section-title">金山文档上传</h3>
<div class="status-inline app-muted">
<span>登录状态</span>
<span v-if="kdocsStatus.last_login_ok === true">已登录</span>
<span v-else-if="kdocsStatus.login_required">需要扫码</span>
<span v-else>未知</span>
<span>· 待上传 {{ kdocsStatus.queue_size || 0 }}</span>
</div>
</div> </div>
</el-card>
<el-card shadow="never" :body-style="{ padding: '16px' }" class="card"> <el-form label-width="118px" class="kdocs-form">
<h3 class="section-title">代理设置</h3>
<el-form label-width="130px">
<el-form-item label="启用IP代理">
<el-switch v-model="proxyEnabled" />
<div class="help">开启后所有浏览任务将通过代理IP访问失败自动重试3次</div>
</el-form-item>
<el-form-item label="代理API地址">
<el-input v-model="proxyApiUrl" placeholder="http://api.xxx/Tools/IP.ashx?..." />
<div class="help">API 应返回IP:PORT例如 123.45.67.89:8888</div>
</el-form-item>
<el-form-item label="代理有效期(分钟)">
<el-input-number v-model="proxyExpireMinutes" :min="1" :max="60" />
</el-form-item>
</el-form>
<div class="row-actions">
<el-button type="primary" @click="saveProxy">保存代理配置</el-button>
<el-button @click="onTestProxy">测试代理</el-button>
</div>
</el-card>
<el-card shadow="never" :body-style="{ padding: '16px' }" class="card">
<h3 class="section-title">注册设置</h3>
<el-form label-width="130px">
<el-form-item label="注册赠送VIP">
<el-switch v-model="autoApproveEnabled" />
<div class="help">开启后新用户注册成功后将赠送下方设置的VIP天数注册已默认无需审核</div>
</el-form-item>
<el-form-item label="每小时注册限制">
<el-input-number v-model="autoApproveHourlyLimit" :min="1" :max="10000" />
</el-form-item>
<el-form-item label="注册赠送VIP天数">
<el-input-number v-model="autoApproveVipDays" :min="0" :max="999999" />
</el-form-item>
</el-form>
<el-button type="primary" @click="saveAutoApprove">保存注册设置</el-button>
</el-card>
<el-card shadow="never" :body-style="{ padding: '16px' }" class="card">
<h3 class="section-title">金山文档上传</h3>
<el-form label-width="130px">
<el-form-item label="启用上传"> <el-form-item label="启用上传">
<el-switch v-model="kdocsEnabled" /> <el-switch v-model="kdocsEnabled" />
<div class="help">表格结构变化时可先关闭避免错误上传</div> <div class="help">表格结构变化时可先关闭避免错误上传</div>
@@ -554,30 +424,29 @@ onMounted(loadAll)
<el-input v-model="kdocsDefaultUnit" placeholder="如:道县(用户可覆盖)" /> <el-input v-model="kdocsDefaultUnit" placeholder="如:道县(用户可覆盖)" />
</el-form-item> </el-form-item>
<el-form-item label="Sheet名称"> <el-form-item label="Sheet 名称">
<el-input v-model="kdocsSheetName" placeholder="留空使用第一个Sheet" /> <el-input v-model="kdocsSheetName" placeholder="留空使用第一个 Sheet" />
</el-form-item> </el-form-item>
<el-form-item label="Sheet序号"> <el-form-item label="Sheet 序号">
<el-input-number v-model="kdocsSheetIndex" :min="0" :max="50" /> <el-input-number v-model="kdocsSheetIndex" :min="0" :max="50" />
<div class="help">0 表示第一个Sheet</div> <div class="help">0 表示第一个 Sheet</div>
</el-form-item> </el-form-item>
<el-form-item label="县区列"> <el-form-item label="列配置">
<el-input v-model="kdocsUnitColumn" placeholder="A" style="max-width: 120px" /> <div class="kdocs-inline">
</el-form-item> <el-input v-model="kdocsUnitColumn" placeholder="县区列,如 A" />
<el-input v-model="kdocsImageColumn" placeholder="图片列,如 D" />
<el-form-item label="图片列"> </div>
<el-input v-model="kdocsImageColumn" placeholder="D" style="max-width: 120px" />
</el-form-item> </el-form-item>
<el-form-item label="有效行范围"> <el-form-item label="有效行范围">
<div style="display: flex; align-items: center; gap: 8px;"> <div class="kdocs-range">
<el-input-number v-model="kdocsRowStart" :min="0" :max="10000" placeholder="起始行" style="width: 120px" /> <el-input-number v-model="kdocsRowStart" :min="0" :max="10000" placeholder="起始行" style="width: 140px" />
<span></span> <span class="app-muted"></span>
<el-input-number v-model="kdocsRowEnd" :min="0" :max="10000" placeholder="结束行" style="width: 120px" /> <el-input-number v-model="kdocsRowEnd" :min="0" :max="10000" placeholder="结束行" style="width: 140px" />
</div> </div>
<div class="help">限制上传的行范围 50-1000 表示不限制用于防止重名导致误传到其他县区</div> <div class="help">用于限制上传区间 50-1000 表示不限制</div>
</el-form-item> </el-form-item>
<el-form-item label="管理员通知"> <el-form-item label="管理员通知">
@@ -618,14 +487,7 @@ onMounted(loadAll)
</el-button> </el-button>
</div> </div>
<div class="help"> <div v-if="kdocsStatus.last_error" class="help">最近错误{{ kdocsStatus.last_error }}</div>
登录状态
<span v-if="kdocsStatus.last_login_ok === true">已登录</span>
<span v-else-if="kdocsStatus.login_required">需要扫码</span>
<span v-else>未知</span>
· 待上传 {{ kdocsStatus.queue_size || 0 }}
<span v-if="kdocsStatus.last_error">· 最近错误{{ kdocsStatus.last_error }}</span>
</div>
<div v-if="kdocsActionHint" class="help">操作提示{{ kdocsActionHint }}</div> <div v-if="kdocsActionHint" class="help">操作提示{{ kdocsActionHint }}</div>
</el-card> </el-card>
@@ -646,6 +508,12 @@ onMounted(loadAll)
min-width: 0; min-width: 0;
} }
.config-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 14px;
}
.card { .card {
border-radius: var(--app-radius); border-radius: var(--app-radius);
border: 1px solid var(--app-border); border: 1px solid var(--app-border);
@@ -653,13 +521,54 @@ onMounted(loadAll)
box-shadow: var(--app-shadow-soft); box-shadow: var(--app-shadow-soft);
} }
.section-card {
min-width: 0;
}
.section-title { .section-title {
margin: 0 0 12px; margin: 0;
font-size: 15px; font-size: 15px;
font-weight: 800; font-weight: 800;
letter-spacing: 0.2px; letter-spacing: 0.2px;
} }
.section-sub {
margin-top: 6px;
margin-bottom: 10px;
font-size: 12px;
}
.section-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 10px;
}
.status-inline {
font-size: 12px;
}
.kdocs-form {
margin-top: 6px;
}
.kdocs-inline {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 10px;
width: 100%;
}
.kdocs-range {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.kdocs-qr { .kdocs-qr {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -687,4 +596,24 @@ onMounted(loadAll)
flex-wrap: wrap; flex-wrap: wrap;
gap: 10px; gap: 10px;
} }
@media (max-width: 1200px) {
.config-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 768px) {
.config-grid {
grid-template-columns: 1fr;
}
.kdocs-inline {
grid-template-columns: 1fr;
}
.kdocs-range {
align-items: stretch;
}
}
</style> </style>

View File

@@ -205,3 +205,65 @@ a {
justify-content: flex-start; justify-content: flex-start;
} }
} }
@media (max-width: 900px) {
.toolbar {
width: 100%;
}
.toolbar > * {
min-width: 0;
}
}
@media (max-width: 768px) {
.app-page-title > div {
width: 100%;
}
.app-page-title .toolbar {
width: 100%;
}
.toolbar > * {
flex: 1 1 calc(50% - 6px);
}
.toolbar .el-button,
.toolbar .el-select,
.toolbar .el-input,
.toolbar .el-input-number {
width: 100% !important;
}
.section-head {
align-items: flex-start;
}
.section-head > * {
width: 100%;
}
.table-wrap {
-webkit-overflow-scrolling: touch;
}
.table-wrap .el-table {
min-width: 700px;
}
.el-pagination {
width: 100%;
justify-content: flex-start;
}
}
@media (max-width: 520px) {
.toolbar > * {
flex-basis: 100%;
}
.table-wrap .el-table {
min-width: 620px;
}
}

View File

@@ -1,5 +1,5 @@
<script setup> <script setup>
import { computed, onMounted, reactive, ref } from 'vue' import { computed, onMounted, reactive, ref, watch } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
@@ -137,9 +137,7 @@ async function openForgot() {
forgotHint.value = '' forgotHint.value = ''
forgotForm.username = '' forgotForm.username = ''
forgotForm.captcha = '' forgotForm.captcha = ''
if (emailEnabled.value) { await refreshEmailResetCaptcha()
await refreshEmailResetCaptcha()
}
} }
async function submitForgot() { async function submitForgot() {
@@ -227,6 +225,18 @@ function goRegister() {
router.push('/register') router.push('/register')
} }
watch(forgotOpen, async (open) => {
if (open && !forgotCaptchaImage.value) {
await refreshEmailResetCaptcha()
}
})
watch(resendOpen, async (open) => {
if (open && !resendCaptchaImage.value) {
await refreshResendCaptcha()
}
})
onMounted(async () => { onMounted(async () => {
try { try {
const status = await fetchEmailVerifyStatus() const status = await fetchEmailVerifyStatus()
@@ -236,6 +246,10 @@ onMounted(async () => {
emailEnabled.value = false emailEnabled.value = false
registerVerifyEnabled.value = false registerVerifyEnabled.value = false
} }
if (emailEnabled.value) {
await Promise.allSettled([refreshEmailResetCaptcha(), refreshResendCaptcha()])
}
}) })
</script> </script>

View File

@@ -1,6 +1,6 @@
{ {
"_MetricGrid-W4bphIvI.js": { "_MetricGrid-D01YbVLF.js": {
"file": "assets/MetricGrid-W4bphIvI.js", "file": "assets/MetricGrid-D01YbVLF.js",
"name": "MetricGrid", "name": "MetricGrid",
"imports": [ "imports": [
"index.html" "index.html"
@@ -13,36 +13,36 @@
"file": "assets/MetricGrid-yP_dkP6X.css", "file": "assets/MetricGrid-yP_dkP6X.css",
"src": "_MetricGrid-yP_dkP6X.css" "src": "_MetricGrid-yP_dkP6X.css"
}, },
"_email-CgV08DvO.js": { "_email-BRC2BC3-.js": {
"file": "assets/email-CgV08DvO.js", "file": "assets/email-BRC2BC3-.js",
"name": "email", "name": "email",
"imports": [ "imports": [
"index.html" "index.html"
] ]
}, },
"_system-XwnAZq10.js": { "_system-DF5NjIEU.js": {
"file": "assets/system-XwnAZq10.js", "file": "assets/system-DF5NjIEU.js",
"name": "system", "name": "system",
"imports": [ "imports": [
"index.html" "index.html"
] ]
}, },
"_tasks-xgGctksM.js": { "_tasks-DznK6yjR.js": {
"file": "assets/tasks-xgGctksM.js", "file": "assets/tasks-DznK6yjR.js",
"name": "tasks", "name": "tasks",
"imports": [ "imports": [
"index.html" "index.html"
] ]
}, },
"_users-D07hXCyn.js": { "_users-D0z-1dZS.js": {
"file": "assets/users-D07hXCyn.js", "file": "assets/users-D0z-1dZS.js",
"name": "users", "name": "users",
"imports": [ "imports": [
"index.html" "index.html"
] ]
}, },
"index.html": { "index.html": {
"file": "assets/index-Bd3qzysl.js", "file": "assets/index-C92R8Skh.js",
"name": "index", "name": "index",
"src": "index.html", "src": "index.html",
"isEntry": true, "isEntry": true,
@@ -58,11 +58,11 @@
"src/pages/SettingsPage.vue" "src/pages/SettingsPage.vue"
], ],
"css": [ "css": [
"assets/index-Gi1T-zxa.css" "assets/index-BZpWUSSL.css"
] ]
}, },
"src/pages/AnnouncementsPage.vue": { "src/pages/AnnouncementsPage.vue": {
"file": "assets/AnnouncementsPage-C4Nx-yDs.js", "file": "assets/AnnouncementsPage-f4WCpDMp.js",
"name": "AnnouncementsPage", "name": "AnnouncementsPage",
"src": "src/pages/AnnouncementsPage.vue", "src": "src/pages/AnnouncementsPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
@@ -74,40 +74,40 @@
] ]
}, },
"src/pages/EmailPage.vue": { "src/pages/EmailPage.vue": {
"file": "assets/EmailPage-DV2FB_3E.js", "file": "assets/EmailPage-DNqsPKq9.js",
"name": "EmailPage", "name": "EmailPage",
"src": "src/pages/EmailPage.vue", "src": "src/pages/EmailPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"_email-CgV08DvO.js", "_email-BRC2BC3-.js",
"index.html", "index.html",
"_MetricGrid-W4bphIvI.js" "_MetricGrid-D01YbVLF.js"
], ],
"css": [ "css": [
"assets/EmailPage-BUCRqRf3.css" "assets/EmailPage-BUCRqRf3.css"
] ]
}, },
"src/pages/FeedbacksPage.vue": { "src/pages/FeedbacksPage.vue": {
"file": "assets/FeedbacksPage-CJdd3zlQ.js", "file": "assets/FeedbacksPage-YS4G_-sU.js",
"name": "FeedbacksPage", "name": "FeedbacksPage",
"src": "src/pages/FeedbacksPage.vue", "src": "src/pages/FeedbacksPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"index.html", "index.html",
"_MetricGrid-W4bphIvI.js" "_MetricGrid-D01YbVLF.js"
], ],
"css": [ "css": [
"assets/FeedbacksPage-OAEQDysw.css" "assets/FeedbacksPage-OAEQDysw.css"
] ]
}, },
"src/pages/LogsPage.vue": { "src/pages/LogsPage.vue": {
"file": "assets/LogsPage-CE03Ev2z.js", "file": "assets/LogsPage-znXDa_15.js",
"name": "LogsPage", "name": "LogsPage",
"src": "src/pages/LogsPage.vue", "src": "src/pages/LogsPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"_users-D07hXCyn.js", "_users-D0z-1dZS.js",
"_tasks-xgGctksM.js", "_tasks-DznK6yjR.js",
"index.html" "index.html"
], ],
"css": [ "css": [
@@ -115,36 +115,36 @@
] ]
}, },
"src/pages/ReportPage.vue": { "src/pages/ReportPage.vue": {
"file": "assets/ReportPage-BVWvJbtL.js", "file": "assets/ReportPage-FK_pGyNn.js",
"name": "ReportPage", "name": "ReportPage",
"src": "src/pages/ReportPage.vue", "src": "src/pages/ReportPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"index.html", "index.html",
"_email-CgV08DvO.js", "_email-BRC2BC3-.js",
"_tasks-xgGctksM.js", "_tasks-DznK6yjR.js",
"_system-XwnAZq10.js", "_system-DF5NjIEU.js",
"_MetricGrid-W4bphIvI.js" "_MetricGrid-D01YbVLF.js"
], ],
"css": [ "css": [
"assets/ReportPage-BFOQHLC4.css" "assets/ReportPage-BNnuA0U2.css"
] ]
}, },
"src/pages/SecurityPage.vue": { "src/pages/SecurityPage.vue": {
"file": "assets/SecurityPage-CwG-un_5.js", "file": "assets/SecurityPage-CDequYbX.js",
"name": "SecurityPage", "name": "SecurityPage",
"src": "src/pages/SecurityPage.vue", "src": "src/pages/SecurityPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"index.html", "index.html",
"_MetricGrid-W4bphIvI.js" "_MetricGrid-D01YbVLF.js"
], ],
"css": [ "css": [
"assets/SecurityPage-CQ0qfBKE.css" "assets/SecurityPage-CQ0qfBKE.css"
] ]
}, },
"src/pages/SettingsPage.vue": { "src/pages/SettingsPage.vue": {
"file": "assets/SettingsPage-D8X8xkDr.js", "file": "assets/SettingsPage-CPrFYKD9.js",
"name": "SettingsPage", "name": "SettingsPage",
"src": "src/pages/SettingsPage.vue", "src": "src/pages/SettingsPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
@@ -156,25 +156,25 @@
] ]
}, },
"src/pages/SystemPage.vue": { "src/pages/SystemPage.vue": {
"file": "assets/SystemPage-D-4toRBK.js", "file": "assets/SystemPage-x3i8nc17.js",
"name": "SystemPage", "name": "SystemPage",
"src": "src/pages/SystemPage.vue", "src": "src/pages/SystemPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"_system-XwnAZq10.js", "_system-DF5NjIEU.js",
"index.html" "index.html"
], ],
"css": [ "css": [
"assets/SystemPage-DY4Ehu3c.css" "assets/SystemPage-BoP0iqH5.css"
] ]
}, },
"src/pages/UsersPage.vue": { "src/pages/UsersPage.vue": {
"file": "assets/UsersPage-Cny_5hNj.js", "file": "assets/UsersPage-WcOe5gFJ.js",
"name": "UsersPage", "name": "UsersPage",
"src": "src/pages/UsersPage.vue", "src": "src/pages/UsersPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"_users-D07hXCyn.js", "_users-D0z-1dZS.js",
"index.html" "index.html"
], ],
"css": [ "css": [

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{_ as m,f as c,g as s,h as t,F as l,K as u,C as p,j as o,n as r,m as y,w as h,A as i,T as v,p as n,q as k,U as f}from"./index-Bd3qzysl.js";const b={class:"metric-top"},g={key:0,class:"metric-icon"},x={class:"metric-label"},C={class:"metric-value"},B={key:0,class:"metric-hint app-muted"},N={__name:"MetricGrid",props:{items:{type:Array,default:()=>[]},loading:{type:Boolean,default:!1},minWidth:{type:Number,default:180}},setup(a){return(V,w)=>{const d=c("el-icon"),_=c("el-skeleton");return t(),s("div",{class:"metric-grid",style:f({"--metric-min":`${a.minWidth}px`})},[(t(!0),s(l,null,u(a.items,e=>(t(),s("div",{key:e?.key||e?.label,class:p(["metric-card",`metric-tone--${e?.tone||"blue"}`])},[o("div",b,[e?.icon?(t(),s("div",g,[y(d,null,{default:h(()=>[(t(),i(v(e.icon)))]),_:2},1024)])):r("",!0),o("div",x,n(e?.label||"-"),1)]),o("div",C,[a.loading?(t(),i(_,{key:0,rows:1,animated:""})):(t(),s(l,{key:1},[k(n(e?.value??0),1)],64))]),e?.hint||e?.sub?(t(),s("div",B,n(e?.hint||e?.sub),1)):r("",!0)],2))),128))],4)}}},z=m(N,[["__scopeId","data-v-00e217d4"]]);export{z as M}; import{_ as m,f as c,g as s,h as t,F as l,K as u,C as p,j as o,n as r,m as y,w as h,A as i,T as v,p as n,q as k,U as f}from"./index-C92R8Skh.js";const b={class:"metric-top"},g={key:0,class:"metric-icon"},x={class:"metric-label"},C={class:"metric-value"},B={key:0,class:"metric-hint app-muted"},N={__name:"MetricGrid",props:{items:{type:Array,default:()=>[]},loading:{type:Boolean,default:!1},minWidth:{type:Number,default:180}},setup(a){return(V,w)=>{const d=c("el-icon"),_=c("el-skeleton");return t(),s("div",{class:"metric-grid",style:f({"--metric-min":`${a.minWidth}px`})},[(t(!0),s(l,null,u(a.items,e=>(t(),s("div",{key:e?.key||e?.label,class:p(["metric-card",`metric-tone--${e?.tone||"blue"}`])},[o("div",b,[e?.icon?(t(),s("div",g,[y(d,null,{default:h(()=>[(t(),i(v(e.icon)))]),_:2},1024)])):r("",!0),o("div",x,n(e?.label||"-"),1)]),o("div",C,[a.loading?(t(),i(_,{key:0,rows:1,animated:""})):(t(),s(l,{key:1},[k(n(e?.value??0),1)],64))]),e?.hint||e?.sub?(t(),s("div",B,n(e?.hint||e?.sub),1)):r("",!0)],2))),128))],4)}}},z=m(N,[["__scopeId","data-v-00e217d4"]]);export{z as M};

View File

@@ -1 +0,0 @@
.page-stack[data-v-f462fc0d]{display:flex;flex-direction:column;gap:14px}.report-hero[data-v-f462fc0d]{position:relative;overflow:hidden;border-radius:18px;border:1px solid rgba(17,24,39,.1);background:radial-gradient(circle at 10% 10%,rgba(59,130,246,.18),transparent 48%),radial-gradient(circle at 80% 0%,rgba(236,72,153,.16),transparent 45%),radial-gradient(circle at 90% 90%,rgba(16,185,129,.14),transparent 42%),#ffffffb8;box-shadow:0 14px 40px #0f172a14;-webkit-backdrop-filter:saturate(180%) blur(12px);backdrop-filter:saturate(180%) blur(12px);padding:16px}.hero-head[data-v-f462fc0d]{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:14px}.hero-main h2[data-v-f462fc0d]{margin:0;font-size:19px;font-weight:900;letter-spacing:.2px}.hero-meta[data-v-f462fc0d]{margin-top:6px;font-size:12px;display:flex;align-items:center;flex-wrap:wrap;gap:8px}.hero-dot[data-v-f462fc0d]{opacity:.65}.hero-actions[data-v-f462fc0d]{display:flex;gap:10px;align-items:center;flex-wrap:wrap}.panel[data-v-f462fc0d]{border-radius:18px;border:1px solid rgba(17,24,39,.1);background:#ffffffb8;box-shadow:var(--app-shadow);-webkit-backdrop-filter:saturate(180%) blur(10px);backdrop-filter:saturate(180%) blur(10px)}.panel-head[data-v-f462fc0d]{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:14px}.head-left[data-v-f462fc0d]{display:flex;align-items:center;gap:12px;min-width:0}.head-text[data-v-f462fc0d]{min-width:0}.head-icon[data-v-f462fc0d]{width:40px;height:40px;border-radius:16px;display:flex;align-items:center;justify-content:center;border:1px solid rgba(17,24,39,.08);flex:0 0 auto}.tone-blue[data-v-f462fc0d]{background:#3b82f61f;color:#1d4ed8}.tone-cyan[data-v-f462fc0d]{background:#22d3ee1f;color:#0369a1}.tone-purple[data-v-f462fc0d]{background:#8b5cf61f;color:#6d28d9}.tone-orange[data-v-f462fc0d]{background:#f59e0b1f;color:#b45309}.tone-green[data-v-f462fc0d]{background:#10b9811f;color:#047857}.tone-red[data-v-f462fc0d]{background:#ef44441f;color:#b91c1c}.panel-title[data-v-f462fc0d]{font-size:14px;font-weight:900}.panel-sub[data-v-f462fc0d]{margin-top:4px;font-size:12px;color:var(--app-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.metrics-block[data-v-f462fc0d]{display:flex;flex-direction:column;gap:10px}.block-title[data-v-f462fc0d]{font-size:13px;font-weight:900;letter-spacing:.2px}.divider[data-v-f462fc0d]{height:1px;background:linear-gradient(90deg,transparent,rgba(17,24,39,.12),transparent);margin:14px 0}.queue-tabs[data-v-f462fc0d] .el-tabs__header{margin:0 0 10px}.tab-label[data-v-f462fc0d]{display:inline-flex;align-items:center;gap:6px}.table-wrap[data-v-f462fc0d]{overflow-x:auto;border-radius:10px;border:1px solid var(--app-border);background:#fff}.help[data-v-f462fc0d]{margin-top:10px;font-size:12px}.resource-grid[data-v-f462fc0d]{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}.resource-item[data-v-f462fc0d]{border:1px solid rgba(17,24,39,.08);border-radius:16px;padding:12px;background:#ffffffb3}.resource-k[data-v-f462fc0d]{font-size:12px;margin-bottom:8px}.resource-sub[data-v-f462fc0d]{margin-top:8px;font-size:12px}.config-grid[data-v-f462fc0d]{display:grid;grid-template-columns:1fr;gap:10px}.config-item[data-v-f462fc0d]{border:1px solid rgba(17,24,39,.08);border-radius:16px;padding:12px;background:#ffffffb3}.config-k[data-v-f462fc0d]{font-size:12px}.config-v[data-v-f462fc0d]{margin-top:8px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}.config-inline[data-v-f462fc0d]{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.config-split[data-v-f462fc0d]{opacity:.65}.config-sub[data-v-f462fc0d]{margin-top:8px;font-size:12px}.err[data-v-f462fc0d]{color:#b91c1c}[data-v-f462fc0d] .el-table{--el-table-border-color: rgba(17, 24, 39, .08);--el-table-header-bg-color: rgba(246, 247, 251, .8)}[data-v-f462fc0d] .el-table th.el-table__cell{background:#f6f7fbcc}@media(max-width:768px){.resource-grid[data-v-f462fc0d]{grid-template-columns:1fr}}

View File

@@ -0,0 +1 @@
.page-stack[data-v-dc8671cb]{display:flex;flex-direction:column;gap:14px}.report-hero[data-v-dc8671cb]{position:relative;overflow:hidden;border-radius:18px;border:1px solid rgba(17,24,39,.1);background:radial-gradient(circle at 10% 10%,rgba(59,130,246,.18),transparent 48%),radial-gradient(circle at 80% 0%,rgba(236,72,153,.16),transparent 45%),radial-gradient(circle at 90% 90%,rgba(16,185,129,.14),transparent 42%),#ffffffb8;box-shadow:0 14px 40px #0f172a14;-webkit-backdrop-filter:saturate(180%) blur(12px);backdrop-filter:saturate(180%) blur(12px);padding:16px}.hero-head[data-v-dc8671cb]{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:14px}.hero-main h2[data-v-dc8671cb]{margin:0;font-size:19px;font-weight:900;letter-spacing:.2px}.hero-meta[data-v-dc8671cb]{margin-top:6px;font-size:12px;display:flex;align-items:center;flex-wrap:wrap;gap:8px}.hero-dot[data-v-dc8671cb]{opacity:.65}.hero-actions[data-v-dc8671cb]{display:flex;gap:10px;align-items:center;flex-wrap:wrap}.panel[data-v-dc8671cb]{border-radius:18px;border:1px solid rgba(17,24,39,.1);background:#ffffffb8;box-shadow:var(--app-shadow);-webkit-backdrop-filter:saturate(180%) blur(10px);backdrop-filter:saturate(180%) blur(10px)}.panel-head[data-v-dc8671cb]{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:14px}.head-left[data-v-dc8671cb]{display:flex;align-items:center;gap:12px;min-width:0}.head-text[data-v-dc8671cb]{min-width:0}.head-icon[data-v-dc8671cb]{width:40px;height:40px;border-radius:16px;display:flex;align-items:center;justify-content:center;border:1px solid rgba(17,24,39,.08);flex:0 0 auto}.tone-blue[data-v-dc8671cb]{background:#3b82f61f;color:#1d4ed8}.tone-cyan[data-v-dc8671cb]{background:#22d3ee1f;color:#0369a1}.tone-purple[data-v-dc8671cb]{background:#8b5cf61f;color:#6d28d9}.tone-orange[data-v-dc8671cb]{background:#f59e0b1f;color:#b45309}.tone-green[data-v-dc8671cb]{background:#10b9811f;color:#047857}.tone-red[data-v-dc8671cb]{background:#ef44441f;color:#b91c1c}.panel-title[data-v-dc8671cb]{font-size:14px;font-weight:900}.panel-sub[data-v-dc8671cb]{margin-top:4px;font-size:12px;color:var(--app-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.metrics-block[data-v-dc8671cb]{display:flex;flex-direction:column;gap:10px}.block-title[data-v-dc8671cb]{font-size:13px;font-weight:900;letter-spacing:.2px}.divider[data-v-dc8671cb]{height:1px;background:linear-gradient(90deg,transparent,rgba(17,24,39,.12),transparent);margin:14px 0}.queue-tabs[data-v-dc8671cb] .el-tabs__header{margin:0 0 10px}.tab-label[data-v-dc8671cb]{display:inline-flex;align-items:center;gap:6px}.table-wrap[data-v-dc8671cb]{overflow-x:auto;border-radius:10px;border:1px solid var(--app-border);background:#fff}.help[data-v-dc8671cb]{margin-top:10px;font-size:12px}.resource-grid[data-v-dc8671cb]{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}.resource-item[data-v-dc8671cb]{border:1px solid rgba(17,24,39,.08);border-radius:16px;padding:12px;background:#ffffffb3}.resource-k[data-v-dc8671cb]{font-size:12px;margin-bottom:8px}.resource-sub[data-v-dc8671cb]{margin-top:8px;font-size:12px}.config-grid[data-v-dc8671cb]{display:grid;grid-template-columns:1fr;gap:10px}.config-item[data-v-dc8671cb]{border:1px solid rgba(17,24,39,.08);border-radius:16px;padding:12px;background:#ffffffb3}.config-k[data-v-dc8671cb]{font-size:12px}.config-v[data-v-dc8671cb]{margin-top:8px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}.config-inline[data-v-dc8671cb]{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.config-split[data-v-dc8671cb]{opacity:.65}.config-sub[data-v-dc8671cb]{margin-top:8px;font-size:12px}.err[data-v-dc8671cb]{color:#b91c1c}[data-v-dc8671cb] .el-table{--el-table-border-color: rgba(17, 24, 39, .08);--el-table-header-bg-color: rgba(246, 247, 251, .8)}[data-v-dc8671cb] .el-table th.el-table__cell{background:#f6f7fbcc}@media(max-width:768px){.resource-grid[data-v-dc8671cb]{grid-template-columns:1fr}}

View File

@@ -1 +1 @@
import{a as m,_ as B,r as p,f as u,g as T,h as P,j as r,m as a,w as l,q as x,J as i,I as b}from"./index-Bd3qzysl.js";async function C(o){const{data:s}=await m.put("/admin/username",{new_username:o});return s}async function S(o){const{data:s}=await m.put("/admin/password",{new_password:o});return s}async function U(){const{data:o}=await m.post("/logout");return o}const A={class:"page-stack"},E={__name:"SettingsPage",setup(o){const s=p(""),d=p(""),n=p(!1);function k(t){const e=String(t||"");return e.length<8?{ok:!1,message:"密码长度至少8位"}:e.length>128?{ok:!1,message:"密码长度不能超过128个字符"}:!/[a-zA-Z]/.test(e)||!/\d/.test(e)?{ok:!1,message:"密码必须包含字母和数字"}:{ok:!0,message:""}}async function f(){try{await U()}catch{}finally{window.location.href="/yuyx"}}async function V(){const t=s.value.trim();if(!t){i.error("请输入新用户名");return}try{await b.confirm(`确定将管理员用户名修改为「${t}」吗?修改后需要重新登录。`,"修改用户名",{confirmButtonText:"确认修改",cancelButtonText:"取消",type:"warning"})}catch{return}n.value=!0;try{await C(t),i.success("用户名修改成功,请重新登录"),s.value="",setTimeout(f,1200)}catch{}finally{n.value=!1}}async function h(){const t=d.value;if(!t){i.error("请输入新密码");return}const e=k(t);if(!e.ok){i.error(e.message);return}try{await b.confirm("确定修改管理员密码吗?修改后需要重新登录。","修改密码",{confirmButtonText:"确认修改",cancelButtonText:"取消",type:"warning"})}catch{return}n.value=!0;try{await S(t),i.success("密码修改成功,请重新登录"),d.value="",setTimeout(f,1200)}catch{}finally{n.value=!1}}return(t,e)=>{const g=u("el-input"),w=u("el-form-item"),v=u("el-form"),y=u("el-button"),_=u("el-card");return P(),T("div",A,[e[7]||(e[7]=r("div",{class:"app-page-title"},[r("h2",null,"设置"),r("span",{class:"app-muted"},"管理员账号设置")],-1)),a(_,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:l(()=>[e[3]||(e[3]=r("h3",{class:"section-title"},"修改管理员用户名",-1)),a(v,{"label-width":"120px"},{default:l(()=>[a(w,{label:"新用户名"},{default:l(()=>[a(g,{modelValue:s.value,"onUpdate:modelValue":e[0]||(e[0]=c=>s.value=c),placeholder:"输入新用户名",disabled:n.value},null,8,["modelValue","disabled"])]),_:1})]),_:1}),a(y,{type:"primary",loading:n.value,onClick:V},{default:l(()=>[...e[2]||(e[2]=[x("保存用户名",-1)])]),_:1},8,["loading"])]),_:1}),a(_,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:l(()=>[e[5]||(e[5]=r("h3",{class:"section-title"},"修改管理员密码",-1)),a(v,{"label-width":"120px"},{default:l(()=>[a(w,{label:"新密码"},{default:l(()=>[a(g,{modelValue:d.value,"onUpdate:modelValue":e[1]||(e[1]=c=>d.value=c),type:"password","show-password":"",placeholder:"输入新密码",disabled:n.value},null,8,["modelValue","disabled"])]),_:1})]),_:1}),a(y,{type:"primary",loading:n.value,onClick:h},{default:l(()=>[...e[4]||(e[4]=[x("保存密码",-1)])]),_:1},8,["loading"]),e[6]||(e[6]=r("div",{class:"help"},"建议使用更强密码至少8位且包含字母与数字。",-1))]),_:1})])}}},I=B(E,[["__scopeId","data-v-83d3840a"]]);export{I as default}; import{a as m,_ as B,r as p,f as u,g as T,h as P,j as r,m as a,w as l,q as x,J as i,I as b}from"./index-C92R8Skh.js";async function C(o){const{data:s}=await m.put("/admin/username",{new_username:o});return s}async function S(o){const{data:s}=await m.put("/admin/password",{new_password:o});return s}async function U(){const{data:o}=await m.post("/logout");return o}const A={class:"page-stack"},E={__name:"SettingsPage",setup(o){const s=p(""),d=p(""),n=p(!1);function k(t){const e=String(t||"");return e.length<8?{ok:!1,message:"密码长度至少8位"}:e.length>128?{ok:!1,message:"密码长度不能超过128个字符"}:!/[a-zA-Z]/.test(e)||!/\d/.test(e)?{ok:!1,message:"密码必须包含字母和数字"}:{ok:!0,message:""}}async function f(){try{await U()}catch{}finally{window.location.href="/yuyx"}}async function V(){const t=s.value.trim();if(!t){i.error("请输入新用户名");return}try{await b.confirm(`确定将管理员用户名修改为「${t}」吗?修改后需要重新登录。`,"修改用户名",{confirmButtonText:"确认修改",cancelButtonText:"取消",type:"warning"})}catch{return}n.value=!0;try{await C(t),i.success("用户名修改成功,请重新登录"),s.value="",setTimeout(f,1200)}catch{}finally{n.value=!1}}async function h(){const t=d.value;if(!t){i.error("请输入新密码");return}const e=k(t);if(!e.ok){i.error(e.message);return}try{await b.confirm("确定修改管理员密码吗?修改后需要重新登录。","修改密码",{confirmButtonText:"确认修改",cancelButtonText:"取消",type:"warning"})}catch{return}n.value=!0;try{await S(t),i.success("密码修改成功,请重新登录"),d.value="",setTimeout(f,1200)}catch{}finally{n.value=!1}}return(t,e)=>{const g=u("el-input"),w=u("el-form-item"),v=u("el-form"),y=u("el-button"),_=u("el-card");return P(),T("div",A,[e[7]||(e[7]=r("div",{class:"app-page-title"},[r("h2",null,"设置"),r("span",{class:"app-muted"},"管理员账号设置")],-1)),a(_,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:l(()=>[e[3]||(e[3]=r("h3",{class:"section-title"},"修改管理员用户名",-1)),a(v,{"label-width":"120px"},{default:l(()=>[a(w,{label:"新用户名"},{default:l(()=>[a(g,{modelValue:s.value,"onUpdate:modelValue":e[0]||(e[0]=c=>s.value=c),placeholder:"输入新用户名",disabled:n.value},null,8,["modelValue","disabled"])]),_:1})]),_:1}),a(y,{type:"primary",loading:n.value,onClick:V},{default:l(()=>[...e[2]||(e[2]=[x("保存用户名",-1)])]),_:1},8,["loading"])]),_:1}),a(_,{shadow:"never","body-style":{padding:"16px"},class:"card"},{default:l(()=>[e[5]||(e[5]=r("h3",{class:"section-title"},"修改管理员密码",-1)),a(v,{"label-width":"120px"},{default:l(()=>[a(w,{label:"新密码"},{default:l(()=>[a(g,{modelValue:d.value,"onUpdate:modelValue":e[1]||(e[1]=c=>d.value=c),type:"password","show-password":"",placeholder:"输入新密码",disabled:n.value},null,8,["modelValue","disabled"])]),_:1})]),_:1}),a(y,{type:"primary",loading:n.value,onClick:h},{default:l(()=>[...e[4]||(e[4]=[x("保存密码",-1)])]),_:1},8,["loading"]),e[6]||(e[6]=r("div",{class:"help"},"建议使用更强密码至少8位且包含字母与数字。",-1))]),_:1})])}}},I=B(E,[["__scopeId","data-v-83d3840a"]]);export{I as default};

View File

@@ -0,0 +1 @@
.page-stack[data-v-8509cc24]{display:flex;flex-direction:column;gap:14px;min-width:0}.config-grid[data-v-8509cc24]{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:14px}.card[data-v-8509cc24]{border-radius:var(--app-radius);border:1px solid var(--app-border);background:var(--app-card-bg);box-shadow:var(--app-shadow-soft)}.section-card[data-v-8509cc24]{min-width:0}.section-title[data-v-8509cc24]{margin:0;font-size:15px;font-weight:800;letter-spacing:.2px}.section-sub[data-v-8509cc24]{margin-top:6px;margin-bottom:10px;font-size:12px}.section-head[data-v-8509cc24]{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:10px}.status-inline[data-v-8509cc24]{font-size:12px}.kdocs-form[data-v-8509cc24]{margin-top:6px}.kdocs-inline[data-v-8509cc24]{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;width:100%}.kdocs-range[data-v-8509cc24]{display:flex;align-items:center;gap:8px;flex-wrap:wrap}.kdocs-qr[data-v-8509cc24]{display:flex;flex-direction:column;align-items:center;gap:12px}.kdocs-qr img[data-v-8509cc24]{width:260px;max-width:100%;border:1px solid var(--app-border);border-radius:8px;padding:8px;background:#fff}.help[data-v-8509cc24]{margin-top:6px;font-size:12px;color:var(--app-muted)}.row-actions[data-v-8509cc24]{display:flex;flex-wrap:wrap;gap:10px}@media(max-width:1200px){.config-grid[data-v-8509cc24]{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:768px){.config-grid[data-v-8509cc24],.kdocs-inline[data-v-8509cc24]{grid-template-columns:1fr}.kdocs-range[data-v-8509cc24]{align-items:stretch}}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
.page-stack[data-v-f6db7ea6]{display:flex;flex-direction:column;gap:14px;min-width:0}.card[data-v-f6db7ea6]{border-radius:var(--app-radius);border:1px solid var(--app-border);background:var(--app-card-bg);box-shadow:var(--app-shadow-soft)}.section-title[data-v-f6db7ea6]{margin:0 0 12px;font-size:15px;font-weight:800;letter-spacing:.2px}.kdocs-qr[data-v-f6db7ea6]{display:flex;flex-direction:column;align-items:center;gap:12px}.kdocs-qr img[data-v-f6db7ea6]{width:260px;max-width:100%;border:1px solid var(--app-border);border-radius:8px;padding:8px;background:#fff}.help[data-v-f6db7ea6]{margin-top:6px;font-size:12px;color:var(--app-muted)}.row-actions[data-v-f6db7ea6]{display:flex;flex-wrap:wrap;gap:10px}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{a as n}from"./index-Bd3qzysl.js";async function i(){const{data:a}=await n.get("/email/settings");return a}async function e(a){const{data:t}=await n.post("/email/settings",a);return t}async function c(){const{data:a}=await n.get("/email/stats");return a}async function o(a){const{data:t}=await n.get("/email/logs",{params:a});return t}async function l(a){const{data:t}=await n.post("/email/logs/cleanup",{days:a});return t}export{o as a,i as b,l as c,c as f,e as u}; import{a as n}from"./index-C92R8Skh.js";async function i(){const{data:a}=await n.get("/email/settings");return a}async function e(a){const{data:t}=await n.post("/email/settings",a);return t}async function c(){const{data:a}=await n.get("/email/stats");return a}async function o(a){const{data:t}=await n.get("/email/logs",{params:a});return t}async function l(a){const{data:t}=await n.post("/email/logs/cleanup",{days:a});return t}export{o as a,i as b,l as c,c as f,e as u};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
import{a}from"./index-C92R8Skh.js";async function o(){const{data:t}=await a.get("/system/config");return t}async function e(t){const{data:n}=await a.post("/system/config",t);return n}export{o as f,e as u};

View File

@@ -1 +0,0 @@
import{a}from"./index-Bd3qzysl.js";async function s(){const{data:t}=await a.get("/system/config");return t}async function c(t){const{data:e}=await a.post("/system/config",t);return e}async function o(){const{data:t}=await a.post("/schedule/execute",{});return t}export{o as e,s as f,c as u};

View File

@@ -1 +1 @@
import{a}from"./index-Bd3qzysl.js";async function c(){const{data:t}=await a.get("/server/info");return t}async function e(){const{data:t}=await a.get("/docker_stats");return t}async function o(){const{data:t}=await a.get("/task/stats");return t}async function r(){const{data:t}=await a.get("/task/running");return t}async function i(t){const{data:s}=await a.get("/task/logs",{params:t});return s}async function f(t){const{data:s}=await a.post("/task/logs/clear",{days:t});return s}export{r as a,c as b,e as c,i as d,f as e,o as f}; import{a}from"./index-C92R8Skh.js";async function c(){const{data:t}=await a.get("/server/info");return t}async function e(){const{data:t}=await a.get("/docker_stats");return t}async function o(){const{data:t}=await a.get("/task/stats");return t}async function r(){const{data:t}=await a.get("/task/running");return t}async function i(t){const{data:s}=await a.get("/task/logs",{params:t});return s}async function f(t){const{data:s}=await a.post("/task/logs/clear",{days:t});return s}export{r as a,c as b,e as c,i as d,f as e,o as f};

View File

@@ -1 +1 @@
import{a as t}from"./index-Bd3qzysl.js";async function n(){const{data:s}=await t.get("/users");return s}async function o(s){const{data:a}=await t.post(`/users/${s}/approve`);return a}async function c(s){const{data:a}=await t.post(`/users/${s}/reject`);return a}async function i(s){const{data:a}=await t.delete(`/users/${s}`);return a}async function u(s,a){const{data:e}=await t.post(`/users/${s}/vip`,{days:a});return e}async function p(s){const{data:a}=await t.delete(`/users/${s}/vip`);return a}async function d(s,a){const{data:e}=await t.post(`/users/${s}/reset_password`,{new_password:a});return e}export{o as a,p as b,d as c,i as d,n as f,c as r,u as s}; import{a as t}from"./index-C92R8Skh.js";async function n(){const{data:s}=await t.get("/users");return s}async function o(s){const{data:a}=await t.post(`/users/${s}/approve`);return a}async function c(s){const{data:a}=await t.post(`/users/${s}/reject`);return a}async function i(s){const{data:a}=await t.delete(`/users/${s}`);return a}async function u(s,a){const{data:e}=await t.post(`/users/${s}/vip`,{days:a});return e}async function p(s){const{data:a}=await t.delete(`/users/${s}/vip`);return a}async function d(s,a){const{data:e}=await t.post(`/users/${s}/reset_password`,{new_password:a});return e}export{o as a,p as b,d as c,i as d,n as f,c as r,u as s};

View File

@@ -5,8 +5,8 @@
<link rel="icon" type="image/svg+xml" href="./vite.svg" /> <link rel="icon" type="image/svg+xml" href="./vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>后台管理 - 知识管理平台</title> <title>后台管理 - 知识管理平台</title>
<script type="module" crossorigin src="./assets/index-Bd3qzysl.js"></script> <script type="module" crossorigin src="./assets/index-C92R8Skh.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-Gi1T-zxa.css"> <link rel="stylesheet" crossorigin href="./assets/index-BZpWUSSL.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

View File

@@ -1,20 +1,20 @@
{ {
"_accounts-DMWldvrc.js": { "_accounts-PyhRkiaU.js": {
"file": "assets/accounts-DMWldvrc.js", "file": "assets/accounts-PyhRkiaU.js",
"name": "accounts", "name": "accounts",
"imports": [ "imports": [
"index.html" "index.html"
] ]
}, },
"_auth-RsjJ-Dgh.js": { "_auth-BA1ZmOLU.js": {
"file": "assets/auth-RsjJ-Dgh.js", "file": "assets/auth-BA1ZmOLU.js",
"name": "auth", "name": "auth",
"imports": [ "imports": [
"index.html" "index.html"
] ]
}, },
"index.html": { "index.html": {
"file": "assets/index-D1OuoXoU.js", "file": "assets/index-BUFlUzjg.js",
"name": "index", "name": "index",
"src": "index.html", "src": "index.html",
"isEntry": true, "isEntry": true,
@@ -32,12 +32,12 @@
] ]
}, },
"src/pages/AccountsPage.vue": { "src/pages/AccountsPage.vue": {
"file": "assets/AccountsPage-BaKp9Hif.js", "file": "assets/AccountsPage-BAh10EUB.js",
"name": "AccountsPage", "name": "AccountsPage",
"src": "src/pages/AccountsPage.vue", "src": "src/pages/AccountsPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"_accounts-DMWldvrc.js", "_accounts-PyhRkiaU.js",
"index.html" "index.html"
], ],
"css": [ "css": [
@@ -45,51 +45,51 @@
] ]
}, },
"src/pages/LoginPage.vue": { "src/pages/LoginPage.vue": {
"file": "assets/LoginPage-BVBKu4Tf.js", "file": "assets/LoginPage-QA1ky-IE.js",
"name": "LoginPage", "name": "LoginPage",
"src": "src/pages/LoginPage.vue", "src": "src/pages/LoginPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"index.html", "index.html",
"_auth-RsjJ-Dgh.js" "_auth-BA1ZmOLU.js"
], ],
"css": [ "css": [
"assets/LoginPage-m2uYyAaW.css" "assets/LoginPage-DKpbim43.css"
] ]
}, },
"src/pages/RegisterPage.vue": { "src/pages/RegisterPage.vue": {
"file": "assets/RegisterPage-D74ftG7F.js", "file": "assets/RegisterPage-BFItDu20.js",
"name": "RegisterPage", "name": "RegisterPage",
"src": "src/pages/RegisterPage.vue", "src": "src/pages/RegisterPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"index.html", "index.html",
"_auth-RsjJ-Dgh.js" "_auth-BA1ZmOLU.js"
], ],
"css": [ "css": [
"assets/RegisterPage-BOcNcW5D.css" "assets/RegisterPage-BOcNcW5D.css"
] ]
}, },
"src/pages/ResetPasswordPage.vue": { "src/pages/ResetPasswordPage.vue": {
"file": "assets/ResetPasswordPage-DlzgcuUb.js", "file": "assets/ResetPasswordPage-DLGrCh2_.js",
"name": "ResetPasswordPage", "name": "ResetPasswordPage",
"src": "src/pages/ResetPasswordPage.vue", "src": "src/pages/ResetPasswordPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"index.html", "index.html",
"_auth-RsjJ-Dgh.js" "_auth-BA1ZmOLU.js"
], ],
"css": [ "css": [
"assets/ResetPasswordPage-DybfLMAw.css" "assets/ResetPasswordPage-DybfLMAw.css"
] ]
}, },
"src/pages/SchedulesPage.vue": { "src/pages/SchedulesPage.vue": {
"file": "assets/SchedulesPage-CgezmtHQ.js", "file": "assets/SchedulesPage-BAqo6799.js",
"name": "SchedulesPage", "name": "SchedulesPage",
"src": "src/pages/SchedulesPage.vue", "src": "src/pages/SchedulesPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
"imports": [ "imports": [
"_accounts-DMWldvrc.js", "_accounts-PyhRkiaU.js",
"index.html" "index.html"
], ],
"css": [ "css": [
@@ -97,7 +97,7 @@
] ]
}, },
"src/pages/ScreenshotsPage.vue": { "src/pages/ScreenshotsPage.vue": {
"file": "assets/ScreenshotsPage-CQ27mEKf.js", "file": "assets/ScreenshotsPage-DFhvzfGf.js",
"name": "ScreenshotsPage", "name": "ScreenshotsPage",
"src": "src/pages/ScreenshotsPage.vue", "src": "src/pages/ScreenshotsPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,
@@ -109,7 +109,7 @@
] ]
}, },
"src/pages/VerifyResultPage.vue": { "src/pages/VerifyResultPage.vue": {
"file": "assets/VerifyResultPage-CfKXGuTu.js", "file": "assets/VerifyResultPage-BY1IwZVO.js",
"name": "VerifyResultPage", "name": "VerifyResultPage",
"src": "src/pages/VerifyResultPage.vue", "src": "src/pages/VerifyResultPage.vue",
"isDynamicEntry": true, "isDynamicEntry": true,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
.login-page[data-v-dc51a501]{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px;position:relative;background:linear-gradient(135deg,#eef2ff,#f6f7fb 45%,#ecfeff)}.login-page[data-v-dc51a501]:before{content:"";position:fixed;inset:0;background:radial-gradient(800px 500px at 15% 20%,rgba(59,130,246,.18),transparent 60%),radial-gradient(700px 420px at 85% 70%,rgba(124,58,237,.16),transparent 55%);pointer-events:none}.login-container[data-v-dc51a501]{width:100%;max-width:420px;background:#fff;border-radius:16px;box-shadow:0 18px 60px #11182726;border:1px solid rgba(17,24,39,.08);padding:38px 34px;position:relative;z-index:1}.login-header[data-v-dc51a501]{text-align:center;margin-bottom:28px}.login-badge[data-v-dc51a501]{display:inline-block;background:#3b82f61a;color:#1d4ed8;padding:6px 14px;border-radius:999px;font-size:12px;font-weight:700;margin-bottom:14px}.login-header h1[data-v-dc51a501]{font-size:24px;color:#111827;margin:0 0 10px;letter-spacing:.2px}.login-header p[data-v-dc51a501]{margin:0;color:#6b7280;font-size:14px}.form-group[data-v-dc51a501]{margin-bottom:20px}.form-group label[data-v-dc51a501]{display:block;margin-bottom:8px;color:#111827;font-weight:700;font-size:13px}.login-input[data-v-dc51a501] .el-input__wrapper{border-radius:10px;min-height:44px;background:#ffffffe6;box-shadow:0 0 0 1px #11182724 inset;transition:box-shadow .2s}.login-input[data-v-dc51a501] .el-input__wrapper.is-focus{box-shadow:0 0 0 1px #3b82f6b3 inset,0 0 0 4px #3b82f629}.login-input[data-v-dc51a501] .el-input__inner{font-size:14px}.btn-login[data-v-dc51a501]{width:100%;padding:12px;border:none;border-radius:10px;background:linear-gradient(135deg,#2563eb,#7c3aed);color:#fff;font-size:16px;font-weight:800;cursor:pointer;transition:transform .15s,filter .15s}.btn-login[data-v-dc51a501]:hover:not(:disabled){transform:translateY(-2px);filter:brightness(1.02)}.btn-login[data-v-dc51a501]:active:not(:disabled){transform:translateY(0)}.btn-login[data-v-dc51a501]:disabled{cursor:not-allowed;opacity:.8}.action-links[data-v-dc51a501]{margin-top:14px;display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap}.link-btn[data-v-dc51a501]{border:none;background:none;color:#2563eb;font-size:13px;font-weight:700;cursor:pointer;padding:0}.link-btn[data-v-dc51a501]:hover{text-decoration:underline}.register-row[data-v-dc51a501]{margin-top:16px;display:flex;justify-content:center;align-items:center;gap:8px;color:#6b7280;font-size:13px}.dialog-form[data-v-dc51a501]{margin-top:10px}.alert[data-v-dc51a501]{margin-top:12px}.captcha-row[data-v-dc51a501]{display:flex;align-items:center;gap:10px;width:100%}.captcha-input[data-v-dc51a501]{flex:1;min-width:0}.captcha-img[data-v-dc51a501]{height:46px;border:1px solid rgba(17,24,39,.14);border-radius:8px;cursor:pointer;-webkit-user-select:none;user-select:none}.captcha-refresh[data-v-dc51a501]{height:44px;padding:0 14px;border:1px solid rgba(17,24,39,.14);border-radius:10px;background:#f8fafc;color:#111827;font-size:13px;cursor:pointer}.captcha-refresh[data-v-dc51a501]:hover{background:#f1f5f9}@media(max-width:480px){.login-page[data-v-dc51a501]{align-items:flex-start;padding:20px 12px 12px}.login-container[data-v-dc51a501]{max-width:100%;padding:28px 20px;border-radius:14px}.login-header h1[data-v-dc51a501]{font-size:22px}.btn-login[data-v-dc51a501]{padding:13px;font-size:15px}.captcha-img[data-v-dc51a501]{height:42px}.captcha-refresh[data-v-dc51a501]{height:42px;padding:0 12px}}

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
.login-page[data-v-b82518fc]{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px;position:relative;background:linear-gradient(135deg,#eef2ff,#f6f7fb 45%,#ecfeff)}.login-page[data-v-b82518fc]:before{content:"";position:fixed;inset:0;background:radial-gradient(800px 500px at 15% 20%,rgba(59,130,246,.18),transparent 60%),radial-gradient(700px 420px at 85% 70%,rgba(124,58,237,.16),transparent 55%);pointer-events:none}.login-container[data-v-b82518fc]{width:100%;max-width:420px;background:#fff;border-radius:16px;box-shadow:0 18px 60px #11182726;border:1px solid rgba(17,24,39,.08);padding:38px 34px;position:relative;z-index:1}.login-header[data-v-b82518fc]{text-align:center;margin-bottom:28px}.login-badge[data-v-b82518fc]{display:inline-block;background:#3b82f61a;color:#1d4ed8;padding:6px 14px;border-radius:999px;font-size:12px;font-weight:700;margin-bottom:14px}.login-header h1[data-v-b82518fc]{font-size:24px;color:#111827;margin:0 0 10px;letter-spacing:.2px}.login-header p[data-v-b82518fc]{margin:0;color:#6b7280;font-size:14px}.form-group[data-v-b82518fc]{margin-bottom:20px}.form-group label[data-v-b82518fc]{display:block;margin-bottom:8px;color:#111827;font-weight:700;font-size:13px}.login-input[data-v-b82518fc] .el-input__wrapper{border-radius:10px;min-height:44px;background:#ffffffe6;box-shadow:0 0 0 1px #11182724 inset;transition:box-shadow .2s}.login-input[data-v-b82518fc] .el-input__wrapper.is-focus{box-shadow:0 0 0 1px #3b82f6b3 inset,0 0 0 4px #3b82f629}.login-input[data-v-b82518fc] .el-input__inner{font-size:14px}.btn-login[data-v-b82518fc]{width:100%;padding:12px;border:none;border-radius:10px;background:linear-gradient(135deg,#2563eb,#7c3aed);color:#fff;font-size:16px;font-weight:800;cursor:pointer;transition:transform .15s,filter .15s}.btn-login[data-v-b82518fc]:hover:not(:disabled){transform:translateY(-2px);filter:brightness(1.02)}.btn-login[data-v-b82518fc]:active:not(:disabled){transform:translateY(0)}.btn-login[data-v-b82518fc]:disabled{cursor:not-allowed;opacity:.8}.action-links[data-v-b82518fc]{margin-top:14px;display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap}.link-btn[data-v-b82518fc]{border:none;background:none;color:#2563eb;font-size:13px;font-weight:700;cursor:pointer;padding:0}.link-btn[data-v-b82518fc]:hover{text-decoration:underline}.register-row[data-v-b82518fc]{margin-top:16px;display:flex;justify-content:center;align-items:center;gap:8px;color:#6b7280;font-size:13px}.dialog-form[data-v-b82518fc]{margin-top:10px}.alert[data-v-b82518fc]{margin-top:12px}.captcha-row[data-v-b82518fc]{display:flex;align-items:center;gap:10px;width:100%}.captcha-input[data-v-b82518fc]{flex:1;min-width:0}.captcha-img[data-v-b82518fc]{height:46px;border:1px solid rgba(17,24,39,.14);border-radius:8px;cursor:pointer;-webkit-user-select:none;user-select:none}.captcha-refresh[data-v-b82518fc]{height:44px;padding:0 14px;border:1px solid rgba(17,24,39,.14);border-radius:10px;background:#f8fafc;color:#111827;font-size:13px;cursor:pointer}.captcha-refresh[data-v-b82518fc]:hover{background:#f1f5f9}@media(max-width:480px){.login-page[data-v-b82518fc]{align-items:flex-start;padding:20px 12px 12px}.login-container[data-v-b82518fc]{max-width:100%;padding:28px 20px;border-radius:14px}.login-header h1[data-v-b82518fc]{font-size:22px}.btn-login[data-v-b82518fc]{padding:13px;font-size:15px}.captcha-img[data-v-b82518fc]{height:42px}.captcha-refresh[data-v-b82518fc]{height:42px;padding:0 12px}}

View File

@@ -1 +1 @@
import{_ as M,r as j,a as d,c as B,o as A,b as U,e as l,h as o,g as v,u as H,i as b,d as n,j as N,f as E,w as P,t as q,k as S,E as c,v as z}from"./index-D1OuoXoU.js";import{g as F,f as G,b as J}from"./auth-RsjJ-Dgh.js";const O={class:"auth-wrap"},Q={class:"hint app-muted"},W={class:"captcha-row"},X=["src"],Y={class:"actions"},Z={__name:"RegisterPage",setup($){const T=H(),a=j({username:"",password:"",confirm_password:"",email:"",captcha:""}),f=d(!1),w=d(""),h=d(""),V=d(!1),t=d(""),_=d(""),k=d(""),K=B(()=>f.value?"邮箱 *":"邮箱(可选)"),R=B(()=>f.value?"必填,用于账号验证":"选填,用于找回密码和接收通知");async function y(){try{const u=await F();h.value=u?.session_id||"",w.value=u?.captcha_image||"",a.captcha=""}catch{h.value="",w.value=""}}async function D(){try{const u=await G();f.value=!!u?.register_verify_enabled}catch{f.value=!1}}function I(){t.value="",_.value="",k.value=""}async function C(){I();const u=a.username.trim(),e=a.password,g=a.confirm_password,s=a.email.trim(),i=a.captcha.trim();if(u.length<3){t.value="用户名至少3个字符",c.error(t.value);return}const p=z(e);if(!p.ok){t.value=p.message||"密码格式不正确",c.error(t.value);return}if(e!==g){t.value="两次输入的密码不一致",c.error(t.value);return}if(f.value&&!s){t.value="请填写邮箱地址用于账号验证",c.error(t.value);return}if(s&&!s.includes("@")){t.value="邮箱格式不正确",c.error(t.value);return}if(!i){t.value="请输入验证码",c.error(t.value);return}V.value=!0;try{const m=await J({username:u,password:e,email:s,captcha_session:h.value,captcha:i});_.value=m?.message||"注册成功",k.value=m?.need_verify?"请检查您的邮箱(包括垃圾邮件文件夹)":"",c.success("注册成功"),a.username="",a.password="",a.confirm_password="",a.email="",a.captcha="",setTimeout(()=>{window.location.href="/login"},3e3)}catch(m){const x=m?.response?.data;t.value=x?.error||"注册失败",c.error(t.value),await y()}finally{V.value=!1}}function L(){T.push("/login")}return A(async()=>{await y(),await D()}),(u,e)=>{const g=v("el-alert"),s=v("el-input"),i=v("el-form-item"),p=v("el-button"),m=v("el-form"),x=v("el-card");return b(),U("div",O,[l(x,{shadow:"never",class:"auth-card","body-style":{padding:"22px"}},{default:o(()=>[e[11]||(e[11]=n("div",{class:"brand"},[n("div",{class:"brand-title"},"知识管理平台"),n("div",{class:"brand-sub app-muted"},"用户注册")],-1)),t.value?(b(),N(g,{key:0,type:"error",closable:!1,title:t.value,"show-icon":"",class:"alert"},null,8,["title"])):E("",!0),_.value?(b(),N(g,{key:1,type:"success",closable:!1,title:_.value,description:k.value,"show-icon":"",class:"alert"},null,8,["title","description"])):E("",!0),l(m,{"label-position":"top"},{default:o(()=>[l(i,{label:"用户名 *"},{default:o(()=>[l(s,{modelValue:a.username,"onUpdate:modelValue":e[0]||(e[0]=r=>a.username=r),placeholder:"至少3个字符",autocomplete:"username"},null,8,["modelValue"]),e[5]||(e[5]=n("div",{class:"hint app-muted"},"至少3个字符",-1))]),_:1}),l(i,{label:"密码 *"},{default:o(()=>[l(s,{modelValue:a.password,"onUpdate:modelValue":e[1]||(e[1]=r=>a.password=r),type:"password","show-password":"",placeholder:"至少8位且包含字母和数字",autocomplete:"new-password"},null,8,["modelValue"]),e[6]||(e[6]=n("div",{class:"hint app-muted"},"至少8位且包含字母和数字",-1))]),_:1}),l(i,{label:"确认密码 *"},{default:o(()=>[l(s,{modelValue:a.confirm_password,"onUpdate:modelValue":e[2]||(e[2]=r=>a.confirm_password=r),type:"password","show-password":"",placeholder:"请再次输入密码",autocomplete:"new-password",onKeyup:P(C,["enter"])},null,8,["modelValue"])]),_:1}),l(i,{label:K.value},{default:o(()=>[l(s,{modelValue:a.email,"onUpdate:modelValue":e[3]||(e[3]=r=>a.email=r),placeholder:"name@example.com",autocomplete:"email"},null,8,["modelValue"]),n("div",Q,q(R.value),1)]),_:1},8,["label"]),l(i,{label:"验证码 *"},{default:o(()=>[n("div",W,[l(s,{modelValue:a.captcha,"onUpdate:modelValue":e[4]||(e[4]=r=>a.captcha=r),placeholder:"请输入验证码",onKeyup:P(C,["enter"])},null,8,["modelValue"]),w.value?(b(),U("img",{key:0,class:"captcha-img",src:w.value,alt:"验证码",title:"点击刷新",onClick:y},null,8,X)):E("",!0),l(p,{onClick:y},{default:o(()=>[...e[7]||(e[7]=[S("刷新",-1)])]),_:1})])]),_:1})]),_:1}),l(p,{type:"primary",class:"submit-btn",loading:V.value,onClick:C},{default:o(()=>[...e[8]||(e[8]=[S("注册",-1)])]),_:1},8,["loading"]),n("div",Y,[e[10]||(e[10]=n("span",{class:"app-muted"},"已有账号?",-1)),l(p,{link:"",type:"primary",onClick:L},{default:o(()=>[...e[9]||(e[9]=[S("立即登录",-1)])]),_:1})])]),_:1})])}}},te=M(Z,[["__scopeId","data-v-a9d7804f"]]);export{te as default}; import{_ as M,r as j,a as d,c as B,o as A,b as U,e as t,i as o,g as v,u as H,j as b,d as n,k as N,f as E,h as P,t as q,l as S,E as c,v as z}from"./index-BUFlUzjg.js";import{g as F,f as G,b as J}from"./auth-BA1ZmOLU.js";const O={class:"auth-wrap"},Q={class:"hint app-muted"},W={class:"captcha-row"},X=["src"],Y={class:"actions"},Z={__name:"RegisterPage",setup($){const T=H(),a=j({username:"",password:"",confirm_password:"",email:"",captcha:""}),f=d(!1),w=d(""),h=d(""),V=d(!1),l=d(""),_=d(""),k=d(""),K=B(()=>f.value?"邮箱 *":"邮箱(可选)"),R=B(()=>f.value?"必填,用于账号验证":"选填,用于找回密码和接收通知");async function y(){try{const u=await F();h.value=u?.session_id||"",w.value=u?.captcha_image||"",a.captcha=""}catch{h.value="",w.value=""}}async function D(){try{const u=await G();f.value=!!u?.register_verify_enabled}catch{f.value=!1}}function I(){l.value="",_.value="",k.value=""}async function C(){I();const u=a.username.trim(),e=a.password,g=a.confirm_password,s=a.email.trim(),i=a.captcha.trim();if(u.length<3){l.value="用户名至少3个字符",c.error(l.value);return}const p=z(e);if(!p.ok){l.value=p.message||"密码格式不正确",c.error(l.value);return}if(e!==g){l.value="两次输入的密码不一致",c.error(l.value);return}if(f.value&&!s){l.value="请填写邮箱地址用于账号验证",c.error(l.value);return}if(s&&!s.includes("@")){l.value="邮箱格式不正确",c.error(l.value);return}if(!i){l.value="请输入验证码",c.error(l.value);return}V.value=!0;try{const m=await J({username:u,password:e,email:s,captcha_session:h.value,captcha:i});_.value=m?.message||"注册成功",k.value=m?.need_verify?"请检查您的邮箱(包括垃圾邮件文件夹)":"",c.success("注册成功"),a.username="",a.password="",a.confirm_password="",a.email="",a.captcha="",setTimeout(()=>{window.location.href="/login"},3e3)}catch(m){const x=m?.response?.data;l.value=x?.error||"注册失败",c.error(l.value),await y()}finally{V.value=!1}}function L(){T.push("/login")}return A(async()=>{await y(),await D()}),(u,e)=>{const g=v("el-alert"),s=v("el-input"),i=v("el-form-item"),p=v("el-button"),m=v("el-form"),x=v("el-card");return b(),U("div",O,[t(x,{shadow:"never",class:"auth-card","body-style":{padding:"22px"}},{default:o(()=>[e[11]||(e[11]=n("div",{class:"brand"},[n("div",{class:"brand-title"},"知识管理平台"),n("div",{class:"brand-sub app-muted"},"用户注册")],-1)),l.value?(b(),N(g,{key:0,type:"error",closable:!1,title:l.value,"show-icon":"",class:"alert"},null,8,["title"])):E("",!0),_.value?(b(),N(g,{key:1,type:"success",closable:!1,title:_.value,description:k.value,"show-icon":"",class:"alert"},null,8,["title","description"])):E("",!0),t(m,{"label-position":"top"},{default:o(()=>[t(i,{label:"用户名 *"},{default:o(()=>[t(s,{modelValue:a.username,"onUpdate:modelValue":e[0]||(e[0]=r=>a.username=r),placeholder:"至少3个字符",autocomplete:"username"},null,8,["modelValue"]),e[5]||(e[5]=n("div",{class:"hint app-muted"},"至少3个字符",-1))]),_:1}),t(i,{label:"密码 *"},{default:o(()=>[t(s,{modelValue:a.password,"onUpdate:modelValue":e[1]||(e[1]=r=>a.password=r),type:"password","show-password":"",placeholder:"至少8位且包含字母和数字",autocomplete:"new-password"},null,8,["modelValue"]),e[6]||(e[6]=n("div",{class:"hint app-muted"},"至少8位且包含字母和数字",-1))]),_:1}),t(i,{label:"确认密码 *"},{default:o(()=>[t(s,{modelValue:a.confirm_password,"onUpdate:modelValue":e[2]||(e[2]=r=>a.confirm_password=r),type:"password","show-password":"",placeholder:"请再次输入密码",autocomplete:"new-password",onKeyup:P(C,["enter"])},null,8,["modelValue"])]),_:1}),t(i,{label:K.value},{default:o(()=>[t(s,{modelValue:a.email,"onUpdate:modelValue":e[3]||(e[3]=r=>a.email=r),placeholder:"name@example.com",autocomplete:"email"},null,8,["modelValue"]),n("div",Q,q(R.value),1)]),_:1},8,["label"]),t(i,{label:"验证码 *"},{default:o(()=>[n("div",W,[t(s,{modelValue:a.captcha,"onUpdate:modelValue":e[4]||(e[4]=r=>a.captcha=r),placeholder:"请输入验证码",onKeyup:P(C,["enter"])},null,8,["modelValue"]),w.value?(b(),U("img",{key:0,class:"captcha-img",src:w.value,alt:"验证码",title:"点击刷新",onClick:y},null,8,X)):E("",!0),t(p,{onClick:y},{default:o(()=>[...e[7]||(e[7]=[S("刷新",-1)])]),_:1})])]),_:1})]),_:1}),t(p,{type:"primary",class:"submit-btn",loading:V.value,onClick:C},{default:o(()=>[...e[8]||(e[8]=[S("注册",-1)])]),_:1},8,["loading"]),n("div",Y,[e[10]||(e[10]=n("span",{class:"app-muted"},"已有账号?",-1)),t(p,{link:"",type:"primary",onClick:L},{default:o(()=>[...e[9]||(e[9]=[S("立即登录",-1)])]),_:1})])]),_:1})])}}},le=M(Z,[["__scopeId","data-v-a9d7804f"]]);export{le as default};

View File

@@ -0,0 +1 @@
import{_ as L,a as n,m as M,r as U,c as j,o as F,n as K,b as v,e as s,i as a,g as l,u as D,j as m,d as w,F as T,l as k,k as q,f as x,h as z,t as G,v as H,E as y}from"./index-BUFlUzjg.js";import{c as J}from"./auth-BA1ZmOLU.js";const O={class:"auth-wrap"},Q={class:"actions"},W={class:"actions"},X={key:0,class:"app-muted"},Y={__name:"ResetPasswordPage",setup(Z){const B=M(),A=D(),r=n(String(B.params.token||"")),i=n(!0),b=n(""),t=U({newPassword:"",confirmPassword:""}),g=n(!1),_=n(""),d=n(0);let u=null;function C(){if(typeof window>"u")return null;const o=window.__APP_INITIAL_STATE__;return!o||typeof o!="object"?null:(window.__APP_INITIAL_STATE__=null,o)}const I=j(()=>!!(i.value&&r.value&&!_.value));function S(){A.push("/login")}function N(){d.value=3,u=window.setInterval(()=>{d.value-=1,d.value<=0&&(window.clearInterval(u),u=null,window.location.href="/login")},1e3)}async function V(){if(!I.value)return;const o=t.newPassword,e=t.confirmPassword,c=H(o);if(!c.ok){y.error(c.message);return}if(o!==e){y.error("两次输入的密码不一致");return}g.value=!0;try{await J({token:r.value,new_password:o}),_.value="密码重置成功3秒后跳转到登录页面...",y.success("密码重置成功"),N()}catch(p){const f=p?.response?.data;y.error(f?.error||"重置失败")}finally{g.value=!1}}return F(()=>{const o=C();o?.page==="reset_password"?(r.value=String(o?.token||r.value||""),i.value=!!o?.valid,b.value=o?.error_message||(i.value?"":"重置链接无效或已过期,请重新申请密码重置")):r.value||(i.value=!1,b.value="重置链接无效或已过期,请重新申请密码重置")}),K(()=>{u&&window.clearInterval(u)}),(o,e)=>{const c=l("el-alert"),p=l("el-button"),f=l("el-input"),h=l("el-form-item"),R=l("el-form"),E=l("el-card");return m(),v("div",O,[s(E,{shadow:"never",class:"auth-card","body-style":{padding:"22px"}},{default:a(()=>[e[5]||(e[5]=w("div",{class:"brand"},[w("div",{class:"brand-title"},"知识管理平台"),w("div",{class:"brand-sub app-muted"},"重置密码")],-1)),i.value?(m(),v(T,{key:1},[_.value?(m(),q(c,{key:0,type:"success",closable:!1,title:"重置成功",description:_.value,"show-icon":"",class:"alert"},null,8,["description"])):x("",!0),s(R,{"label-position":"top"},{default:a(()=>[s(h,{label:"新密码至少8位且包含字母和数字"},{default:a(()=>[s(f,{modelValue:t.newPassword,"onUpdate:modelValue":e[0]||(e[0]=P=>t.newPassword=P),type:"password","show-password":"",placeholder:"请输入新密码",autocomplete:"new-password"},null,8,["modelValue"])]),_:1}),s(h,{label:"确认密码"},{default:a(()=>[s(f,{modelValue:t.confirmPassword,"onUpdate:modelValue":e[1]||(e[1]=P=>t.confirmPassword=P),type:"password","show-password":"",placeholder:"请再次输入新密码",autocomplete:"new-password",onKeyup:z(V,["enter"])},null,8,["modelValue"])]),_:1})]),_:1}),s(p,{type:"primary",class:"submit-btn",loading:g.value,disabled:!I.value,onClick:V},{default:a(()=>[...e[3]||(e[3]=[k(" 确认重置 ",-1)])]),_:1},8,["loading","disabled"]),w("div",W,[s(p,{link:"",type:"primary",onClick:S},{default:a(()=>[...e[4]||(e[4]=[k("返回登录",-1)])]),_:1}),d.value>0?(m(),v("span",X,G(d.value)+" 秒后自动跳转…",1)):x("",!0)])],64)):(m(),v(T,{key:0},[s(c,{type:"error",closable:!1,title:"链接已失效",description:b.value,"show-icon":""},null,8,["description"]),w("div",Q,[s(p,{type:"primary",onClick:S},{default:a(()=>[...e[2]||(e[2]=[k("返回登录",-1)])]),_:1})])],64))]),_:1})])}}},oe=L(Y,[["__scopeId","data-v-0bbb511c"]]);export{oe as default};

View File

@@ -1 +0,0 @@
import{_ as L,a as n,l as M,r as U,c as j,o as F,m as K,b as v,e as s,h as a,g as l,u as D,i as w,d as m,F as T,k,j as q,f as x,w as z,t as G,v as H,E as y}from"./index-D1OuoXoU.js";import{c as J}from"./auth-RsjJ-Dgh.js";const O={class:"auth-wrap"},Q={class:"actions"},W={class:"actions"},X={key:0,class:"app-muted"},Y={__name:"ResetPasswordPage",setup(Z){const B=M(),A=D(),r=n(String(B.params.token||"")),i=n(!0),b=n(""),t=U({newPassword:"",confirmPassword:""}),g=n(!1),_=n(""),d=n(0);let u=null;function C(){if(typeof window>"u")return null;const o=window.__APP_INITIAL_STATE__;return!o||typeof o!="object"?null:(window.__APP_INITIAL_STATE__=null,o)}const I=j(()=>!!(i.value&&r.value&&!_.value));function S(){A.push("/login")}function N(){d.value=3,u=window.setInterval(()=>{d.value-=1,d.value<=0&&(window.clearInterval(u),u=null,window.location.href="/login")},1e3)}async function V(){if(!I.value)return;const o=t.newPassword,e=t.confirmPassword,c=H(o);if(!c.ok){y.error(c.message);return}if(o!==e){y.error("两次输入的密码不一致");return}g.value=!0;try{await J({token:r.value,new_password:o}),_.value="密码重置成功3秒后跳转到登录页面...",y.success("密码重置成功"),N()}catch(p){const f=p?.response?.data;y.error(f?.error||"重置失败")}finally{g.value=!1}}return F(()=>{const o=C();o?.page==="reset_password"?(r.value=String(o?.token||r.value||""),i.value=!!o?.valid,b.value=o?.error_message||(i.value?"":"重置链接无效或已过期,请重新申请密码重置")):r.value||(i.value=!1,b.value="重置链接无效或已过期,请重新申请密码重置")}),K(()=>{u&&window.clearInterval(u)}),(o,e)=>{const c=l("el-alert"),p=l("el-button"),f=l("el-input"),h=l("el-form-item"),R=l("el-form"),E=l("el-card");return w(),v("div",O,[s(E,{shadow:"never",class:"auth-card","body-style":{padding:"22px"}},{default:a(()=>[e[5]||(e[5]=m("div",{class:"brand"},[m("div",{class:"brand-title"},"知识管理平台"),m("div",{class:"brand-sub app-muted"},"重置密码")],-1)),i.value?(w(),v(T,{key:1},[_.value?(w(),q(c,{key:0,type:"success",closable:!1,title:"重置成功",description:_.value,"show-icon":"",class:"alert"},null,8,["description"])):x("",!0),s(R,{"label-position":"top"},{default:a(()=>[s(h,{label:"新密码至少8位且包含字母和数字"},{default:a(()=>[s(f,{modelValue:t.newPassword,"onUpdate:modelValue":e[0]||(e[0]=P=>t.newPassword=P),type:"password","show-password":"",placeholder:"请输入新密码",autocomplete:"new-password"},null,8,["modelValue"])]),_:1}),s(h,{label:"确认密码"},{default:a(()=>[s(f,{modelValue:t.confirmPassword,"onUpdate:modelValue":e[1]||(e[1]=P=>t.confirmPassword=P),type:"password","show-password":"",placeholder:"请再次输入新密码",autocomplete:"new-password",onKeyup:z(V,["enter"])},null,8,["modelValue"])]),_:1})]),_:1}),s(p,{type:"primary",class:"submit-btn",loading:g.value,disabled:!I.value,onClick:V},{default:a(()=>[...e[3]||(e[3]=[k(" 确认重置 ",-1)])]),_:1},8,["loading","disabled"]),m("div",W,[s(p,{link:"",type:"primary",onClick:S},{default:a(()=>[...e[4]||(e[4]=[k("返回登录",-1)])]),_:1}),d.value>0?(w(),v("span",X,G(d.value)+" 秒后自动跳转…",1)):x("",!0)])],64)):(w(),v(T,{key:0},[s(c,{type:"error",closable:!1,title:"链接已失效",description:b.value,"show-icon":""},null,8,["description"]),m("div",Q,[s(p,{type:"primary",onClick:S},{default:a(()=>[...e[2]||(e[2]=[k("返回登录",-1)])]),_:1})])],64))]),_:1})])}}},oe=L(Y,[["__scopeId","data-v-0bbb511c"]]);export{oe as default};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
import{_ as U,a as o,c as I,o as E,m as R,b as k,e as i,h as s,g as d,u as j,i as _,d as l,f as B,j as W,k as T,t as v}from"./index-D1OuoXoU.js";const $={class:"auth-wrap"},z={class:"actions"},D={key:0,class:"countdown app-muted"},M={__name:"VerifyResultPage",setup(q){const x=j(),p=o(!1),f=o(""),m=o(""),w=o(""),y=o(""),r=o(""),u=o(""),c=o(""),n=o(0);let a=null;function C(){if(typeof window>"u")return null;const e=window.__APP_INITIAL_STATE__;return!e||typeof e!="object"?null:(window.__APP_INITIAL_STATE__=null,e)}function N(e){const t=!!e?.success;p.value=t,f.value=e?.title||(t?"验证成功":"验证失败"),m.value=e?.message||e?.error_message||(t?"操作已完成,现在可以继续使用系统。":"操作失败,请稍后重试。"),w.value=e?.primary_label||(t?"立即登录":"重新注册"),y.value=e?.primary_url||(t?"/login":"/register"),r.value=e?.secondary_label||(t?"":"返回登录"),u.value=e?.secondary_url||(t?"":"/login"),c.value=e?.redirect_url||(t?"/login":""),n.value=Number(e?.redirect_seconds||(t?5:0))||0}const A=I(()=>!!(r.value&&u.value)),b=I(()=>!!(c.value&&n.value>0));async function g(e){if(e){if(e.startsWith("http://")||e.startsWith("https://")){window.location.href=e;return}await x.push(e)}}function P(){b.value&&(a=window.setInterval(()=>{n.value-=1,n.value<=0&&(window.clearInterval(a),a=null,window.location.href=c.value)},1e3))}return E(()=>{const e=C();N(e),P()}),R(()=>{a&&window.clearInterval(a)}),(e,t)=>{const h=d("el-button"),V=d("el-result"),L=d("el-card");return _(),k("div",$,[i(L,{shadow:"never",class:"auth-card","body-style":{padding:"22px"}},{default:s(()=>[t[2]||(t[2]=l("div",{class:"brand"},[l("div",{class:"brand-title"},"知识管理平台"),l("div",{class:"brand-sub app-muted"},"验证结果")],-1)),i(V,{icon:p.value?"success":"error",title:f.value,"sub-title":m.value,class:"result"},{extra:s(()=>[l("div",z,[i(h,{type:"primary",onClick:t[0]||(t[0]=S=>g(y.value))},{default:s(()=>[T(v(w.value),1)]),_:1}),A.value?(_(),W(h,{key:0,onClick:t[1]||(t[1]=S=>g(u.value))},{default:s(()=>[T(v(r.value),1)]),_:1})):B("",!0)]),b.value?(_(),k("div",D,v(n.value)+" 秒后自动跳转... ",1)):B("",!0)]),_:1},8,["icon","title","sub-title"])]),_:1})])}}},G=U(M,[["__scopeId","data-v-1fc6b081"]]);export{G as default}; import{_ as U,a as o,c as I,o as E,n as R,b as k,e as i,i as s,g as d,u as j,j as _,d as l,f as B,k as W,l as T,t as v}from"./index-BUFlUzjg.js";const $={class:"auth-wrap"},z={class:"actions"},D={key:0,class:"countdown app-muted"},M={__name:"VerifyResultPage",setup(q){const x=j(),p=o(!1),f=o(""),m=o(""),w=o(""),y=o(""),r=o(""),u=o(""),c=o(""),n=o(0);let a=null;function C(){if(typeof window>"u")return null;const e=window.__APP_INITIAL_STATE__;return!e||typeof e!="object"?null:(window.__APP_INITIAL_STATE__=null,e)}function N(e){const t=!!e?.success;p.value=t,f.value=e?.title||(t?"验证成功":"验证失败"),m.value=e?.message||e?.error_message||(t?"操作已完成,现在可以继续使用系统。":"操作失败,请稍后重试。"),w.value=e?.primary_label||(t?"立即登录":"重新注册"),y.value=e?.primary_url||(t?"/login":"/register"),r.value=e?.secondary_label||(t?"":"返回登录"),u.value=e?.secondary_url||(t?"":"/login"),c.value=e?.redirect_url||(t?"/login":""),n.value=Number(e?.redirect_seconds||(t?5:0))||0}const A=I(()=>!!(r.value&&u.value)),b=I(()=>!!(c.value&&n.value>0));async function g(e){if(e){if(e.startsWith("http://")||e.startsWith("https://")){window.location.href=e;return}await x.push(e)}}function P(){b.value&&(a=window.setInterval(()=>{n.value-=1,n.value<=0&&(window.clearInterval(a),a=null,window.location.href=c.value)},1e3))}return E(()=>{const e=C();N(e),P()}),R(()=>{a&&window.clearInterval(a)}),(e,t)=>{const h=d("el-button"),V=d("el-result"),L=d("el-card");return _(),k("div",$,[i(L,{shadow:"never",class:"auth-card","body-style":{padding:"22px"}},{default:s(()=>[t[2]||(t[2]=l("div",{class:"brand"},[l("div",{class:"brand-title"},"知识管理平台"),l("div",{class:"brand-sub app-muted"},"验证结果")],-1)),i(V,{icon:p.value?"success":"error",title:f.value,"sub-title":m.value,class:"result"},{extra:s(()=>[l("div",z,[i(h,{type:"primary",onClick:t[0]||(t[0]=S=>g(y.value))},{default:s(()=>[T(v(w.value),1)]),_:1}),A.value?(_(),W(h,{key:0,onClick:t[1]||(t[1]=S=>g(u.value))},{default:s(()=>[T(v(r.value),1)]),_:1})):B("",!0)]),b.value?(_(),k("div",D,v(n.value)+" 秒后自动跳转... ",1)):B("",!0)]),_:1},8,["icon","title","sub-title"])]),_:1})])}}},G=U(M,[["__scopeId","data-v-1fc6b081"]]);export{G as default};

View File

@@ -1 +1 @@
import{p as c}from"./index-D1OuoXoU.js";async function o(t={}){const{data:a}=await c.get("/accounts",{params:t});return a}async function u(t){const{data:a}=await c.post("/accounts",t);return a}async function r(t,a){const{data:n}=await c.put(`/accounts/${t}`,a);return n}async function e(t){const{data:a}=await c.delete(`/accounts/${t}`);return a}async function i(t,a){const{data:n}=await c.put(`/accounts/${t}/remark`,a);return n}async function p(t,a){const{data:n}=await c.post(`/accounts/${t}/start`,a);return n}async function d(t){const{data:a}=await c.post(`/accounts/${t}/stop`,{});return a}async function f(t){const{data:a}=await c.post("/accounts/batch/start",t);return a}async function w(t){const{data:a}=await c.post("/accounts/batch/stop",t);return a}async function y(){const{data:t}=await c.post("/accounts/clear",{});return t}async function A(t,a={}){const{data:n}=await c.post(`/accounts/${t}/screenshot`,a);return n}export{w as a,f as b,y as c,d,e,o as f,u as g,i as h,p as s,A as t,r as u}; import{p as c}from"./index-BUFlUzjg.js";async function o(t={}){const{data:a}=await c.get("/accounts",{params:t});return a}async function u(t){const{data:a}=await c.post("/accounts",t);return a}async function r(t,a){const{data:n}=await c.put(`/accounts/${t}`,a);return n}async function e(t){const{data:a}=await c.delete(`/accounts/${t}`);return a}async function i(t,a){const{data:n}=await c.put(`/accounts/${t}/remark`,a);return n}async function p(t,a){const{data:n}=await c.post(`/accounts/${t}/start`,a);return n}async function d(t){const{data:a}=await c.post(`/accounts/${t}/stop`,{});return a}async function f(t){const{data:a}=await c.post("/accounts/batch/start",t);return a}async function w(t){const{data:a}=await c.post("/accounts/batch/stop",t);return a}async function y(){const{data:t}=await c.post("/accounts/clear",{});return t}async function A(t,a={}){const{data:n}=await c.post(`/accounts/${t}/screenshot`,a);return n}export{w as a,f as b,y as c,d,e,o as f,u as g,i as h,p as s,A as t,r as u};

View File

@@ -1 +1 @@
import{p as s}from"./index-D1OuoXoU.js";async function r(){const{data:a}=await s.get("/email/verify-status");return a}async function o(){const{data:a}=await s.post("/generate_captcha",{});return a}async function e(a){const{data:t}=await s.post("/login",a);return t}async function i(a){const{data:t}=await s.post("/register",a);return t}async function c(a){const{data:t}=await s.post("/resend-verify-email",a);return t}async function f(a){const{data:t}=await s.post("/forgot-password",a);return t}async function u(a){const{data:t}=await s.post("/reset-password-confirm",a);return t}export{f as a,i as b,u as c,r as f,o as g,e as l,c as r}; import{p as s}from"./index-BUFlUzjg.js";async function r(){const{data:a}=await s.get("/email/verify-status");return a}async function o(){const{data:a}=await s.post("/generate_captcha",{});return a}async function e(a){const{data:t}=await s.post("/login",a);return t}async function i(a){const{data:t}=await s.post("/register",a);return t}async function c(a){const{data:t}=await s.post("/resend-verify-email",a);return t}async function f(a){const{data:t}=await s.post("/forgot-password",a);return t}async function u(a){const{data:t}=await s.post("/reset-password-confirm",a);return t}export{f as a,i as b,u as c,r as f,o as g,e as l,c as r};

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<title>知识管理平台</title> <title>知识管理平台</title>
<script type="module" crossorigin src="./assets/index-D1OuoXoU.js"></script> <script type="module" crossorigin src="./assets/index-BUFlUzjg.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-BVjJVlht.css"> <link rel="stylesheet" crossorigin href="./assets/index-BVjJVlht.css">
</head> </head>
<body> <body>