Integrate KDocs auto-upload
This commit is contained in:
16
admin-frontend/src/api/kdocs.js
Normal file
16
admin-frontend/src/api/kdocs.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import { api } from './client'
|
||||
|
||||
export async function fetchKdocsStatus() {
|
||||
const { data } = await api.get('/kdocs/status')
|
||||
return data
|
||||
}
|
||||
|
||||
export async function fetchKdocsQr() {
|
||||
const { data } = await api.post('/kdocs/qr', {})
|
||||
return data
|
||||
}
|
||||
|
||||
export async function clearKdocsLogin() {
|
||||
const { data } = await api.post('/kdocs/clear-login', {})
|
||||
return data
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { computed, onMounted, ref } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
|
||||
import { fetchSystemConfig, updateSystemConfig, executeScheduleNow } from '../api/system'
|
||||
import { fetchKdocsQr, fetchKdocsStatus, clearKdocsLogin } from '../api/kdocs'
|
||||
import { fetchProxyConfig, testProxy, updateProxyConfig } from '../api/proxy'
|
||||
|
||||
const loading = ref(false)
|
||||
@@ -29,6 +30,20 @@ const autoApproveEnabled = ref(false)
|
||||
const autoApproveHourlyLimit = ref(10)
|
||||
const autoApproveVipDays = ref(7)
|
||||
|
||||
// 金山文档上传
|
||||
const kdocsEnabled = ref(false)
|
||||
const kdocsDocUrl = ref('')
|
||||
const kdocsDefaultUnit = ref('')
|
||||
const kdocsSheetName = ref('')
|
||||
const kdocsSheetIndex = ref(0)
|
||||
const kdocsUnitColumn = ref('A')
|
||||
const kdocsImageColumn = ref('D')
|
||||
const kdocsAdminNotifyEnabled = ref(false)
|
||||
const kdocsAdminNotifyEmail = ref('')
|
||||
const kdocsStatus = ref({})
|
||||
const kdocsQrOpen = ref(false)
|
||||
const kdocsQrImage = ref('')
|
||||
|
||||
const weekdaysOptions = [
|
||||
{ label: '周一', value: '1' },
|
||||
{ label: '周二', value: '2' },
|
||||
@@ -63,7 +78,11 @@ function normalizeBrowseType(value) {
|
||||
async function loadAll() {
|
||||
loading.value = true
|
||||
try {
|
||||
const [system, proxy] = await Promise.all([fetchSystemConfig(), fetchProxyConfig()])
|
||||
const [system, proxy, kdocsInfo] = await Promise.all([
|
||||
fetchSystemConfig(),
|
||||
fetchProxyConfig(),
|
||||
fetchKdocsStatus().catch(() => ({})),
|
||||
])
|
||||
|
||||
maxConcurrentGlobal.value = system.max_concurrent_global ?? 2
|
||||
maxConcurrentPerAccount.value = system.max_concurrent_per_account ?? 1
|
||||
@@ -87,6 +106,17 @@ async function loadAll() {
|
||||
proxyEnabled.value = (proxy.proxy_enabled ?? 0) === 1
|
||||
proxyApiUrl.value = proxy.proxy_api_url || ''
|
||||
proxyExpireMinutes.value = proxy.proxy_expire_minutes ?? 3
|
||||
|
||||
kdocsEnabled.value = (system.kdocs_enabled ?? 0) === 1
|
||||
kdocsDocUrl.value = system.kdocs_doc_url || ''
|
||||
kdocsDefaultUnit.value = system.kdocs_default_unit || ''
|
||||
kdocsSheetName.value = system.kdocs_sheet_name || ''
|
||||
kdocsSheetIndex.value = system.kdocs_sheet_index ?? 0
|
||||
kdocsUnitColumn.value = (system.kdocs_unit_column || 'A').toUpperCase()
|
||||
kdocsImageColumn.value = (system.kdocs_image_column || 'D').toUpperCase()
|
||||
kdocsAdminNotifyEnabled.value = (system.kdocs_admin_notify_enabled ?? 0) === 1
|
||||
kdocsAdminNotifyEmail.value = system.kdocs_admin_notify_email || ''
|
||||
kdocsStatus.value = kdocsInfo || {}
|
||||
} catch {
|
||||
// handled by interceptor
|
||||
} finally {
|
||||
@@ -196,6 +226,64 @@ async function saveProxy() {
|
||||
}
|
||||
}
|
||||
|
||||
async function saveKdocsConfig() {
|
||||
const payload = {
|
||||
kdocs_enabled: kdocsEnabled.value ? 1 : 0,
|
||||
kdocs_doc_url: kdocsDocUrl.value.trim(),
|
||||
kdocs_default_unit: kdocsDefaultUnit.value.trim(),
|
||||
kdocs_sheet_name: kdocsSheetName.value.trim(),
|
||||
kdocs_sheet_index: Number(kdocsSheetIndex.value) || 0,
|
||||
kdocs_unit_column: kdocsUnitColumn.value.trim().toUpperCase(),
|
||||
kdocs_image_column: kdocsImageColumn.value.trim().toUpperCase(),
|
||||
kdocs_admin_notify_enabled: kdocsAdminNotifyEnabled.value ? 1 : 0,
|
||||
kdocs_admin_notify_email: kdocsAdminNotifyEmail.value.trim(),
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await updateSystemConfig(payload)
|
||||
ElMessage.success(res?.message || '表格配置已更新')
|
||||
} catch {
|
||||
// handled by interceptor
|
||||
}
|
||||
}
|
||||
|
||||
async function refreshKdocsStatus() {
|
||||
try {
|
||||
kdocsStatus.value = await fetchKdocsStatus()
|
||||
} catch {
|
||||
// handled by interceptor
|
||||
}
|
||||
}
|
||||
|
||||
async function onFetchKdocsQr() {
|
||||
try {
|
||||
const res = await fetchKdocsQr()
|
||||
if (res?.logged_in) {
|
||||
ElMessage.success('当前已登录,无需扫码')
|
||||
await refreshKdocsStatus()
|
||||
return
|
||||
}
|
||||
kdocsQrImage.value = res?.qr_image || ''
|
||||
if (!kdocsQrImage.value) {
|
||||
ElMessage.warning('未获取到二维码')
|
||||
return
|
||||
}
|
||||
kdocsQrOpen.value = true
|
||||
} catch {
|
||||
// handled by interceptor
|
||||
}
|
||||
}
|
||||
|
||||
async function onClearKdocsLogin() {
|
||||
try {
|
||||
await clearKdocsLogin()
|
||||
ElMessage.success('登录态已清除')
|
||||
await refreshKdocsStatus()
|
||||
} catch {
|
||||
// handled by interceptor
|
||||
}
|
||||
}
|
||||
|
||||
async function onTestProxy() {
|
||||
if (!proxyApiUrl.value.trim()) {
|
||||
ElMessage.error('请先输入代理API地址')
|
||||
@@ -357,6 +445,73 @@ onMounted(loadAll)
|
||||
|
||||
<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-switch v-model="kdocsEnabled" />
|
||||
<div class="help">表格结构变化时可先关闭,避免错误上传。</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="文档链接">
|
||||
<el-input v-model="kdocsDocUrl" placeholder="https://kdocs.cn/..." />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="默认县区">
|
||||
<el-input v-model="kdocsDefaultUnit" placeholder="如:道县(用户可覆盖)" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Sheet名称">
|
||||
<el-input v-model="kdocsSheetName" placeholder="留空使用第一个Sheet" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Sheet序号">
|
||||
<el-input-number v-model="kdocsSheetIndex" :min="0" :max="50" />
|
||||
<div class="help">0 表示第一个Sheet。</div>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="县区列">
|
||||
<el-input v-model="kdocsUnitColumn" placeholder="A" style="max-width: 120px" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="图片列">
|
||||
<el-input v-model="kdocsImageColumn" placeholder="D" style="max-width: 120px" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="管理员通知">
|
||||
<el-switch v-model="kdocsAdminNotifyEnabled" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="通知邮箱">
|
||||
<el-input v-model="kdocsAdminNotifyEmail" placeholder="admin@example.com" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="row-actions">
|
||||
<el-button type="primary" @click="saveKdocsConfig">保存表格配置</el-button>
|
||||
<el-button @click="refreshKdocsStatus">刷新状态</el-button>
|
||||
<el-button type="success" plain @click="onFetchKdocsQr">获取二维码</el-button>
|
||||
<el-button type="danger" plain @click="onClearKdocsLogin">清除登录</el-button>
|
||||
</div>
|
||||
|
||||
<div class="help">
|
||||
登录状态:
|
||||
<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>
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="kdocsQrOpen" title="扫码登录" width="min(420px, 92vw)">
|
||||
<div class="kdocs-qr">
|
||||
<img v-if="kdocsQrImage" :src="`data:image/png;base64,${kdocsQrImage}`" alt="KDocs QR" />
|
||||
<div class="help">请使用管理员微信扫码登录。</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -378,6 +533,22 @@ onMounted(loadAll)
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.kdocs-qr {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.kdocs-qr img {
|
||||
width: 260px;
|
||||
max-width: 100%;
|
||||
border: 1px solid var(--app-border);
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.help {
|
||||
margin-top: 6px;
|
||||
font-size: 12px;
|
||||
|
||||
Reference in New Issue
Block a user