This commit is contained in:
2026-01-14 14:17:38 +08:00
commit f1e2ff6563
126 changed files with 13636 additions and 0 deletions

13
web/index.html Normal file
View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>SSQ-Desk</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

1462
web/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

18
web/package.json Normal file
View File

@@ -0,0 +1,18 @@
{
"name": "ssq-desk-web",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"@arco-design/web-vue": "^2.54.0",
"vue": "^3.5.26"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.3",
"vite": "^7.3.0"
}
}

1
web/package.json.md5 Normal file
View File

@@ -0,0 +1 @@
67c87d1d32114e5c095571d4f62523e1

136
web/src/App.vue Normal file
View File

@@ -0,0 +1,136 @@
<template>
<div class="app">
<a-layout class="layout">
<a-layout-header class="header">
<div class="header-content">
<h1 class="title">SSQ-Desk</h1>
<a-menu
mode="horizontal"
:selected-keys="[currentPage]"
@menu-item-click="handleMenuClick"
class="nav-menu"
>
<a-menu-item key="query">
<template #icon>
<icon-search />
</template>
查询
</a-menu-item>
<a-menu-item key="auth">
<template #icon>
<icon-lock />
</template>
授权
</a-menu-item>
</a-menu>
<div class="header-actions">
<span class="version-text">当前版本{{ version.currentVersion || '加载中...' }}</span>
</div>
</div>
</a-layout-header>
<a-layout-content class="content">
<QueryPage v-if="currentPage === 'query'" />
<AuthPage v-if="currentPage === 'auth'" />
</a-layout-content>
</a-layout>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { IconSearch, IconLock } from '@arco-design/web-vue/es/icon'
import QueryPage from './views/query/QueryPage.vue'
import AuthPage from './views/auth/AuthPage.vue'
import { useVersion } from './composables/useVersion'
// ==================== 导航 ====================
const currentPage = ref('query')
const handleMenuClick = (key) => {
currentPage.value = key
}
// ==================== 版本相关 ====================
const version = useVersion()
// 应用启动时不再重复调用useVersion 内部已处理
</script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB',
'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
#app {
width: 100%;
height: 100vh;
}
.app {
width: 100%;
height: 100vh;
}
.layout {
height: 100%;
}
.header {
background: var(--color-bg-2);
border-bottom: 1px solid var(--color-border);
padding: 0 !important;
height: 48px !important;
line-height: 48px;
}
.header.arco-layout-header {
padding: 0 !important;
}
.header-content {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 16px;
height: 100%;
flex-wrap: nowrap;
}
.title {
margin: 0;
font-size: 16px;
font-weight: 500;
white-space: nowrap;
flex-shrink: 0;
}
.nav-menu {
background: transparent;
border: none;
flex-shrink: 0;
}
.version-text {
font-size: 14px;
color: var(--color-text-1);
margin-right: 16px;
}
.header-actions {
display: flex;
align-items: center;
}
.content {
overflow-y: auto;
}
</style>

View File

@@ -0,0 +1,484 @@
import { ref, onMounted, h, onUnmounted, nextTick, watch } from 'vue'
import { Message, Modal, Progress } from '@arco-design/web-vue'
import { EventsOn } from '../wailsjs/runtime/runtime'
// 扩展 Window 接口以支持 Wails 运行时
declare global {
interface Window {
go: any
}
}
/**
* 更新信息接口
*/
interface UpdateInfo {
has_update: boolean
current_version: string
latest_version: string
download_url: string
changelog: string
force_update: boolean
release_date: string
}
/**
* 更新配置接口
*/
interface UpdateConfig {
auto_check_enabled: boolean
check_interval_minutes: number
check_url?: string
last_check_time?: string
}
/**
* API 响应接口
*/
interface ApiResponse<T = any> {
success: boolean
data?: T
message?: string
}
/**
* 版本更新 Composable
* 封装版本相关的逻辑和状态管理
*/
export function useVersion() {
// ==================== 状态定义 ====================
const currentVersion = ref<string>('加载中...')
const autoCheckEnabled = ref<boolean>(true)
const checking = ref<boolean>(false)
const updateInfo = ref<UpdateInfo | null>(null)
// 下载和安装状态
const downloading = ref<boolean>(false)
const installing = ref<boolean>(false)
const downloadProgress = ref<number>(0)
const downloadSpeed = ref<number>(0)
const downloadedSize = ref<number>(0)
const totalSize = ref<number>(0)
const installStatus = ref<string>('')
// 模态框实例
let progressModalInstance: any = null
// ==================== 版本信息 ====================
/**
* 获取当前版本
*/
const loadCurrentVersion = async (): Promise<string> => {
try {
const result = await window.go.main.App.GetCurrentVersion()
if (result && result.success) {
currentVersion.value = result.data.version
updateInfo.value = null
return result.data.version
} else {
console.error(`[版本] 获取版本失败: ${result?.message || '未知错误'}`)
currentVersion.value = '未知'
throw new Error('获取版本失败')
}
} catch (error: any) {
console.error('获取当前版本失败:', error)
currentVersion.value = '未知'
throw error
}
}
/**
* 获取更新配置
*/
const loadUpdateConfig = async (): Promise<void> => {
try {
const result: ApiResponse<UpdateConfig> = await window.go.main.App.GetUpdateConfig()
if (result && result.success && result.data) {
const data = result.data
autoCheckEnabled.value = data.auto_check_enabled || false
}
} catch (error: any) {
console.error('获取更新配置失败:', error)
}
}
// ==================== 版本检查 ====================
/**
* 检查更新
*/
const checkUpdate = async (): Promise<void> => {
if (checking.value) {
return
}
checking.value = true
try {
const result: ApiResponse<UpdateInfo> = await window.go.main.App.CheckUpdate()
if (!result) {
Message.error('检查更新失败:服务器无响应')
return
}
if (!result.success) {
const errorMsg = result.message || '未知错误'
Message.error(`检查更新失败:${errorMsg}`)
return
}
if (!result.data) {
Message.error('检查更新失败:未获取到版本信息')
return
}
const data = result.data
updateInfo.value = data
if (data.has_update) {
// 显示更新提示对话框
Modal.confirm({
title: '发现新版本',
content: () => [
h('div', { style: { marginBottom: '12px', fontWeight: 'bold', fontSize: '16px' } }, [
`当前版本:${data.current_version}`
]),
h('div', { style: { fontWeight: 'bold', fontSize: '16px' } }, [
`最新版本:${data.latest_version}`
]),
h('div', { style: { marginTop: '16px', fontSize: '14px', color: '#666' } }, [
data.changelog || '暂无更新日志'
]),
data.force_update
? h('div', { style: { marginTop: '12px', color: '#ff4d4f', fontWeight: 'bold' } },
'⚠️ 此为强制更新,必须更新后才能继续使用'
)
: null
],
okText: data.force_update ? '立即更新' : '稍后提醒',
cancelText: data.force_update ? undefined : '关闭',
closable: !data.force_update,
maskClosable: !data.force_update,
onOk: async () => {
// 直接开始下载,并显示进度模态框
await downloadUpdate()
}
})
}
} catch (error: any) {
const errorMsg = error?.message || String(error) || '未知错误'
console.error('检查更新失败:', error)
Message.error(`检查更新失败:${errorMsg}`)
} finally {
checking.value = false
}
}
// ==================== 辅助函数 ====================
/**
* 标准化进度值(确保在 0-100 之间)
*/
const clampProgress = (value: number): number => {
if (isNaN(value)) return 0
return Math.max(0, Math.min(100, value))
}
// ==================== 下载和安装 ====================
/**
* 格式化文件大小
*/
const formatFileSize = (bytes: number): string => {
if (bytes === 0) return '0 B'
const k = 1024
const sizes = ['B', 'KB', 'MB', 'GB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i]
}
/**
* 生成进度模态框内容(响应式)
*/
const getProgressModalContent = () => {
if (downloading.value) {
// 下载中
return [
h('div', { style: { marginBottom: '16px' } }, [
h('div', { style: { marginBottom: '8px', fontSize: '14px', color: '#666' } }, '正在下载更新包...')
]),
h('div', { style: { marginBottom: '8px' } }, [
h(Progress, {
percent: clampProgress(downloadProgress.value),
showText: true
})
]),
h('div', { style: { fontSize: '12px', color: '#999', marginTop: '8px' } }, [
totalSize.value > 0
? `${formatFileSize(downloadedSize.value)} / ${formatFileSize(totalSize.value)}`
: downloadProgress.value > 0 ? '计算文件大小...' : '准备下载...'
]),
downloadSpeed.value > 0
? h('div', { style: { fontSize: '12px', color: '#999', marginTop: '4px' } },
`下载速度: ${formatFileSize(downloadSpeed.value)}/s`
)
: null
]
} else if (installing.value) {
// 安装中
return [
h('div', { style: { marginBottom: '16px' } }, [
h('div', { style: { marginBottom: '8px', fontSize: '14px', color: '#666' } }, '正在安装更新...')
]),
h('div', { style: { fontSize: '12px', color: '#999' } }, installStatus.value || '准备安装中...')
]
} else {
// 完成
return [
h('div', { style: { marginBottom: '16px', textAlign: 'center' } }, [
h('div', { style: { fontSize: '16px', color: '#00b42a', marginBottom: '8px' } }, '✓ 更新完成')
]),
h('div', { style: { fontSize: '14px', color: '#666' } }, '应用将在几秒后自动重启...')
]
}
}
/**
* 更新进度模态框内容
*/
const updateProgressModal = async () => {
if (!progressModalInstance) return
await nextTick()
// 使用响应式内容函数
progressModalInstance.update({
content: () => getProgressModalContent()
})
}
/**
* 显示进度模态框
*/
const showProgressModal = async () => {
if (progressModalInstance) {
progressModalInstance.close()
progressModalInstance = null
}
// 重置状态
resetDownloadState()
progressModalInstance = Modal.info({
title: '更新进度',
content: () => getProgressModalContent(),
closable: false,
maskClosable: false,
footer: false
})
await nextTick()
const stopWatcher = watch(
[downloadProgress, downloading, installing, totalSize, downloadedSize, downloadSpeed],
() => nextTick(updateProgressModal),
{ immediate: true, flush: 'post' }
)
if (progressModalInstance) {
(progressModalInstance as any)._stopWatcher = stopWatcher
}
}
/**
* 重置下载状态
*/
const resetDownloadState = () => {
downloading.value = true
installing.value = false
downloadProgress.value = 0
downloadSpeed.value = 0
downloadedSize.value = 0
totalSize.value = 0
installStatus.value = ''
}
/**
* 关闭进度模态框
*/
const closeProgressModal = () => {
if (progressModalInstance) {
// 停止 watcher
if ((progressModalInstance as any)._stopWatcher) {
(progressModalInstance as any)._stopWatcher()
delete (progressModalInstance as any)._stopWatcher
}
progressModalInstance.close()
progressModalInstance = null
}
}
/**
* 下载更新包
*/
const downloadUpdate = async (): Promise<void> => {
if (!updateInfo.value) return
await showProgressModal()
try {
const result = await window.go.main.App.DownloadUpdate(updateInfo.value.download_url) as ApiResponse
if (!result?.success) {
throw new Error(result?.message || '下载启动失败')
}
} catch (error: any) {
closeProgressModal()
Message.error('下载失败:' + error.message)
} finally {
// 确保无论成功失败都重置状态
downloading.value = false
}
}
/**
* 处理下载进度事件
*/
const handleDownloadProgress = (progressData: string) => {
if (!progressData) return
try {
const data = JSON.parse(progressData)
downloadProgress.value = clampProgress(Number(data.progress) || 0)
downloadSpeed.value = Math.max(0, Number(data.speed) || 0)
downloadedSize.value = Math.max(0, Number(data.downloaded) || 0)
totalSize.value = Math.max(0, Number(data.total) || 0)
} catch (error) {
console.error('[进度] 解析失败:', error)
}
}
/**
* 处理下载完成事件
*/
const handleDownloadComplete = async (resultData: string) => {
try {
const data = JSON.parse(resultData)
if (data.error) {
closeProgressModal()
Message.error('下载失败:' + data.error)
return
}
if (!data.success || !data.file_path) {
closeProgressModal()
Message.error('下载完成但数据不完整')
return
}
// 下载成功设置100%
downloadProgress.value = 100
downloadedSize.value = data.file_size || 0
totalSize.value = data.file_size || 0
await nextTick(updateProgressModal)
await new Promise(r => setTimeout(r, 800))
// 开始安装
await installUpdate(data.file_path)
} catch (error: any) {
console.error('处理下载完成事件失败:', error)
closeProgressModal()
}
}
/**
* 安装更新
*/
const installUpdate = async (filePath: string) => {
downloading.value = false
installing.value = true
installStatus.value = '正在安装更新包...'
updateProgressModal()
try {
const result = await window.go.main.App.InstallUpdate(filePath, true)
if (result?.success) {
installStatus.value = '安装成功'
updateProgressModal()
setTimeout(() => closeProgressModal(), 3000)
} else {
installing.value = false
installStatus.value = `安装失败: ${result?.message || '未知错误'}`
updateProgressModal()
Message.error('安装失败:' + (result?.message || '未知错误'))
}
} catch (error: any) {
installing.value = false
installStatus.value = `安装异常: ${error.message}`
updateProgressModal()
Message.error('安装失败:' + error.message)
}
}
// ==================== 生命周期 ====================
let unsubscribeProgress: (() => void) | null = null
let unsubscribeComplete: (() => void) | null = null
/**
* 应用启动时加载
*/
onMounted(async () => {
await loadCurrentVersion()
await loadUpdateConfig()
// 监听下载进度事件(确保在下载开始前注册)
unsubscribeProgress = EventsOn('download-progress', (data: string) => {
handleDownloadProgress(data)
})
unsubscribeComplete = EventsOn('download-complete', (data: string) => {
handleDownloadComplete(data)
})
// 如果启用了自动检查,自动检查更新
if (autoCheckEnabled.value) {
setTimeout(() => {
checkUpdate()
}, 1000)
}
})
/**
* 组件卸载时清理事件监听
*/
onUnmounted(() => {
if (unsubscribeProgress) {
unsubscribeProgress()
unsubscribeProgress = null
}
if (unsubscribeComplete) {
unsubscribeComplete()
unsubscribeComplete = null
}
})
// ==================== 返回公共接口 ====================
return {
// 状态
currentVersion,
autoCheckEnabled,
updateInfo,
// 方法
loadCurrentVersion,
checkUpdate,
downloadUpdate
}
}

9
web/src/main.js Normal file
View File

@@ -0,0 +1,9 @@
import { createApp } from 'vue'
import ArcoVue from '@arco-design/web-vue'
import '@arco-design/web-vue/dist/arco.css'
import './style.css'
import App from './App.vue'
const app = createApp(App)
app.use(ArcoVue)
app.mount('#app')

18
web/src/style.css Normal file
View File

@@ -0,0 +1,18 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB',
'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
overflow-x: hidden;
}
#app {
width: 100%;
height: 100vh;
}

