chore: starter
This commit is contained in:
13
packages/core/env.d.ts
vendored
Normal file
13
packages/core/env.d.ts
vendored
Normal 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 类型
|
||||
}
|
||||
46
packages/core/package.json
Normal file
46
packages/core/package.json
Normal 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
24
packages/core/src/App.vue
Normal 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>
|
||||
26
packages/core/src/assets/styles/index.scss
Normal file
26
packages/core/src/assets/styles/index.scss
Normal 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;
|
||||
}
|
||||
18
packages/core/src/assets/styles/variables.scss
Normal file
18
packages/core/src/assets/styles/variables.scss
Normal 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;
|
||||
38
packages/core/src/index.ts
Normal file
38
packages/core/src/index.ts
Normal 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'
|
||||
19
packages/core/src/router/index.ts
Normal file
19
packages/core/src/router/index.ts
Normal 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
|
||||
17
packages/core/src/stores/app.ts
Normal file
17
packages/core/src/stores/app.ts
Normal 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,
|
||||
})
|
||||
8
packages/core/src/stores/index.ts
Normal file
8
packages/core/src/stores/index.ts
Normal 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
|
||||
95
packages/core/src/views/Home.vue
Normal file
95
packages/core/src/views/Home.vue
Normal 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>
|
||||
16
packages/core/tsconfig.json
Normal file
16
packages/core/tsconfig.json
Normal 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"]
|
||||
}
|
||||
43
packages/core/vite.shared.ts
Normal file
43
packages/core/vite.shared.ts
Normal 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
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user