chore: starter

This commit is contained in:
2026-01-29 18:44:04 +08:00
commit 9cda358a2e
91 changed files with 16946 additions and 0 deletions

13
packages/core/env.d.ts vendored Normal file
View File

@@ -0,0 +1,13 @@
/// <reference types="vite/client" />
/// <reference types="element-plus/global" />
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<object, object, any>
export default component
}
interface Window {
// 可以扩展 window 类型
}

View File

@@ -0,0 +1,46 @@
{
"name": "@cslab-dcs/core",
"type": "module",
"version": "1.0.0",
"private": true,
"exports": {
".": {
"types": "./src/index.ts",
"import": "./src/index.ts"
},
"./vite.shared": {
"types": "./vite.shared.d.ts",
"import": "./vite.shared.ts"
}
},
"main": "./src/index.ts",
"types": "./src/index.ts",
"scripts": {
"typecheck": "vue-tsc --noEmit"
},
"dependencies": {
"@cslab-dcs/bridge": "workspace:*",
"@cslab-dcs/schema": "workspace:*",
"@cslab-dcs/utils": "workspace:*",
"@vueuse/core": "^12.0.0",
"dayjs": "^1.11.13",
"element-plus": "^2.9.0",
"mitt": "^3.0.1",
"ofetch": "^1.4.1",
"pinia": "^3.0.0",
"pinia-plugin-persistedstate": "^4.2.0",
"vue": "^3.5.13",
"vue-router": "^4.5.0",
"zod": "^3.24.1"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.1",
"@vitejs/plugin-vue-jsx": "^4.1.1",
"sass": "^1.83.0",
"typescript": "^5.9.3",
"unplugin-auto-import": "^19.0.0",
"unplugin-vue-components": "^28.0.0",
"vite": "^6.0.3",
"vue-tsc": "^2.2.0"
}
}

24
packages/core/src/App.vue Normal file
View File

@@ -0,0 +1,24 @@
<script setup lang="ts">
import { ElConfigProvider } from 'element-plus'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
const locale = zhCn
</script>
<template>
<ElConfigProvider :locale="locale">
<router-view />
</ElConfigProvider>
</template>
<style>
/* 全局样式 */
html, body, #app {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB',
'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
}
</style>

View File

@@ -0,0 +1,26 @@
@use './variables.scss' as *;
/* Reset or Base styles */
body {
background-color: $bg-color-page;
color: $text-color-primary;
}
/* Scrollbar customization */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: $border-color;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: $text-color-secondary;
}

View File

@@ -0,0 +1,18 @@
/* Global SCSS Variables */
$primary-color: #409eff;
$success-color: #67c23a;
$warning-color: #e6a23c;
$danger-color: #f56c6c;
$info-color: #909399;
$text-color-primary: #303133;
$text-color-regular: #606266;
$text-color-secondary: #909399;
$text-color-placeholder: #a8abb2;
$border-color: #dcdfe6;
$border-color-light: #e4e7ed;
$border-color-lighter: #ebeef5;
$bg-color: #ffffff;
$bg-color-page: #f2f3f5;

View File

@@ -0,0 +1,38 @@
import type { IPlatformBridge } from '@cslab-dcs/bridge'
import type { App } from 'vue'
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
/**
* 核心包入口
*/
import { createApp } from 'vue'
import AppRoot from './App.vue'
import router from './router'
import './assets/styles/index.scss'
export function createDCSApp(bridge?: IPlatformBridge): App {
const app = createApp(AppRoot)
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
app.use(pinia)
app.use(router)
// 如果没有传入 bridge尝试自动创建但这可能无法涵盖 Tauri
// 实际上,为了避免自动创建时的依赖问题,我们建议 Apps 必须传入 bridge
// 或者我们在 @cslab-dcs/core 中不直接依赖 @cslab-dcs/bridge 的实现,只依赖类型
// 但这里为了方便,我们只对 globalProperties 做注入
if (bridge) {
app.config.globalProperties.$bridge = bridge
app.provide('bridge', bridge)
}
return app
}
export { default as AppRoot } from './App.vue'
export * from './router'
export * from './stores'

View File