View File

@@ -0,0 +1,96 @@
<template>
<a-card>
<a-form :model="formData" layout="vertical" @submit="handleSubmit">
<a-form-item
label="授权码"
:validate-status="error ? 'error' : ''"
:help="error || '请输入授权码至少16位字母和数字'"
>
<a-input
v-model="formData.licenseCode"
placeholder="请输入授权码"
:max-length="100"
allow-clear
@input="handleInput"
/>
</a-form-item>
<a-form-item>
<a-space>
<a-button type="primary" @click="handleSubmit" :loading="loading">
激活
</a-button>
<a-button @click="handleReset">重置</a-button>
</a-space>
</a-form-item>
</a-form>
</a-card>
</template>
<script setup>
import { ref } from 'vue'
import { Message } from '@arco-design/web-vue'
import { ActivateLicense } from '../../wailsjs/go/main/App'
const emit = defineEmits(['activated', 'reset'])
const formData = ref({
licenseCode: ''
})
const loading = ref(false)
const error = ref('')
const handleInput = () => {
error.value = ''
}
const handleSubmit = async () => {
if (!formData.value.licenseCode || formData.value.licenseCode.trim() === '') {
error.value = '授权码不能为空'
return
}
const cleaned = formData.value.licenseCode.replace(/[\s-]/g, '')
if (cleaned.length < 16) {
error.value = '授权码长度不足至少需要16位字符'
return
}
loading.value = true
error.value = ''
try {
const result = await ActivateLicense(formData.value.licenseCode)
if (result.success) {
Message.success(result.message || '激活成功')
emit('activated', result.data)
handleReset()
} else {
error.value = result.message || '激活失败'
Message.error(result.message || '激活失败')
}
} catch (err) {
error.value = err.message || '激活失败,请重试'
Message.error('激活失败:' + (err.message || '未知错误'))
} finally {
loading.value = false
}
}
const handleReset = () => {
formData.value.licenseCode = ''
error.value = ''
emit('reset')
}
defineExpose({
setLoading: (val) => {
loading.value = val
}
})
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,42 @@
<template>
<div class="auth-page">
<div class="container">
<a-row :gutter="12">
<a-col :span="12">
<ActivateForm @activated="handleActivated" />
</a-col>
<a-col :span="12">
<AuthStatus ref="authStatusRef" />
</a-col>
</a-row>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import ActivateForm from './ActivateForm.vue'
import AuthStatus from './AuthStatus.vue'
const authStatusRef = ref(null)
const handleActivated = () => {
if (authStatusRef.value) {
authStatusRef.value.refresh()
}
}
</script>
<style scoped>
.auth-page {
width: 100%;
height: 100%;
padding: 12px;
overflow: auto;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
</style>

View File

@@ -0,0 +1,104 @@
<template>
<a-card>
<template #title>授权状态</template>
<a-descriptions :column="1" bordered v-if="authStatus">
<a-descriptions-item label="激活状态">
<a-tag :color="authStatus.is_activated ? 'green' : 'red'">
{{ authStatus.is_activated ? '已激活' : '未激活' }}
</a-tag>
</a-descriptions-item>
<a-descriptions-item label="状态信息">
{{ authStatus.message }}
</a-descriptions-item>
<a-descriptions-item label="授权码" v-if="authStatus.license_code">
{{ formatLicenseCode(authStatus.license_code) }}
</a-descriptions-item>
<a-descriptions-item label="激活时间" v-if="authStatus.activated_at">
{{ formatDate(authStatus.activated_at) }}
</a-descriptions-item>
<a-descriptions-item label="过期时间" v-if="authStatus.expires_at">
{{ formatDate(authStatus.expires_at) }}
</a-descriptions-item>
<a-descriptions-item label="设备ID">
<a-typography-text copyable>{{ deviceID }}</a-typography-text>
</a-descriptions-item>
</a-descriptions>
<a-empty v-else description="加载中..." />
<template #actions>
<a-button @click="handleRefresh" :loading="loading">刷新状态</a-button>
</template>
</a-card>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { Message } from '@arco-design/web-vue'
import { GetAuthStatus, GetDeviceID } from '../../wailsjs/go/main/App'
const authStatus = ref(null)
const deviceID = ref('')
const loading = ref(false)
const formatLicenseCode = (code) => {
if (!code) return ''
const cleaned = code.replace(/[\s-]/g, '')
return cleaned.match(/.{1,4}/g)?.join('-') || cleaned
}
const formatDate = (dateStr) => {
if (!dateStr) return '-'
try {
const date = new Date(dateStr)
return date.toLocaleString('zh-CN')
} catch {
return dateStr
}
}
const loadAuthStatus = async () => {
loading.value = true
try {
const [statusResult, deviceResult] = await Promise.all([
GetAuthStatus(),
GetDeviceID()
])
if (statusResult.success) {
authStatus.value = statusResult.data
} else {
Message.error(statusResult.message || '获取授权状态失败')
}
if (deviceResult) {
deviceID.value = deviceResult
}
} catch (err) {
Message.error('获取授权状态失败:' + (err.message || '未知错误'))
} finally {
loading.value = false
}
}
const handleRefresh = () => {
loadAuthStatus()
}
onMounted(() => {
loadAuthStatus()
})
defineExpose({
refresh: loadAuthStatus
})
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,134 @@
<template>
<a-card>
<template #title>数据备份与恢复</template>
<a-space direction="vertical" style="width: 100%">
<!-- 操作按钮 -->
<a-space>
<a-button type="primary" @click="handleBackup" :loading="backing">
创建备份
</a-button>
<a-button @click="handleRefreshList" :loading="loading">
刷新列表
</a-button>
</a-space>
<!-- 备份列表 -->
<a-table
v-if="backups.length > 0"
:columns="columns"
:data="backups"
:pagination="{ pageSize: 10 }"
>
<template #operation="{ record }">
<a-space>
<a-button type="primary" size="small" @click="handleRestore(record)">
恢复
</a-button>
</a-space>
</template>
</a-table>
<a-empty v-else description="暂无备份文件" />
<!-- 恢复确认对话框 -->
<a-modal
v-model:visible="restoreVisible"
title="确认恢复"
@ok="confirmRestore"
@cancel="cancelRestore"
>
<p>确定要恢复此备份吗恢复后将替换当前数据库此操作不可逆</p>
<p><strong>备份文件</strong>{{ selectedBackup?.file_name }}</p>
<p><strong>创建时间</strong>{{ selectedBackup?.created_at }}</p>
</a-modal>
</a-space>
</a-card>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { Message, Modal } from '@arco-design/web-vue'
import { BackupData, RestoreData, ListBackups } from '../../wailsjs/go/main/App'
const backups = ref([])
const loading = ref(false)
const backing = ref(false)
const restoreVisible = ref(false)
const selectedBackup = ref(null)
const columns = [
{ title: '文件名', dataIndex: 'file_name', width: 250 },
{ title: '文件大小', dataIndex: 'file_size', width: 120, slotName: 'size' },
{ title: '创建时间', dataIndex: 'created_at', width: 180 },
{ title: '操作', slotName: 'operation', width: 100 }
]
// 加载备份列表
const loadBackups = async () => {
loading.value = true
try {
const result = await ListBackups()
backups.value = result.backups || []
} catch (error) {
console.error('获取备份列表失败:', error)
Message.error('获取备份列表失败')
} finally {
loading.value = false
}
}
// 创建备份
const handleBackup = async () => {
backing.value = true
try {
const result = await BackupData()
Message.success(`备份创建成功: ${result.file_name}`)
await loadBackups()
} catch (error) {
console.error('备份失败:', error)
Message.error('备份失败:' + (error.message || '未知错误'))
} finally {
backing.value = false
}
}
// 恢复备份
const handleRestore = (backup) => {
selectedBackup.value = backup
restoreVisible.value = true
}
// 确认恢复
const confirmRestore = async () => {
if (!selectedBackup.value) {
return
}
try {
await RestoreData(selectedBackup.value.backup_path)
Message.success('数据恢复成功')
restoreVisible.value = false
selectedBackup.value = null
} catch (error) {
console.error('恢复失败:', error)
Message.error('恢复失败:' + (error.message || '未知错误'))
}
}
// 取消恢复
const cancelRestore = () => {
restoreVisible.value = false
selectedBackup.value = null
}
// 刷新列表
const handleRefreshList = () => {
loadBackups()
}
onMounted(() => {
loadBackups()
})
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,48 @@
<template>
<a-card>
<template #title>
<span>数据统计</span>
<a-button type="text" size="small" @click="handleRefresh" style="margin-left: 10px">
刷新
</a-button>
</template>
<a-descriptions :column="2" bordered>
<a-descriptions-item label="数据总量">
{{ stats?.total_count || 0 }}
</a-descriptions-item>
<a-descriptions-item label="最新期号">
{{ stats?.latest_issue || '-' }}
</a-descriptions-item>
</a-descriptions>
</a-card>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { Message } from '@arco-design/web-vue'
import { GetDataStats } from '../../wailsjs/go/main/App'
const stats = ref(null)
const loadStats = async () => {
try {
const data = await GetDataStats()
stats.value = data
} catch (error) {
console.error('获取统计数据失败:', error)
Message.error('获取统计数据失败')
}
}
const handleRefresh = async () => {
await loadStats()
Message.success('统计数据已刷新')
}
onMounted(() => {
loadStats()
})
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,182 @@
<template>
<a-card>
<template #title>离线数据包管理</template>
<a-space direction="vertical" style="width: 100%">
<!-- 检查更新 -->
<a-space>
<a-input
v-model="remoteURL"
placeholder="输入数据包信息 URL"
style="width: 400px"
/>
<a-button type="primary" @click="handleCheckUpdate" :loading="checking">
检查更新
</a-button>
</a-space>
<!-- 更新信息 -->
<a-alert v-if="updateInfo" :type="updateInfo.need_update ? 'info' : 'success'">
<template #title>{{ updateInfo.need_update ? '发现新数据包' : '已是最新版本' }}</template>
<div v-if="updateInfo.need_update">
<p>版本{{ updateInfo.version }}</p>
<p>数据总数{{ updateInfo.total_count }}</p>
<p>最新期号{{ updateInfo.latest_issue }}</p>
<p>文件大小{{ formatFileSize(updateInfo.package_size) }}</p>
<p>发布日期{{ updateInfo.release_date }}</p>
<a-button type="primary" @click="handleDownload" :loading="downloading" style="margin-top: 10px">
下载数据包
</a-button>
</div>
</a-alert>
<!-- 下载进度 -->
<a-progress
v-if="downloadProgress > 0 && downloadProgress < 100"
:percent="downloadProgress"
:status="downloadStatus"
/>
<!-- 本地数据包列表 -->
<a-divider />
<a-space>
<a-button @click="handleRefreshList" :loading="loading">刷新列表</a-button>
</a-space>
<a-table
v-if="packages.length > 0"
:columns="columns"
:data="packages"
:pagination="{ pageSize: 10 }"
>
<template #operation="{ record }">
<a-space>
<a-button type="primary" size="small" @click="handleImport(record)">
导入
</a-button>
</a-space>
</template>
</a-table>
<a-empty v-else description="暂无本地数据包" />
</a-space>
</a-card>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { Message } from '@arco-design/web-vue'
import { DownloadPackage, ImportPackage, CheckPackageUpdate, ListLocalPackages } from '../../wailsjs/go/main/App'
const remoteURL = ref('')
const checking = ref(false)
const downloading = ref(false)
const loading = ref(false)
const updateInfo = ref(null)
const downloadProgress = ref(0)
const downloadStatus = ref('normal')
const packages = ref([])
const columns = [
{ title: '文件名', dataIndex: 'name', width: 300 },
{ title: '文件路径', dataIndex: 'path', width: 400 },
{ title: '操作', slotName: 'operation', width: 100 }
]
// 格式化文件大小
const formatFileSize = (bytes) => {
if (!bytes) return '0 B'
const k = 1024
const sizes = ['B', 'KB', 'MB', 'GB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i]
}
// 检查更新
const handleCheckUpdate = async () => {
if (!remoteURL.value) {
Message.warning('请输入数据包信息 URL')
return
}
checking.value = true
try {
const result = await CheckPackageUpdate(remoteURL.value)
updateInfo.value = result
if (result.need_update) {
Message.success('发现新数据包')
} else {
Message.success('已是最新版本')
}
} catch (error) {
console.error('检查更新失败:', error)
Message.error('检查更新失败:' + (error.message || '未知错误'))
} finally {
checking.value = false
}
}
// 下载数据包
const handleDownload = async () => {
if (!updateInfo.value?.download_url) {
Message.warning('下载地址不存在')
return
}
downloading.value = true
downloadProgress.value = 0
downloadStatus.value = 'active'
try {
const result = await DownloadPackage(updateInfo.value.download_url)
downloadProgress.value = 100
downloadStatus.value = 'success'
Message.success('数据包下载成功')
await loadPackages()
} catch (error) {
console.error('下载失败:', error)
downloadStatus.value = 'exception'
Message.error('下载失败:' + (error.message || '未知错误'))
} finally {
downloading.value = false
}
}
// 导入数据包
const handleImport = async (pkg) => {
try {
const result = await ImportPackage(pkg.path)
Message.success(`导入成功:导入 ${result.imported_count} 条数据`)
} catch (error) {
console.error('导入失败:', error)
Message.error('导入失败:' + (error.message || '未知错误'))
}
}
// 加载本地数据包列表
const loadPackages = async () => {
loading.value = true
try {
const result = await ListLocalPackages()
packages.value = (result.packages || []).map(path => ({
name: path.split(/[/\\]/).pop(),
path: path
}))
} catch (error) {
console.error('获取数据包列表失败:', error)
Message.error('获取数据包列表失败')
} finally {
loading.value = false
}
}
// 刷新列表
const handleRefreshList = () => {
loadPackages()
}
onMounted(() => {
loadPackages()
})
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,107 @@
<template>
<a-card>
<template #title>数据同步</template>
<a-space direction="vertical" style="width: 100%">
<!-- 同步状态 -->
<a-descriptions :column="2" bordered>
<a-descriptions-item label="本地数据量">
{{ syncStatus?.local_count || 0 }}
</a-descriptions-item>
<a-descriptions-item label="本地最新期号">
{{ syncStatus?.local_latest_issue || '-' }}
</a-descriptions-item>
<a-descriptions-item label="远程数据量">
{{ syncStatus?.remote_count || 0 }}
</a-descriptions-item>
<a-descriptions-item label="远程最新期号">
{{ syncStatus?.remote_latest_issue || '-' }}
</a-descriptions-item>
<a-descriptions-item label="同步状态" :span="2">
<a-tag :color="syncStatus?.need_sync ? 'orange' : 'green'">
{{ syncStatus?.need_sync ? '需要同步' : '已是最新' }}
</a-tag>
</a-descriptions-item>
</a-descriptions>
<!-- 操作按钮 -->
<a-space>
<a-button type="primary" @click="handleSync" :loading="syncing">
开始同步
</a-button>
<a-button @click="handleRefreshStatus" :loading="refreshing">
刷新状态
</a-button>
</a-space>
<!-- 同步结果 -->
<a-alert v-if="syncResult" :type="syncResult.error_count > 0 ? 'warning' : 'success'">
<template #title>同步完成</template>
<div>总数据量{{ syncResult.total_count }}</div>
<div>同步数量{{ syncResult.synced_count }}</div>
<div>新增数量{{ syncResult.new_count }}</div>
<div>更新数量{{ syncResult.updated_count }}</div>
<div v-if="syncResult.error_count > 0">错误数量{{ syncResult.error_count }}</div>
<div v-if="syncResult.latest_issue">最新期号{{ syncResult.latest_issue }}</div>
</a-alert>
</a-space>
</a-card>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { Message } from '@arco-design/web-vue'
import { SyncData, GetSyncStatus } from '../../wailsjs/go/main/App'
const syncStatus = ref(null)
const syncing = ref(false)
const refreshing = ref(false)
const syncResult = ref(null)
// 加载同步状态
const loadSyncStatus = async () => {
try {
const status = await GetSyncStatus()
syncStatus.value = status
} catch (error) {
console.error('获取同步状态失败:', error)
Message.error('获取同步状态失败')
}
}
// 执行同步
const handleSync = async () => {
syncing.value = true
syncResult.value = null
try {
const result = await SyncData()
syncResult.value = result
Message.success('同步完成')
// 同步后刷新状态
await loadSyncStatus()
} catch (error) {
console.error('同步失败:', error)
Message.error('同步失败:' + (error.message || '未知错误'))
} finally {
syncing.value = false
}
}
// 刷新状态
const handleRefreshStatus = async () => {
refreshing.value = true
try {
await loadSyncStatus()
Message.success('状态已刷新')
} finally {
refreshing.value = false
}
}
onMounted(() => {
loadSyncStatus()
})
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,179 @@
<template>
<a-card>
<template #title>查询条件</template>
<a-form :model="formData" layout="vertical">
<!-- 红球输入 -->
<a-form-item label="红球号码" class="inline-form-item">
<div class="red-balls">
<a-input-number
v-for="(ball, index) in redBalls"
:key="index"
v-model="redBalls[index]"
:min="1"
:max="33"
:precision="0"
placeholder="红球"
class="red-ball-input"
/>
</div>
</a-form-item>
<!-- 蓝球输入 -->
<a-form-item label="蓝球号码" class="inline-form-item">
<a-input-number
v-model="formData.blueBall"
:min="1"
:max="16"
:precision="0"
placeholder="蓝球(不填表示不限制)"
style="width: 200px"
:allow-clear="true"
/>
</a-form-item>
<!-- 蓝球筛选 -->
<a-form-item label="蓝球筛选范围">
<div class="blue-ball-filter">
<div class="blue-ball-item">
<a-checkbox v-model="selectAll" @change="handleSelectAll" />
<span class="blue-ball-label">全选</span>
</div>
<a-checkbox-group v-model="formData.blueBallRange" class="blue-checkboxes">
<div v-for="i in 16" :key="i" class="blue-ball-item">
<a-checkbox :value="i" />
<span class="blue-ball-label">蓝球{{ i }}</span>
</div>
</a-checkbox-group>
</div>
</a-form-item>
<!-- 操作按钮 -->
<a-form-item>
<a-space>
<a-button type="primary" @click="handleQuery" :loading="loading">查询</a-button>
<a-button @click="handleReset">重置</a-button>
</a-space>
</a-form-item>
</a-form>
</a-card>
</template>
<script setup>
import { ref, watch, computed } from 'vue'
const emit = defineEmits(['query', 'reset'])
const formData = ref({
blueBall: undefined,
blueBallRange: []
})
const redBalls = ref([null, null, null, null, null, null])
const loading = ref(false)
const selectAll = ref(true)
// 全选逻辑
const handleSelectAll = (checked) => {
if (checked) {
formData.value.blueBallRange = Array.from({ length: 16 }, (_, i) => i + 1)
} else {
formData.value.blueBallRange = []
}
}
// 监听蓝球筛选变化
watch(() => formData.value.blueBallRange, (newVal) => {
selectAll.value = newVal.length === 16
}, { deep: true })
// 查询
const handleQuery = () => {
const redBallsFiltered = redBalls.value.filter(ball => ball !== null && ball > 0)
emit('query', {
redBalls: redBallsFiltered,
blueBall: formData.value.blueBall || 0,
blueBallRange: formData.value.blueBallRange.length > 0 ? formData.value.blueBallRange : []
})
}
// 重置
const handleReset = () => {
redBalls.value = [null, null, null, null, null, null]
formData.value.blueBall = undefined
formData.value.blueBallRange = Array.from({ length: 16 }, (_, i) => i + 1)
selectAll.value = true
emit('reset')
}
defineExpose({
setLoading: (val) => {
loading.value = val
}
})
</script>
<style scoped>
:deep(.inline-form-item) {
display: flex;
align-items: center;
margin-bottom: 8px;
}
:deep(.arco-form-item) {
margin-bottom: 8px;
}
:deep(.inline-form-item .arco-form-item-label) {
margin-bottom: 0 !important;
margin-right: 12px;
padding-right: 12px;
flex-shrink: 0;
width: auto;
line-height: 32px;
}
:deep(.inline-form-item .arco-form-item-content) {
flex: 1;
display: flex;
align-items: center;
}
.red-balls {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.red-ball-input {
width: 90px;
}
.blue-ball-filter {
display: flex;
flex-wrap: wrap;
gap: 12px;
align-items: flex-start;
}
.blue-ball-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
min-width: 50px;
}
.blue-ball-label {
font-size: 12px;
color: var(--color-text-2);
text-align: center;
line-height: 1.2;
}
.blue-checkboxes {
display: flex;
flex-wrap: wrap;
gap: 12px;
align-items: flex-start;
}
</style>

View File

@@ -0,0 +1,102 @@
<template>
<div class="query-page">
<div class="container">
<!-- 查询条件 -->
<QueryForm
ref="queryFormRef"
@query="handleQuery"
@reset="handleReset"
/>
<!-- 查询结果 -->
<ResultPanel
v-if="queryResult"
:summary="queryResult.summary || []"
:details="queryResult.details || []"
:query-red-balls="currentQuery.redBalls"
:query-blue-ball="currentQuery.blueBall"
:query-blue-ball-range="currentQuery.blueBallRange"
@summary-click="handleSummaryClick"
style="margin-top: 12px"
/>
<!-- 加载中 -->
<a-spin v-if="loading" :style="{ width: '100%', marginTop: '12px' }" />
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { Message } from '@arco-design/web-vue'
import QueryForm from './QueryForm.vue'
import ResultPanel from './ResultPanel.vue'
import { QueryHistory } from '../../wailsjs/go/main/App'
const queryFormRef = ref(null)
const loading = ref(false)
const queryResult = ref(null)
const currentQuery = ref({
redBalls: [],
blueBall: 0,
blueBallRange: []
})
// 查询
const handleQuery = async (queryParams) => {
if (!queryParams.redBalls || queryParams.redBalls.length === 0) {
Message.warning('请至少输入一个红球号码')
return
}
loading.value = true
currentQuery.value = queryParams
try {
const result = await QueryHistory({
red_balls: queryParams.redBalls,
blue_ball: queryParams.blueBall,
blue_ball_range: queryParams.blueBallRange
})
if (result) {
queryResult.value = result
Message.success('查询成功')
}
} catch (error) {
console.error('查询失败:', error)
Message.error('查询失败:' + (error.message || '未知错误'))
} finally {
loading.value = false
}
}
// 重置
const handleReset = () => {
queryResult.value = null
currentQuery.value = {
redBalls: [],
blueBall: 0,
blueBallRange: []
}
}
// 点击汇总项
const handleSummaryClick = (item) => {
console.log('点击汇总项:', item)
}
</script>
<style scoped>
.query-page {
width: 100%;
height: 100%;
padding: 12px;
overflow: auto;
}
.container {
max-width: 1400px;
margin: 0 auto;
}
</style>

View File

@@ -0,0 +1,198 @@
<template>
<a-layout class="result-layout">
<!-- 左侧汇总列表 -->
<a-layout-sider width="280" class="summary-sider">
<a-card>
<template #title>查询汇总</template>
<a-list v-if="summary.length > 0" :data="summary">
<template #item="{ item }">
<a-list-item class="summary-item" @click="handleSummaryClick(item)">
<a-list-item-meta>
<template #title>
<span>{{ item.type }}{{ item.count }}</span>
</template>
</a-list-item-meta>
<template #actions>
<a-button type="text" size="small">显示历史开奖</a-button>
</template>
</a-list-item>
</template>
</a-list>
<a-empty v-else description="暂无数据" />
</a-card>
</a-layout-sider>
<!-- 右侧详情列表 -->
<a-layout-content class="detail-content">
<a-card>
<template #title>
<span>查询结果详情</span>
<a-button v-if="selectedSummary" type="text" size="small" @click="clearSelection" style="margin-left: 8px">
清除筛选
</a-button>
</template>
<a-table
v-if="displayDetails.length > 0"
:columns="columns"
:data="displayDetails"
:pagination="paginationConfig"
size="mini"
row-key="id"
@page-change="handlePageChange"
@page-size-change="handlePageSizeChange"
>
<template #ball="{ record, column }">
<span
:style="getBallStyle(record, column.dataIndex)"
>
{{ record[column.dataIndex] }}
</span>
</template>
</a-table>
<a-empty v-else description="暂无数据" />
</a-card>
</a-layout-content>
</a-layout>
</template>
<script setup>
import { ref, computed } from 'vue'
const props = defineProps({
summary: {
type: Array,
default: () => []
},
details: {
type: Array,
default: () => []
},
queryRedBalls: {
type: Array,
default: () => []
},
queryBlueBall: {
type: Number,
default: 0
},
queryBlueBallRange: {
type: Array,
default: () => []
}
})
const emit = defineEmits(['summary-click'])
const selectedSummary = ref(null)
const pageSize = ref(20)
// 分页配置
const paginationConfig = computed(() => ({
pageSize: pageSize.value,
pageSizeOptions: [20, 30, 50, 100, 200],
showPageSize: true,
showTotal: (total) => `${total} 条记录`
}))
// 表格列定义
const columns = [
{ title: '期号', dataIndex: 'issue_number', align: 'center' },
{ title: '红球1', dataIndex: 'red_ball_1', slotName: 'ball', align: 'center' },
{ title: '红球2', dataIndex: 'red_ball_2', slotName: 'ball', align: 'center' },
{ title: '红球3', dataIndex: 'red_ball_3', slotName: 'ball', align: 'center' },
{ title: '红球4', dataIndex: 'red_ball_4', slotName: 'ball', align: 'center' },
{ title: '红球5', dataIndex: 'red_ball_5', slotName: 'ball', align: 'center' },
{ title: '红球6', dataIndex: 'red_ball_6', slotName: 'ball', align: 'center' },
{ title: '蓝球', dataIndex: 'blue_ball', slotName: 'ball', align: 'center' }
]
// 显示的数据
const displayDetails = computed(() => {
if (selectedSummary.value) {
return selectedSummary.value.histories || []
}
return props.details
})
// 点击汇总项
const handleSummaryClick = (item) => {
selectedSummary.value = item
emit('summary-click', item)
}
// 清除筛选
const clearSelection = () => {
selectedSummary.value = null
}
// 分页变化
const handlePageChange = (page) => {
// 页面变化处理(如果需要)
}
// 分页大小变化
const handlePageSizeChange = (size) => {
pageSize.value = size
}
// 获取球的样式
const getBallStyle = (record, field) => {
if (field.startsWith('red_ball_')) {
const ballValue = record[field]
// 检查是否在查询的红球列表中
if (props.queryRedBalls.includes(ballValue)) {
return { color: '#F53F3F', fontWeight: 'bold' }
}
} else if (field === 'blue_ball') {
const ballValue = record[field]
// 检查是否匹配查询的蓝球(精确匹配或在筛选范围内)
if (props.queryBlueBall > 0 && ballValue === props.queryBlueBall) {
return { color: '#165DFF', fontWeight: 'bold' }
}
// 检查是否在蓝球筛选范围内
if (props.queryBlueBallRange.length > 0 && props.queryBlueBallRange.includes(ballValue)) {
return { color: '#165DFF', fontWeight: 'bold' }
}
}
return {}
}
</script>
<style scoped>
.result-layout {
height: 100%;
}
.summary-sider {
background: var(--color-bg-1);
border-right: 1px solid var(--color-border);
}
.summary-item {
cursor: pointer;
transition: background 0.2s;
}
.summary-item:hover {
background: var(--color-fill-2);
}
.detail-content {
padding: 0;
background: var(--color-bg-1);
}
:deep(.arco-card-body) {
padding: 12px;
}
:deep(.arco-table) {
width: 100%;
min-width: 0;
}
:deep(.arco-table table) {
width: 100%;
min-width: 0;
}
</style>

47
web/src/wailsjs/go/main/App.d.ts vendored Normal file
View File

@@ -0,0 +1,47 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
import {api} from '../models';
export function ActivateLicense(arg1:string):Promise<Record<string, any>>;
export function BackupData():Promise<Record<string, any>>;
export function CheckPackageUpdate(arg1:string):Promise<Record<string, any>>;
export function CheckUpdate():Promise<Record<string, any>>;
export function DownloadPackage(arg1:string):Promise<Record<string, any>>;
export function DownloadUpdate(arg1:string):Promise<Record<string, any>>;
export function GetAuthStatus():Promise<Record<string, any>>;
export function GetCurrentVersion():Promise<Record<string, any>>;
export function GetDataStats():Promise<Record<string, any>>;
export function GetDeviceID():Promise<string>;
export function GetSyncStatus():Promise<Record<string, any>>;
export function GetUpdateConfig():Promise<Record<string, any>>;
export function Greet(arg1:string):Promise<string>;
export function ImportPackage(arg1:string):Promise<Record<string, any>>;
export function InstallUpdate(arg1:string,arg2:boolean):Promise<Record<string, any>>;
export function ListBackups():Promise<Record<string, any>>;
export function ListLocalPackages():Promise<Record<string, any>>;
export function QueryHistory(arg1:api.QueryRequest):Promise<Record<string, any>>;
export function RestoreData(arg1:string):Promise<Record<string, any>>;
export function SetUpdateConfig(arg1:boolean,arg2:number,arg3:string):Promise<Record<string, any>>;
export function SyncData():Promise<Record<string, any>>;
export function VerifyUpdateFile(arg1:string,arg2:string,arg3:string):Promise<Record<string, any>>;

View File

@@ -0,0 +1,91 @@
// @ts-check
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
export function ActivateLicense(arg1) {
return window['go']['main']['App']['ActivateLicense'](arg1);
}
export function BackupData() {
return window['go']['main']['App']['BackupData']();
}
export function CheckPackageUpdate(arg1) {
return window['go']['main']['App']['CheckPackageUpdate'](arg1);
}
export function CheckUpdate() {
return window['go']['main']['App']['CheckUpdate']();
}
export function DownloadPackage(arg1) {
return window['go']['main']['App']['DownloadPackage'](arg1);
}
export function DownloadUpdate(arg1) {
return window['go']['main']['App']['DownloadUpdate'](arg1);
}
export function GetAuthStatus() {
return window['go']['main']['App']['GetAuthStatus']();
}
export function GetCurrentVersion() {
return window['go']['main']['App']['GetCurrentVersion']();
}
export function GetDataStats() {
return window['go']['main']['App']['GetDataStats']();
}
export function GetDeviceID() {
return window['go']['main']['App']['GetDeviceID']();
}
export function GetSyncStatus() {
return window['go']['main']['App']['GetSyncStatus']();
}
export function GetUpdateConfig() {
return window['go']['main']['App']['GetUpdateConfig']();
}
export function Greet(arg1) {
return window['go']['main']['App']['Greet'](arg1);
}
export function ImportPackage(arg1) {
return window['go']['main']['App']['ImportPackage'](arg1);
}
export function InstallUpdate(arg1, arg2) {
return window['go']['main']['App']['InstallUpdate'](arg1, arg2);
}
export function ListBackups() {
return window['go']['main']['App']['ListBackups']();
}
export function ListLocalPackages() {
return window['go']['main']['App']['ListLocalPackages']();
}
export function QueryHistory(arg1) {
return window['go']['main']['App']['QueryHistory'](arg1);
}
export function RestoreData(arg1) {
return window['go']['main']['App']['RestoreData'](arg1);
}
export function SetUpdateConfig(arg1, arg2, arg3) {
return window['go']['main']['App']['SetUpdateConfig'](arg1, arg2, arg3);
}
export function SyncData() {
return window['go']['main']['App']['SyncData']();
}
export function VerifyUpdateFile(arg1, arg2, arg3) {
return window['go']['main']['App']['VerifyUpdateFile'](arg1, arg2, arg3);
}

View File

@@ -0,0 +1,21 @@
export namespace api {
export class QueryRequest {
red_balls: number[];
blue_ball: number;
blue_ball_range: number[];
static createFrom(source: any = {}) {
return new QueryRequest(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.red_balls = source["red_balls"];
this.blue_ball = source["blue_ball"];
this.blue_ball_range = source["blue_ball_range"];
}
}
}

View File

@@ -0,0 +1,24 @@
{
"name": "@wailsapp/runtime",
"version": "2.0.0",
"description": "Wails Javascript runtime library",
"main": "runtime.js",
"types": "runtime.d.ts",
"scripts": {
},
"repository": {
"type": "git",
"url": "git+https://github.com/wailsapp/wails.git"
},
"keywords": [
"Wails",
"Javascript",
"Go"
],
"author": "Lea Anthony <lea.anthony@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/wailsapp/wails/issues"
},
"homepage": "https://github.com/wailsapp/wails#readme"
}

249
web/src/wailsjs/runtime/runtime.d.ts vendored Normal file
View File

@@ -0,0 +1,249 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
export interface Position {
x: number;
y: number;
}
export interface Size {
w: number;
h: number;
}
export interface Screen {
isCurrent: boolean;
isPrimary: boolean;
width : number
height : number
}
// Environment information such as platform, buildtype, ...
export interface EnvironmentInfo {
buildType: string;
platform: string;
arch: string;
}
// [EventsEmit](https://wails.io/docs/reference/runtime/events#eventsemit)
// emits the given event. Optional data may be passed with the event.
// This will trigger any event listeners.
export function EventsEmit(eventName: string, ...data: any): void;
// [EventsOn](https://wails.io/docs/reference/runtime/events#eventson) sets up a listener for the given event name.
export function EventsOn(eventName: string, callback: (...data: any) => void): () => void;
// [EventsOnMultiple](https://wails.io/docs/reference/runtime/events#eventsonmultiple)
// sets up a listener for the given event name, but will only trigger a given number times.
export function EventsOnMultiple(eventName: string, callback: (...data: any) => void, maxCallbacks: number): () => void;
// [EventsOnce](https://wails.io/docs/reference/runtime/events#eventsonce)
// sets up a listener for the given event name, but will only trigger once.
export function EventsOnce(eventName: string, callback: (...data: any) => void): () => void;
// [EventsOff](https://wails.io/docs/reference/runtime/events#eventsoff)
// unregisters the listener for the given event name.
export function EventsOff(eventName: string, ...additionalEventNames: string[]): void;
// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
// unregisters all listeners.
export function EventsOffAll(): void;
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
// [LogTrace](https://wails.io/docs/reference/runtime/log#logtrace)
// logs the given message at the `trace` log level.
export function LogTrace(message: string): void;
// [LogDebug](https://wails.io/docs/reference/runtime/log#logdebug)
// logs the given message at the `debug` log level.
export function LogDebug(message: string): void;
// [LogError](https://wails.io/docs/reference/runtime/log#logerror)
// logs the given message at the `error` log level.
export function LogError(message: string): void;
// [LogFatal](https://wails.io/docs/reference/runtime/log#logfatal)
// logs the given message at the `fatal` log level.
// The application will quit after calling this method.
export function LogFatal(message: string): void;
// [LogInfo](https://wails.io/docs/reference/runtime/log#loginfo)
// logs the given message at the `info` log level.
export function LogInfo(message: string): void;
// [LogWarning](https://wails.io/docs/reference/runtime/log#logwarning)
// logs the given message at the `warning` log level.
export function LogWarning(message: string): void;
// [WindowReload](https://wails.io/docs/reference/runtime/window#windowreload)
// Forces a reload by the main application as well as connected browsers.
export function WindowReload(): void;
// [WindowReloadApp](https://wails.io/docs/reference/runtime/window#windowreloadapp)
// Reloads the application frontend.
export function WindowReloadApp(): void;
// [WindowSetAlwaysOnTop](https://wails.io/docs/reference/runtime/window#windowsetalwaysontop)
// Sets the window AlwaysOnTop or not on top.
export function WindowSetAlwaysOnTop(b: boolean): void;
// [WindowSetSystemDefaultTheme](https://wails.io/docs/next/reference/runtime/window#windowsetsystemdefaulttheme)
// *Windows only*
// Sets window theme to system default (dark/light).
export function WindowSetSystemDefaultTheme(): void;
// [WindowSetLightTheme](https://wails.io/docs/next/reference/runtime/window#windowsetlighttheme)
// *Windows only*
// Sets window to light theme.
export function WindowSetLightTheme(): void;
// [WindowSetDarkTheme](https://wails.io/docs/next/reference/runtime/window#windowsetdarktheme)
// *Windows only*
// Sets window to dark theme.
export function WindowSetDarkTheme(): void;
// [WindowCenter](https://wails.io/docs/reference/runtime/window#windowcenter)
// Centers the window on the monitor the window is currently on.
export function WindowCenter(): void;
// [WindowSetTitle](https://wails.io/docs/reference/runtime/window#windowsettitle)
// Sets the text in the window title bar.
export function WindowSetTitle(title: string): void;
// [WindowFullscreen](https://wails.io/docs/reference/runtime/window#windowfullscreen)
// Makes the window full screen.
export function WindowFullscreen(): void;
// [WindowUnfullscreen](https://wails.io/docs/reference/runtime/window#windowunfullscreen)
// Restores the previous window dimensions and position prior to full screen.
export function WindowUnfullscreen(): void;
// [WindowIsFullscreen](https://wails.io/docs/reference/runtime/window#windowisfullscreen)
// Returns the state of the window, i.e. whether the window is in full screen mode or not.
export function WindowIsFullscreen(): Promise<boolean>;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
export function WindowGetSize(): Promise<Size>;
// [WindowSetMaxSize](https://wails.io/docs/reference/runtime/window#windowsetmaxsize)
// Sets the maximum window size. Will resize the window if the window is currently larger than the given dimensions.
// Setting a size of 0,0 will disable this constraint.
export function WindowSetMaxSize(width: number, height: number): void;
// [WindowSetMinSize](https://wails.io/docs/reference/runtime/window#windowsetminsize)
// Sets the minimum window size. Will resize the window if the window is currently smaller than the given dimensions.
// Setting a size of 0,0 will disable this constraint.
export function WindowSetMinSize(width: number, height: number): void;
// [WindowSetPosition](https://wails.io/docs/reference/runtime/window#windowsetposition)
// Sets the window position relative to the monitor the window is currently on.
export function WindowSetPosition(x: number, y: number): void;
// [WindowGetPosition](https://wails.io/docs/reference/runtime/window#windowgetposition)
// Gets the window position relative to the monitor the window is currently on.
export function WindowGetPosition(): Promise<Position>;
// [WindowHide](https://wails.io/docs/reference/runtime/window#windowhide)
// Hides the window.
export function WindowHide(): void;
// [WindowShow](https://wails.io/docs/reference/runtime/window#windowshow)
// Shows the window, if it is currently hidden.
export function WindowShow(): void;
// [WindowMaximise](https://wails.io/docs/reference/runtime/window#windowmaximise)
// Maximises the window to fill the screen.
export function WindowMaximise(): void;
// [WindowToggleMaximise](https://wails.io/docs/reference/runtime/window#windowtogglemaximise)
// Toggles between Maximised and UnMaximised.
export function WindowToggleMaximise(): void;
// [WindowUnmaximise](https://wails.io/docs/reference/runtime/window#windowunmaximise)
// Restores the window to the dimensions and position prior to maximising.
export function WindowUnmaximise(): void;
// [WindowIsMaximised](https://wails.io/docs/reference/runtime/window#windowismaximised)
// Returns the state of the window, i.e. whether the window is maximised or not.
export function WindowIsMaximised(): Promise<boolean>;
// [WindowMinimise](https://wails.io/docs/reference/runtime/window#windowminimise)
// Minimises the window.
export function WindowMinimise(): void;
// [WindowUnminimise](https://wails.io/docs/reference/runtime/window#windowunminimise)
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
// [WindowIsMinimised](https://wails.io/docs/reference/runtime/window#windowisminimised)
// Returns the state of the window, i.e. whether the window is minimised or not.
export function WindowIsMinimised(): Promise<boolean>;
// [WindowIsNormal](https://wails.io/docs/reference/runtime/window#windowisnormal)
// Returns the state of the window, i.e. whether the window is normal or not.
export function WindowIsNormal(): Promise<boolean>;
// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [ScreenGetAll](https://wails.io/docs/reference/runtime/window#screengetall)
// Gets the all screens. Call this anew each time you want to refresh data from the underlying windowing system.
export function ScreenGetAll(): Promise<Screen[]>;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
export function Environment(): Promise<EnvironmentInfo>;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
export function Quit(): void;
// [Hide](https://wails.io/docs/reference/runtime/intro#hide)
// Hides the application.
export function Hide(): void;
// [Show](https://wails.io/docs/reference/runtime/intro#show)
// Shows the application.
export function Show(): void;
// [ClipboardGetText](https://wails.io/docs/reference/runtime/clipboard#clipboardgettext)
// Returns the current text stored on clipboard
export function ClipboardGetText(): Promise<string>;
// [ClipboardSetText](https://wails.io/docs/reference/runtime/clipboard#clipboardsettext)
// Sets a text on the clipboard
export function ClipboardSetText(text: string): Promise<boolean>;
// [OnFileDrop](https://wails.io/docs/reference/runtime/draganddrop#onfiledrop)
// OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings.
export function OnFileDrop(callback: (x: number, y: number ,paths: string[]) => void, useDropTarget: boolean) :void
// [OnFileDropOff](https://wails.io/docs/reference/runtime/draganddrop#dragandddropoff)
// OnFileDropOff removes the drag and drop listeners and handlers.
export function OnFileDropOff() :void
// Check if the file path resolver is available
export function CanResolveFilePaths(): boolean;
// Resolves file paths for an array of files
export function ResolveFilePaths(files: File[]): void

View File

@@ -0,0 +1,242 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
export function LogPrint(message) {
window.runtime.LogPrint(message);
}
export function LogTrace(message) {
window.runtime.LogTrace(message);
}
export function LogDebug(message) {
window.runtime.LogDebug(message);
}
export function LogInfo(message) {
window.runtime.LogInfo(message);
}
export function LogWarning(message) {
window.runtime.LogWarning(message);
}
export function LogError(message) {
window.runtime.LogError(message);
}
export function LogFatal(message) {
window.runtime.LogFatal(message);
}
export function EventsOnMultiple(eventName, callback, maxCallbacks) {
return window.runtime.EventsOnMultiple(eventName, callback, maxCallbacks);
}
export function EventsOn(eventName, callback) {
return EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName, ...additionalEventNames) {
return window.runtime.EventsOff(eventName, ...additionalEventNames);
}
export function EventsOffAll() {
return window.runtime.EventsOffAll();
}
export function EventsOnce(eventName, callback) {
return EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
let args = [eventName].slice.call(arguments);
return window.runtime.EventsEmit.apply(null, args);
}
export function WindowReload() {
window.runtime.WindowReload();
}
export function WindowReloadApp() {
window.runtime.WindowReloadApp();
}
export function WindowSetAlwaysOnTop(b) {
window.runtime.WindowSetAlwaysOnTop(b);
}
export function WindowSetSystemDefaultTheme() {
window.runtime.WindowSetSystemDefaultTheme();
}
export function WindowSetLightTheme() {
window.runtime.WindowSetLightTheme();
}
export function WindowSetDarkTheme() {
window.runtime.WindowSetDarkTheme();
}
export function WindowCenter() {
window.runtime.WindowCenter();
}
export function WindowSetTitle(title) {
window.runtime.WindowSetTitle(title);
}
export function WindowFullscreen() {
window.runtime.WindowFullscreen();
}
export function WindowUnfullscreen() {
window.runtime.WindowUnfullscreen();
}
export function WindowIsFullscreen() {
return window.runtime.WindowIsFullscreen();
}
export function WindowGetSize() {
return window.runtime.WindowGetSize();
}
export function WindowSetSize(width, height) {
window.runtime.WindowSetSize(width, height);
}
export function WindowSetMaxSize(width, height) {
window.runtime.WindowSetMaxSize(width, height);
}
export function WindowSetMinSize(width, height) {
window.runtime.WindowSetMinSize(width, height);
}
export function WindowSetPosition(x, y) {
window.runtime.WindowSetPosition(x, y);
}
export function WindowGetPosition() {
return window.runtime.WindowGetPosition();
}
export function WindowHide() {
window.runtime.WindowHide();
}
export function WindowShow() {
window.runtime.WindowShow();
}
export function WindowMaximise() {
window.runtime.WindowMaximise();
}
export function WindowToggleMaximise() {
window.runtime.WindowToggleMaximise();
}
export function WindowUnmaximise() {
window.runtime.WindowUnmaximise();
}
export function WindowIsMaximised() {
return window.runtime.WindowIsMaximised();
}
export function WindowMinimise() {
window.runtime.WindowMinimise();
}
export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
export function WindowSetBackgroundColour(R, G, B, A) {
window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function ScreenGetAll() {
return window.runtime.ScreenGetAll();
}
export function WindowIsMinimised() {
return window.runtime.WindowIsMinimised();
}
export function WindowIsNormal() {
return window.runtime.WindowIsNormal();
}
export function BrowserOpenURL(url) {
window.runtime.BrowserOpenURL(url);
}
export function Environment() {
return window.runtime.Environment();
}
export function Quit() {
window.runtime.Quit();
}
export function Hide() {
window.runtime.Hide();
}
export function Show() {
window.runtime.Show();
}
export function ClipboardGetText() {
return window.runtime.ClipboardGetText();
}
export function ClipboardSetText(text) {
return window.runtime.ClipboardSetText(text);
}
/**
* Callback for OnFileDrop returns a slice of file path strings when a drop is finished.
*
* @export
* @callback OnFileDropCallback
* @param {number} x - x coordinate of the drop
* @param {number} y - y coordinate of the drop
* @param {string[]} paths - A list of file paths.
*/
/**
* OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings.
*
* @export
* @param {OnFileDropCallback} callback - Callback for OnFileDrop returns a slice of file path strings when a drop is finished.
* @param {boolean} [useDropTarget=true] - Only call the callback when the drop finished on an element that has the drop target style. (--wails-drop-target)
*/
export function OnFileDrop(callback, useDropTarget) {
return window.runtime.OnFileDrop(callback, useDropTarget);
}
/**
* OnFileDropOff removes the drag and drop listeners and handlers.
*/
export function OnFileDropOff() {
return window.runtime.OnFileDropOff();
}
export function CanResolveFilePaths() {
return window.runtime.CanResolveFilePaths();
}
export function ResolveFilePaths(files) {
return window.runtime.ResolveFilePaths(files);
}

View File

@@ -0,0 +1,47 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
import {api} from '../models';
export function ActivateLicense(arg1:string):Promise<Record<string, any>>;
export function BackupData():Promise<Record<string, any>>;
export function CheckPackageUpdate(arg1:string):Promise<Record<string, any>>;
export function CheckUpdate():Promise<Record<string, any>>;
export function DownloadPackage(arg1:string):Promise<Record<string, any>>;
export function DownloadUpdate(arg1:string):Promise<Record<string, any>>;
export function GetAuthStatus():Promise<Record<string, any>>;
export function GetCurrentVersion():Promise<Record<string, any>>;
export function GetDataStats():Promise<Record<string, any>>;
export function GetDeviceID():Promise<string>;
export function GetSyncStatus():Promise<Record<string, any>>;
export function GetUpdateConfig():Promise<Record<string, any>>;
export function Greet(arg1:string):Promise<string>;
export function ImportPackage(arg1:string):Promise<Record<string, any>>;
export function InstallUpdate(arg1:string,arg2:boolean):Promise<Record<string, any>>;
export function ListBackups():Promise<Record<string, any>>;
export function ListLocalPackages():Promise<Record<string, any>>;
export function QueryHistory(arg1:api.QueryRequest):Promise<Record<string, any>>;
export function RestoreData(arg1:string):Promise<Record<string, any>>;
export function SetUpdateConfig(arg1:boolean,arg2:number,arg3:string):Promise<Record<string, any>>;
export function SyncData():Promise<Record<string, any>>;
export function VerifyUpdateFile(arg1:string,arg2:string,arg3:string):Promise<Record<string, any>>;

View File

@@ -0,0 +1,91 @@
// @ts-check
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
export function ActivateLicense(arg1) {
return window['go']['main']['App']['ActivateLicense'](arg1);
}
export function BackupData() {
return window['go']['main']['App']['BackupData']();
}
export function CheckPackageUpdate(arg1) {
return window['go']['main']['App']['CheckPackageUpdate'](arg1);
}
export function CheckUpdate() {
return window['go']['main']['App']['CheckUpdate']();
}
export function DownloadPackage(arg1) {
return window['go']['main']['App']['DownloadPackage'](arg1);
}
export function DownloadUpdate(arg1) {
return window['go']['main']['App']['DownloadUpdate'](arg1);
}
export function GetAuthStatus() {
return window['go']['main']['App']['GetAuthStatus']();
}
export function GetCurrentVersion() {
return window['go']['main']['App']['GetCurrentVersion']();
}
export function GetDataStats() {
return window['go']['main']['App']['GetDataStats']();
}
export function GetDeviceID() {
return window['go']['main']['App']['GetDeviceID']();
}
export function GetSyncStatus() {
return window['go']['main']['App']['GetSyncStatus']();
}
export function GetUpdateConfig() {
return window['go']['main']['App']['GetUpdateConfig']();
}
export function Greet(arg1) {
return window['go']['main']['App']['Greet'](arg1);
}
export function ImportPackage(arg1) {
return window['go']['main']['App']['ImportPackage'](arg1);
}
export function InstallUpdate(arg1, arg2) {
return window['go']['main']['App']['InstallUpdate'](arg1, arg2);
}
export function ListBackups() {
return window['go']['main']['App']['ListBackups']();
}
export function ListLocalPackages() {
return window['go']['main']['App']['ListLocalPackages']();
}
export function QueryHistory(arg1) {
return window['go']['main']['App']['QueryHistory'](arg1);
}
export function RestoreData(arg1) {
return window['go']['main']['App']['RestoreData'](arg1);
}
export function SetUpdateConfig(arg1, arg2, arg3) {
return window['go']['main']['App']['SetUpdateConfig'](arg1, arg2, arg3);
}
export function SyncData() {
return window['go']['main']['App']['SyncData']();
}
export function VerifyUpdateFile(arg1, arg2, arg3) {
return window['go']['main']['App']['VerifyUpdateFile'](arg1, arg2, arg3);
}

View File

@@ -0,0 +1,21 @@
export namespace api {
export class QueryRequest {
red_balls: number[];
blue_ball: number;
blue_ball_range: number[];
static createFrom(source: any = {}) {
return new QueryRequest(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.red_balls = source["red_balls"];
this.blue_ball = source["blue_ball"];
this.blue_ball_range = source["blue_ball_range"];
}
}
}

View File

@@ -0,0 +1,24 @@
{
"name": "@wailsapp/runtime",
"version": "2.0.0",
"description": "Wails Javascript runtime library",
"main": "runtime.js",
"types": "runtime.d.ts",
"scripts": {
},
"repository": {
"type": "git",
"url": "git+https://github.com/wailsapp/wails.git"
},
"keywords": [
"Wails",
"Javascript",
"Go"
],
"author": "Lea Anthony <lea.anthony@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/wailsapp/wails/issues"
},
"homepage": "https://github.com/wailsapp/wails#readme"
}

View File

@@ -0,0 +1,249 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
export interface Position {
x: number;
y: number;
}
export interface Size {
w: number;
h: number;
}
export interface Screen {
isCurrent: boolean;
isPrimary: boolean;
width : number
height : number
}
// Environment information such as platform, buildtype, ...
export interface EnvironmentInfo {
buildType: string;
platform: string;
arch: string;
}
// [EventsEmit](https://wails.io/docs/reference/runtime/events#eventsemit)
// emits the given event. Optional data may be passed with the event.
// This will trigger any event listeners.
export function EventsEmit(eventName: string, ...data: any): void;
// [EventsOn](https://wails.io/docs/reference/runtime/events#eventson) sets up a listener for the given event name.
export function EventsOn(eventName: string, callback: (...data: any) => void): () => void;
// [EventsOnMultiple](https://wails.io/docs/reference/runtime/events#eventsonmultiple)
// sets up a listener for the given event name, but will only trigger a given number times.
export function EventsOnMultiple(eventName: string, callback: (...data: any) => void, maxCallbacks: number): () => void;
// [EventsOnce](https://wails.io/docs/reference/runtime/events#eventsonce)
// sets up a listener for the given event name, but will only trigger once.
export function EventsOnce(eventName: string, callback: (...data: any) => void): () => void;
// [EventsOff](https://wails.io/docs/reference/runtime/events#eventsoff)
// unregisters the listener for the given event name.
export function EventsOff(eventName: string, ...additionalEventNames: string[]): void;
// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall)
// unregisters all listeners.
export function EventsOffAll(): void;
// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint)
// logs the given message as a raw message
export function LogPrint(message: string): void;
// [LogTrace](https://wails.io/docs/reference/runtime/log#logtrace)
// logs the given message at the `trace` log level.
export function LogTrace(message: string): void;
// [LogDebug](https://wails.io/docs/reference/runtime/log#logdebug)
// logs the given message at the `debug` log level.
export function LogDebug(message: string): void;
// [LogError](https://wails.io/docs/reference/runtime/log#logerror)
// logs the given message at the `error` log level.
export function LogError(message: string): void;
// [LogFatal](https://wails.io/docs/reference/runtime/log#logfatal)
// logs the given message at the `fatal` log level.
// The application will quit after calling this method.
export function LogFatal(message: string): void;
// [LogInfo](https://wails.io/docs/reference/runtime/log#loginfo)
// logs the given message at the `info` log level.
export function LogInfo(message: string): void;
// [LogWarning](https://wails.io/docs/reference/runtime/log#logwarning)
// logs the given message at the `warning` log level.
export function LogWarning(message: string): void;
// [WindowReload](https://wails.io/docs/reference/runtime/window#windowreload)
// Forces a reload by the main application as well as connected browsers.
export function WindowReload(): void;
// [WindowReloadApp](https://wails.io/docs/reference/runtime/window#windowreloadapp)
// Reloads the application frontend.
export function WindowReloadApp(): void;
// [WindowSetAlwaysOnTop](https://wails.io/docs/reference/runtime/window#windowsetalwaysontop)
// Sets the window AlwaysOnTop or not on top.
export function WindowSetAlwaysOnTop(b: boolean): void;
// [WindowSetSystemDefaultTheme](https://wails.io/docs/next/reference/runtime/window#windowsetsystemdefaulttheme)
// *Windows only*
// Sets window theme to system default (dark/light).
export function WindowSetSystemDefaultTheme(): void;
// [WindowSetLightTheme](https://wails.io/docs/next/reference/runtime/window#windowsetlighttheme)
// *Windows only*
// Sets window to light theme.
export function WindowSetLightTheme(): void;
// [WindowSetDarkTheme](https://wails.io/docs/next/reference/runtime/window#windowsetdarktheme)
// *Windows only*
// Sets window to dark theme.
export function WindowSetDarkTheme(): void;
// [WindowCenter](https://wails.io/docs/reference/runtime/window#windowcenter)
// Centers the window on the monitor the window is currently on.
export function WindowCenter(): void;
// [WindowSetTitle](https://wails.io/docs/reference/runtime/window#windowsettitle)
// Sets the text in the window title bar.
export function WindowSetTitle(title: string): void;
// [WindowFullscreen](https://wails.io/docs/reference/runtime/window#windowfullscreen)
// Makes the window full screen.
export function WindowFullscreen(): void;
// [WindowUnfullscreen](https://wails.io/docs/reference/runtime/window#windowunfullscreen)
// Restores the previous window dimensions and position prior to full screen.
export function WindowUnfullscreen(): void;
// [WindowIsFullscreen](https://wails.io/docs/reference/runtime/window#windowisfullscreen)
// Returns the state of the window, i.e. whether the window is in full screen mode or not.
export function WindowIsFullscreen(): Promise<boolean>;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
export function WindowGetSize(): Promise<Size>;
// [WindowSetMaxSize](https://wails.io/docs/reference/runtime/window#windowsetmaxsize)
// Sets the maximum window size. Will resize the window if the window is currently larger than the given dimensions.
// Setting a size of 0,0 will disable this constraint.
export function WindowSetMaxSize(width: number, height: number): void;
// [WindowSetMinSize](https://wails.io/docs/reference/runtime/window#windowsetminsize)
// Sets the minimum window size. Will resize the window if the window is currently smaller than the given dimensions.
// Setting a size of 0,0 will disable this constraint.
export function WindowSetMinSize(width: number, height: number): void;
// [WindowSetPosition](https://wails.io/docs/reference/runtime/window#windowsetposition)
// Sets the window position relative to the monitor the window is currently on.
export function WindowSetPosition(x: number, y: number): void;
// [WindowGetPosition](https://wails.io/docs/reference/runtime/window#windowgetposition)
// Gets the window position relative to the monitor the window is currently on.
export function WindowGetPosition(): Promise<Position>;
// [WindowHide](https://wails.io/docs/reference/runtime/window#windowhide)
// Hides the window.
export function WindowHide(): void;
// [WindowShow](https://wails.io/docs/reference/runtime/window#windowshow)
// Shows the window, if it is currently hidden.
export function WindowShow(): void;
// [WindowMaximise](https://wails.io/docs/reference/runtime/window#windowmaximise)
// Maximises the window to fill the screen.
export function WindowMaximise(): void;
// [WindowToggleMaximise](https://wails.io/docs/reference/runtime/window#windowtogglemaximise)
// Toggles between Maximised and UnMaximised.
export function WindowToggleMaximise(): void;
// [WindowUnmaximise](https://wails.io/docs/reference/runtime/window#windowunmaximise)
// Restores the window to the dimensions and position prior to maximising.
export function WindowUnmaximise(): void;
// [WindowIsMaximised](https://wails.io/docs/reference/runtime/window#windowismaximised)
// Returns the state of the window, i.e. whether the window is maximised or not.
export function WindowIsMaximised(): Promise<boolean>;
// [WindowMinimise](https://wails.io/docs/reference/runtime/window#windowminimise)
// Minimises the window.
export function WindowMinimise(): void;
// [WindowUnminimise](https://wails.io/docs/reference/runtime/window#windowunminimise)
// Restores the window to the dimensions and position prior to minimising.
export function WindowUnminimise(): void;
// [WindowIsMinimised](https://wails.io/docs/reference/runtime/window#windowisminimised)
// Returns the state of the window, i.e. whether the window is minimised or not.
export function WindowIsMinimised(): Promise<boolean>;
// [WindowIsNormal](https://wails.io/docs/reference/runtime/window#windowisnormal)
// Returns the state of the window, i.e. whether the window is normal or not.
export function WindowIsNormal(): Promise<boolean>;
// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour)
// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels.
export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void;
// [ScreenGetAll](https://wails.io/docs/reference/runtime/window#screengetall)
// Gets the all screens. Call this anew each time you want to refresh data from the underlying windowing system.
export function ScreenGetAll(): Promise<Screen[]>;
// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl)
// Opens the given URL in the system browser.
export function BrowserOpenURL(url: string): void;
// [Environment](https://wails.io/docs/reference/runtime/intro#environment)
// Returns information about the environment
export function Environment(): Promise<EnvironmentInfo>;
// [Quit](https://wails.io/docs/reference/runtime/intro#quit)
// Quits the application.
export function Quit(): void;
// [Hide](https://wails.io/docs/reference/runtime/intro#hide)
// Hides the application.
export function Hide(): void;
// [Show](https://wails.io/docs/reference/runtime/intro#show)
// Shows the application.
export function Show(): void;
// [ClipboardGetText](https://wails.io/docs/reference/runtime/clipboard#clipboardgettext)
// Returns the current text stored on clipboard
export function ClipboardGetText(): Promise<string>;
// [ClipboardSetText](https://wails.io/docs/reference/runtime/clipboard#clipboardsettext)
// Sets a text on the clipboard
export function ClipboardSetText(text: string): Promise<boolean>;
// [OnFileDrop](https://wails.io/docs/reference/runtime/draganddrop#onfiledrop)
// OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings.
export function OnFileDrop(callback: (x: number, y: number ,paths: string[]) => void, useDropTarget: boolean) :void
// [OnFileDropOff](https://wails.io/docs/reference/runtime/draganddrop#dragandddropoff)
// OnFileDropOff removes the drag and drop listeners and handlers.
export function OnFileDropOff() :void
// Check if the file path resolver is available
export function CanResolveFilePaths(): boolean;
// Resolves file paths for an array of files
export function ResolveFilePaths(files: File[]): void

View File

@@ -0,0 +1,242 @@
/*
_ __ _ __
| | / /___ _(_) /____
| | /| / / __ `/ / / ___/
| |/ |/ / /_/ / / (__ )
|__/|__/\__,_/_/_/____/
The electron alternative for Go
(c) Lea Anthony 2019-present
*/
export function LogPrint(message) {
window.runtime.LogPrint(message);
}
export function LogTrace(message) {
window.runtime.LogTrace(message);
}
export function LogDebug(message) {
window.runtime.LogDebug(message);
}
export function LogInfo(message) {
window.runtime.LogInfo(message);
}
export function LogWarning(message) {
window.runtime.LogWarning(message);
}
export function LogError(message) {
window.runtime.LogError(message);
}
export function LogFatal(message) {
window.runtime.LogFatal(message);
}
export function EventsOnMultiple(eventName, callback, maxCallbacks) {
return window.runtime.EventsOnMultiple(eventName, callback, maxCallbacks);
}
export function EventsOn(eventName, callback) {
return EventsOnMultiple(eventName, callback, -1);
}
export function EventsOff(eventName, ...additionalEventNames) {
return window.runtime.EventsOff(eventName, ...additionalEventNames);
}
export function EventsOffAll() {
return window.runtime.EventsOffAll();
}
export function EventsOnce(eventName, callback) {
return EventsOnMultiple(eventName, callback, 1);
}
export function EventsEmit(eventName) {
let args = [eventName].slice.call(arguments);
return window.runtime.EventsEmit.apply(null, args);
}
export function WindowReload() {
window.runtime.WindowReload();
}
export function WindowReloadApp() {
window.runtime.WindowReloadApp();
}
export function WindowSetAlwaysOnTop(b) {
window.runtime.WindowSetAlwaysOnTop(b);
}
export function WindowSetSystemDefaultTheme() {
window.runtime.WindowSetSystemDefaultTheme();
}
export function WindowSetLightTheme() {
window.runtime.WindowSetLightTheme();
}
export function WindowSetDarkTheme() {
window.runtime.WindowSetDarkTheme();
}
export function WindowCenter() {
window.runtime.WindowCenter();
}
export function WindowSetTitle(title) {
window.runtime.WindowSetTitle(title);
}
export function WindowFullscreen() {
window.runtime.WindowFullscreen();
}
export function WindowUnfullscreen() {
window.runtime.WindowUnfullscreen();
}
export function WindowIsFullscreen() {
return window.runtime.WindowIsFullscreen();
}
export function WindowGetSize() {
return window.runtime.WindowGetSize();
}
export function WindowSetSize(width, height) {
window.runtime.WindowSetSize(width, height);
}
export function WindowSetMaxSize(width, height) {
window.runtime.WindowSetMaxSize(width, height);
}
export function WindowSetMinSize(width, height) {
window.runtime.WindowSetMinSize(width, height);
}
export function WindowSetPosition(x, y) {
window.runtime.WindowSetPosition(x, y);
}
export function WindowGetPosition() {
return window.runtime.WindowGetPosition();
}
export function WindowHide() {
window.runtime.WindowHide();
}
export function WindowShow() {
window.runtime.WindowShow();
}
export function WindowMaximise() {
window.runtime.WindowMaximise();
}
export function WindowToggleMaximise() {
window.runtime.WindowToggleMaximise();
}
export function WindowUnmaximise() {
window.runtime.WindowUnmaximise();
}
export function WindowIsMaximised() {
return window.runtime.WindowIsMaximised();
}
export function WindowMinimise() {
window.runtime.WindowMinimise();
}
export function WindowUnminimise() {
window.runtime.WindowUnminimise();
}
export function WindowSetBackgroundColour(R, G, B, A) {
window.runtime.WindowSetBackgroundColour(R, G, B, A);
}
export function ScreenGetAll() {
return window.runtime.ScreenGetAll();
}
export function WindowIsMinimised() {
return window.runtime.WindowIsMinimised();
}
export function WindowIsNormal() {
return window.runtime.WindowIsNormal();
}
export function BrowserOpenURL(url) {
window.runtime.BrowserOpenURL(url);
}
export function Environment() {
return window.runtime.Environment();
}
export function Quit() {
window.runtime.Quit();
}
export function Hide() {
window.runtime.Hide();
}
export function Show() {
window.runtime.Show();
}
export function ClipboardGetText() {
return window.runtime.ClipboardGetText();
}
export function ClipboardSetText(text) {
return window.runtime.ClipboardSetText(text);
}
/**
* Callback for OnFileDrop returns a slice of file path strings when a drop is finished.
*
* @export
* @callback OnFileDropCallback
* @param {number} x - x coordinate of the drop
* @param {number} y - y coordinate of the drop
* @param {string[]} paths - A list of file paths.
*/
/**
* OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings.
*
* @export
* @param {OnFileDropCallback} callback - Callback for OnFileDrop returns a slice of file path strings when a drop is finished.
* @param {boolean} [useDropTarget=true] - Only call the callback when the drop finished on an element that has the drop target style. (--wails-drop-target)
*/
export function OnFileDrop(callback, useDropTarget) {
return window.runtime.OnFileDrop(callback, useDropTarget);
}
/**
* OnFileDropOff removes the drag and drop listeners and handlers.
*/
export function OnFileDropOff() {
return window.runtime.OnFileDropOff();
}
export function CanResolveFilePaths() {
return window.runtime.CanResolveFilePaths();
}
export function ResolveFilePaths(files) {
return window.runtime.ResolveFilePaths(files);
}

11
web/vite.config.js Normal file
View File

@@ -0,0 +1,11 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vite.dev/config/
export default defineConfig({
plugins: [vue()],
server: {
port: 34115,
strictPort: true,
},
})