@@ -0,0 +1,19 @@
import type { RouteRecordRaw } from 'vue-router'
import { createRouter, createWebHashHistory } from 'vue-router'
const routes: RouteRecordRaw[] = [
{
path: '/',
name: 'Home',
component: () => import('../views/Home.vue'),
meta: { title: '首页' },
},
// 可以添加更多路由
]
const router = createRouter({
history: createWebHashHistory(), // 使用 Hash 模式兼容 Electron
routes,
})
export default router

View File

@@ -0,0 +1,17 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useAppStore = defineStore('app', () => {
const theme = ref<'light' | 'dark'>('light')
function toggleTheme() {
theme.value = theme.value === 'light' ? 'dark' : 'light'
}
return {
theme,
toggleTheme,
}
}, {
persist: true,
})

View File

@@ -0,0 +1,8 @@
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
export const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
export * from './app'
export default pinia

View File

@@ -0,0 +1,95 @@
<script setup lang="ts">
import type { IPlatformBridge } from '@cslab-dcs/bridge'
import { bridge as defaultBridge } from '@cslab-dcs/bridge'
import { inject, onMounted, ref } from 'vue'
const platformInfo = ref<any>(null)
const appVersion = ref('')
const bridge = inject<IPlatformBridge>('bridge', defaultBridge)
onMounted(async () => {
platformInfo.value = await bridge.system.getPlatformInfo()
appVersion.value = await bridge.system.getAppVersion()
})
async function handleOpenFile() {
const result = await bridge.file.openDialog({
title: '打开配置',
filters: [{ name: 'JSON', extensions: ['json'] }],
})
if (result) {
await bridge.dialog.message({
title: '选择文件',
message: `你选择了: ${Array.isArray(result) ? result.join(', ') : result}`,
})
}
}
function handleGreet() {
bridge.dialog.message({
title: 'Hello',
message: `Welcome to DCS Editor on ${platformInfo.value?.name}`,
})
}
</script>
<template>
<div class="home-container">
<div class="content">
<h1>DCS Editor ({{ platformInfo?.name || 'Loading...' }})</h1>
<p>Version: {{ appVersion }}</p>
<div class="card">
<el-button type="primary" @click="handleGreet">
打招呼
</el-button>
<el-button type="success" @click="handleOpenFile">
打开文件
</el-button>
</div>
<div class="debug-info">
<h3>Platform Info:</h3>
<pre>{{ JSON.stringify(platformInfo, null, 2) }}</pre>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.home-container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
.content {
text-align: center;
background: white;
padding: 2rem;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
.card {
margin: 20px 0;
gap: 10px;
display: flex;
justify-content: center;
}
.debug-info {
margin-top: 20px;
text-align: left;
background: #f8f9fa;
padding: 10px;
border-radius: 4px;
pre {
margin: 0;
font-size: 12px;
}
}
}
}
</style>

View File

@@ -0,0 +1,16 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@cslab-dcs/bridge": ["../bridge/src"],
"@cslab-dcs/schema": ["../schema/src"],
"@cslab-dcs/utils": ["../utils/src"]
},
"types": ["element-plus/global"]
},
"include": ["src/**/*", "vite.shared.ts", "env.d.ts"],
"exclude": ["node_modules", "dist"]
}

View File

@@ -0,0 +1,43 @@
import type { UserConfig } from 'vite'
import { resolve } from 'node:path'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import AutoImport from 'unplugin-auto-import/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import Components from 'unplugin-vue-components/vite'
export function createSharedViteConfig(rootDir: string): UserConfig {
return {
plugins: [
vue(),
vueJsx(),
AutoImport({
imports: ['vue', 'vue-router', 'pinia', '@vueuse/core'],
resolvers: [ElementPlusResolver()],
dts: resolve(rootDir, 'src/auto-imports.d.ts'),
eslintrc: {
enabled: true,
},
}),
Components({
resolvers: [ElementPlusResolver()],
dts: resolve(rootDir, 'src/components.d.ts'),
}),
],
resolve: {
alias: {
'@': resolve(rootDir, 'src'),
'@cslab-dcs/core': resolve(__dirname, './src'),
},
},
css: {
preprocessorOptions: {
scss: {
// 自定义 element-plus 主题或全局变量
additionalData: `@use "@/assets/styles/variables.scss" as *;`,
api: 'modern-compiler', // sass-loader v15+ requirement
},
},
},
}
}