init
This commit is contained in:
22
.env
Normal file
22
.env
Normal file
@@ -0,0 +1,22 @@
|
||||
# 全局环境变量配置
|
||||
|
||||
# Coze API 配置
|
||||
COZE_API_TOKEN=pat_7VvJA4an8IbsjmID9SasNBZyVDCJ3NamxwBOBdDxfUQEnGOYGaQf3odBUoibO0aF
|
||||
COZE_DEFAULT_WORKFLOW_ID=7554970254934605859
|
||||
|
||||
# Feishu API 配置
|
||||
FEISHU_APP_ID=cli_a62aaf3d9d385013
|
||||
FEISHU_APP_SECRET=VH46dJI4T4bbUD7rI9J6Se2EI5rWVpBf
|
||||
|
||||
# Coze OAuth 配置
|
||||
COZE_CLIENT_ID=27608009841040583568491680329534.app.coze
|
||||
COZE_CLIENT_SECRET=Bx7ctHOQlzWVdoaQnSYJgRPwlK64IUuhi4oPnRO3OyJ5K4yc
|
||||
|
||||
# 数据库配置
|
||||
DATABASE_URL=file:./dev.db
|
||||
# 其他配置
|
||||
TOKEN_REFRESH_SCHEDULER_ENABLED=true
|
||||
NUXT_PUBLIC_API_BASE=
|
||||
|
||||
# Server 配置
|
||||
NUXT_DEV_PORT=8080
|
||||
24
.env.example
Normal file
24
.env.example
Normal file
@@ -0,0 +1,24 @@
|
||||
# 环境变量配置示例
|
||||
# 复制此文件为 .env 并修改为你的实际配置
|
||||
|
||||
# Coze API 配置
|
||||
COZE_API_TOKEN=your_coze_api_token_here
|
||||
COZE_DEFAULT_WORKFLOW_ID=your_default_workflow_id_here
|
||||
|
||||
# Feishu API 配置
|
||||
FEISHU_APP_ID=your_feishu_app_id_here
|
||||
FEISHU_APP_SECRET=your_feishu_app_secret_here
|
||||
|
||||
# Coze OAuth 配置
|
||||
COZE_CLIENT_ID=your_coze_client_id_here
|
||||
COZE_CLIENT_SECRET=your_coze_client_secret_here
|
||||
|
||||
# 数据库配置
|
||||
DATABASE_URL=file:./dev.db
|
||||
|
||||
# 其他配置
|
||||
TOKEN_REFRESH_SCHEDULER_ENABLED=true
|
||||
NUXT_PUBLIC_API_BASE=
|
||||
|
||||
# Server 配置
|
||||
NUXT_DEV_PORT=8080
|
||||
3
.npmrc
Normal file
3
.npmrc
Normal file
@@ -0,0 +1,3 @@
|
||||
shamefully-hoist=true
|
||||
public-hoist-pattern[]=*@element-plus*
|
||||
public-hoist-pattern[]=*dayjs*
|
||||
11
.prettierignore
Normal file
11
.prettierignore
Normal file
@@ -0,0 +1,11 @@
|
||||
# 忽略不需要格式化的文件
|
||||
node_modules/
|
||||
dist/
|
||||
.nuxt/
|
||||
.output/
|
||||
*.log
|
||||
*.min.js
|
||||
*.min.css
|
||||
.env*
|
||||
prisma/migrations/
|
||||
.DS_Store
|
||||
12
.prettierrc
Normal file
12
.prettierrc
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5",
|
||||
"printWidth": 100,
|
||||
"arrowParens": "avoid",
|
||||
"endOfLine": "lf",
|
||||
"bracketSpacing": true,
|
||||
"jsxBracketSameLine": false,
|
||||
"proseWrap": "preserve"
|
||||
}
|
||||
94
Nuxt4Curd.code-workspace
Normal file
94
Nuxt4Curd.code-workspace
Normal file
@@ -0,0 +1,94 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"name": "Nuxt4Curd - App",
|
||||
"path": "./app"
|
||||
},
|
||||
{
|
||||
"name": "Nuxt4Curd - Root",
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"tailwindCSS.experimental.configFile": "./tailwind.config.js",
|
||||
"tailwindCSS.cssPath": "./assets/css/main.css",
|
||||
"tailwindCSS.includeLanguages": {
|
||||
"vue": "html",
|
||||
"javascript": "javascript",
|
||||
"typescript": "typescript",
|
||||
"vue-html": "html",
|
||||
"plaintext": "css",
|
||||
"markdown": "html"
|
||||
},
|
||||
"tailwindCSS.experimental.classRegex": [
|
||||
["class:\\s*?[\"'`]([^\"'`]*).*?[\"'`]", "[\"'`]([^\"'`]*)[\"'`]"],
|
||||
["className:\\s*?[\"'`]([^\"'`]*).*?[\"'`]", "[\"'`]([^\"'`]*)[\"'`]"],
|
||||
["\\bclass\\s*=\\s*[\"']([^\"']*)[\"']", "([^\"']*)"],
|
||||
["\\bclassName\\s*=\\s*[\"']([^\"']*)[\"']", "([^\"']*)"],
|
||||
["class=\"([^\"]*)\"", "([^\"]*)"],
|
||||
["class='([^']*)'", "([^']*)"],
|
||||
["class=`([^`]*)`", "([^`]*)"],
|
||||
["@apply\\s+([^;]*)", 1],
|
||||
["@layer utilities\\s*{[^}]*?\\.([^\\s{]+)", 1],
|
||||
["tw`([^`]*)`", 1],
|
||||
["tw=\"([^\"]*)\"", 1],
|
||||
["cva\\(([^\\)]*)\\)", 1],
|
||||
["cx\\(([^\\)]*)\\)", 1],
|
||||
["cn\\(([^\\)]*)\\)", 1]
|
||||
],
|
||||
"tailwindCSS.validate": true,
|
||||
"tailwindCSS.suggestions": true,
|
||||
"tailwindCSS.hovers": true,
|
||||
"tailwindCSS.codeActions": true,
|
||||
"tailwindCSS.experimental.classSorting": true,
|
||||
"tailwindCSS.colorDecorators": true,
|
||||
"tailwindCSS.showPixelEquivalents": true,
|
||||
"tailwindCSS.rootFontSize": 16,
|
||||
"tailwindCSS.experimental.classAttributes": ["class", "className", "ngClass"],
|
||||
"typescript.preferences.importModuleSpecifier": "relative",
|
||||
"typescript.suggest.autoImports": true,
|
||||
"typescript.suggest.completeFunctionCalls": true,
|
||||
"typescript.inlayHints.parameterNames.enabled": "all",
|
||||
"typescript.inlayHints.parameterTypes.enabled": true,
|
||||
"typescript.inlayHints.variableTypes.enabled": true,
|
||||
"files.associations": {
|
||||
"*.css": "tailwindcss",
|
||||
"main.css": "tailwindcss"
|
||||
},
|
||||
"css.customData": [".vscode/css_custom_data.json"],
|
||||
"css.validate": false,
|
||||
"tailwindCSS.includeLanguages": {
|
||||
"css": "css",
|
||||
"scss": "scss",
|
||||
"less": "less",
|
||||
"postcss": "css"
|
||||
},
|
||||
"emmet.includeLanguages": {
|
||||
"vue-html": "html",
|
||||
"vue": "html",
|
||||
"javascript": "javascriptreact",
|
||||
"typescript": "typescriptreact"
|
||||
},
|
||||
"css.validate": true,
|
||||
"css.completion.completePropertyWithSemicolon": true,
|
||||
"css.completion.triggerPropertyValueCompletion": true,
|
||||
"cssPeek.enable": true,
|
||||
"cssPeek.enableGotoDefinition": true,
|
||||
"cssPeek.enableHover": true,
|
||||
"cssPeek.enableShowReferences": true,
|
||||
"cssPeek.enableShowReferencesInPeek": true,
|
||||
"cssPeek.enableShowDefinitionInPeek": true,
|
||||
"cssPeek.enableShowQuickInfo": true,
|
||||
"cssPeek.enableColors": true,
|
||||
"cssPeek.enableFiles": ["css", "scss", "less", "vue", "html"],
|
||||
"nuxt.isNuxtApp": true
|
||||
},
|
||||
"extensions": {
|
||||
"recommendations": [
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"austenc.tailwind-docs",
|
||||
"Vue.volar",
|
||||
"Vue.vscode-typescript-vue-plugin"
|
||||
]
|
||||
}
|
||||
}
|
||||
223
app/pages/PowerStation/index.vue
Normal file
223
app/pages/PowerStation/index.vue
Normal file
@@ -0,0 +1,223 @@
|
||||
<!--
|
||||
PowerStation/index.vue
|
||||
电站设备管理系统主页面
|
||||
使用网格布局展示3D模型视图、数据图表和属性面板
|
||||
-->
|
||||
<template>
|
||||
<div
|
||||
class="w-full h-screen flex flex-col overflow-hidden bg-[#0B1120] font-sans powerstation-scrollbar"
|
||||
>
|
||||
<!-- ============================================================
|
||||
头部导航
|
||||
============================================================ -->
|
||||
<HeaderNavigation />
|
||||
|
||||
<!-- ============================================================
|
||||
主要内容区域
|
||||
============================================================ -->
|
||||
<div class="flex-1 flex justify-start relative min-h-0">
|
||||
<!-- 左侧面板:模型结构树 -->
|
||||
<ModelTreePanel class="w-[280px] h-full z-50 self-stretch flex-shrink-0" />
|
||||
|
||||
<!-- 右侧面板:主内容区 -->
|
||||
<div class="flex-1 transition-all duration-300">
|
||||
<div
|
||||
class="h-full bg-[#020617] p-2 gap-2 overflow-hidden grid transition-all duration-300 min-h-0"
|
||||
:class="[
|
||||
maximizedComponent
|
||||
? 'grid-cols-1 grid-rows-1'
|
||||
: 'grid-cols-[1fr_30%] grid-rows-[70%_30%]',
|
||||
]"
|
||||
>
|
||||
<!-- 3D视图 - 左上区域 -->
|
||||
<Model3DView
|
||||
class="bg-[#0b1120] border border-cyan-500/20 rounded shadow-[0_0_10px_rgba(6,182,212,0.05)] transition-all duration-300 min-h-0"
|
||||
:class="[
|
||||
maximizedComponent === '3d'
|
||||
? 'col-span-full row-span-full'
|
||||
: maximizedComponent
|
||||
? 'hidden'
|
||||
: 'col-start-1 row-start-1',
|
||||
]"
|
||||
:is-maximized="maximizedComponent === '3d'"
|
||||
@toggle-maximize="toggleMaximize('3d')"
|
||||
/>
|
||||
|
||||
<!-- 数据图表 - 左下区域 -->
|
||||
<DataChartsSection
|
||||
class="bg-[#0b1120] border border-cyan-500/20 rounded shadow-[0_0_10px_rgba(6,182,212,0.05)] overflow-hidden transition-all duration-300 min-h-0"
|
||||
:class="[
|
||||
maximizedComponent === 'charts'
|
||||
? 'col-span-full row-span-full'
|
||||
: maximizedComponent
|
||||
? 'hidden'
|
||||
: 'col-start-1 row-start-2',
|
||||
]"
|
||||
:is-maximized="maximizedComponent === 'charts'"
|
||||
@toggle-maximize="toggleMaximize('charts')"
|
||||
/>
|
||||
|
||||
<!-- 属性面板 - 右侧区域(跨两行) -->
|
||||
<ModelPropertiesPanel
|
||||
class="bg-[#0b1120] border border-cyan-500/20 rounded shadow-[0_0_10px_rgba(6,182,212,0.05)] overflow-hidden relative transition-all duration-300 border-l border-cyan-500/20"
|
||||
:class="[
|
||||
maximizedComponent === 'props'
|
||||
? 'col-span-full row-span-full'
|
||||
: maximizedComponent
|
||||
? 'hidden'
|
||||
: 'col-start-2 row-span-2',
|
||||
]"
|
||||
:is-maximized="maximizedComponent === 'props'"
|
||||
@toggle-maximize="toggleMaximize('props')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* PowerStation 主页面
|
||||
* 电站设备管理系统的核心页面
|
||||
* 集成3D视图、数据图表和属性面板
|
||||
*/
|
||||
import DataChartsSection from '~/components/PowerStation/DataChartsSection.vue'
|
||||
import HeaderNavigation from '~/components/PowerStation/HeaderNavigation.vue'
|
||||
import Model3DView from '~/components/PowerStation/Model3DView.vue'
|
||||
import ModelPropertiesPanel from '~/components/PowerStation/ModelPropertiesPanel.vue'
|
||||
import ModelTreePanel from '~/components/PowerStation/ModelTreePanel.vue'
|
||||
|
||||
// ============================================================
|
||||
// 页面配置
|
||||
// ============================================================
|
||||
|
||||
definePageMeta({
|
||||
layout: false, // 使用全屏自定义布局
|
||||
})
|
||||
|
||||
// ============================================================
|
||||
// 状态和引用
|
||||
// ============================================================
|
||||
|
||||
const route = useRoute()
|
||||
const store = usePowerStationStore()
|
||||
|
||||
/** 当前最大化的组件 */
|
||||
const maximizedComponent = ref<string | null>(null)
|
||||
|
||||
// ============================================================
|
||||
// 方法
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* 切换组件最大化状态
|
||||
* @param component - 组件标识('3d' | 'charts' | 'props')
|
||||
*/
|
||||
const toggleMaximize = (component: string) => {
|
||||
if (maximizedComponent.value === component) {
|
||||
maximizedComponent.value = null // 还原
|
||||
} else {
|
||||
maximizedComponent.value = component // 最大化指定组件
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 路由同步
|
||||
// ============================================================
|
||||
|
||||
// 监听路由变化,确保store与路由参数同步
|
||||
watch(
|
||||
() => route.query.currentNodeId,
|
||||
newId => {
|
||||
if (newId && typeof newId === 'string') {
|
||||
// 只在完整模式下同步
|
||||
if (store.loadMode && store.currentNodeId !== newId) {
|
||||
console.log('PowerStation页面:同步路由currentNodeId到store:', newId)
|
||||
store.currentNodeId = newId
|
||||
}
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
// ============================================================
|
||||
// 生命周期
|
||||
// ============================================================
|
||||
|
||||
onMounted(() => {
|
||||
// 保留路由参数检查,供后续扩展使用
|
||||
const currentNodeId = route.query.currentNodeId as string
|
||||
if (currentNodeId) {
|
||||
// 节点选择逻辑由子组件处理
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* ============================================================
|
||||
页面全局样式
|
||||
============================================================ */
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
全局滚动条样式
|
||||
============================================================ */
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: rgba(15, 23, 42, 0.3);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: rgba(34, 211, 238, 0.3);
|
||||
border-radius: 4px;
|
||||
border: 1px solid rgba(34, 211, 238, 0.1);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(34, 211, 238, 0.5);
|
||||
box-shadow: 0 0 8px rgba(34, 211, 238, 0.3);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-corner {
|
||||
background: rgba(15, 23, 42, 0.3);
|
||||
}
|
||||
|
||||
/* Firefox滚动条样式 */
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(34, 211, 238, 0.3) rgba(15, 23, 42, 0.3);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
PowerStation页面特殊滚动条样式
|
||||
============================================================ */
|
||||
|
||||
.powerstation-scrollbar ::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
.powerstation-scrollbar ::-webkit-scrollbar-track {
|
||||
background: rgba(11, 17, 32, 0.5);
|
||||
}
|
||||
|
||||
.powerstation-scrollbar ::-webkit-scrollbar-thumb {
|
||||
background: rgba(6, 182, 212, 0.4);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.powerstation-scrollbar ::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(6, 182, 212, 0.6);
|
||||
}
|
||||
</style>
|
||||
67
package.json
Normal file
67
package.json
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"name": "@nuxt4crud/monorepo",
|
||||
"version": "1.0.0",
|
||||
"description": "Nuxt 4 CRUD 应用 - 前后端分离架构",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"workspaces": [
|
||||
"shared",
|
||||
"app",
|
||||
"server"
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "concurrently \"pnpm run dev:shared\" \"pnpm run dev:app\"",
|
||||
"dev:shared": "pnpm -F @nuxt4crud/shared dev",
|
||||
"dev:app": "pnpm -F @nuxt4crud/app dev",
|
||||
"build": "pnpm run build:shared && pnpm run build:app",
|
||||
"build:shared": "pnpm -F @nuxt4crud/shared build",
|
||||
"build:app": "pnpm -F @nuxt4crud/app build",
|
||||
"build:prod": "chmod +x build-and-deploy.sh && ./build-and-deploy.sh",
|
||||
"build:prod:win": "build-and-deploy.bat",
|
||||
"start": "pnpm -F @nuxt4crud/app start",
|
||||
"start:prod": "cd app/.output && node server/index.mjs",
|
||||
"start:prod:win": "cd app/.output && node server/index.mjs",
|
||||
"clean": "pnpm -F @nuxt4crud/shared clean && pnpm -F @nuxt4crud/app clean",
|
||||
"clean:all": "rimraf app/.nuxt app/.output app/dist shared/dist node_modules",
|
||||
"format": "prettier --write .",
|
||||
"format:check": "prettier --check .",
|
||||
"lint": "pnpm -F @nuxt4crud/app lint",
|
||||
"lint:fix": "pnpm -F @nuxt4crud/app lint:fix",
|
||||
"type-check": "pnpm -F @nuxt4crud/shared type-check && pnpm -F @nuxt4crud/app type-check",
|
||||
"test": "echo \"No tests specified\"",
|
||||
"postinstall": "pnpm run build:shared && pnpm -F @nuxt4crud/server prisma:generate",
|
||||
"setup": "pnpm install && pnpm run build:shared && pnpm run prisma:migrate",
|
||||
"prisma:migrate": "pnpm -F @nuxt4crud/server prisma:migrate",
|
||||
"prisma:studio": "pnpm -F @nuxt4crud/server prisma:studio",
|
||||
"seed": "node scripts/simple-seed.js",
|
||||
"check-db": "node scripts/check-users.js",
|
||||
"test:env": "node -e \"require('dotenv').config({path: '.env'}); console.log('环境变量测试:'); console.log('FEISHU_APP_ID:', process.env.FEISHU_APP_ID); console.log('COZE_API_TOKEN:', process.env.COZE_API_TOKEN ? '已设置' : '未设置'); console.log('DATABASE_URL:', process.env.DATABASE_URL);\""
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt4crud/prettier-config": "file:./prettier-config",
|
||||
"@types/node": "^20.17.6",
|
||||
"axios": "^1.13.2",
|
||||
"concurrently": "^8.2.2",
|
||||
"dotenv": "^17.2.3",
|
||||
"prettier": "^3.3.3",
|
||||
"rimraf": "^5.0.10",
|
||||
"typescript": "^5.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"pnpm": ">=8.0.0"
|
||||
},
|
||||
"keywords": [
|
||||
"nuxt4",
|
||||
"crud",
|
||||
"monorepo",
|
||||
"typescript",
|
||||
"prisma"
|
||||
],
|
||||
"author": "Your Name",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@pinia/nuxt": "^0.11.3",
|
||||
"pinia": "^3.0.4"
|
||||
}
|
||||
}
|
||||
12495
pnpm-lock.yaml
generated
Normal file
12495
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
5
pnpm-workspace.yaml
Normal file
5
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,5 @@
|
||||
packages:
|
||||
- 'shared'
|
||||
- 'app'
|
||||
- 'server'
|
||||
- 'prettier-config'
|
||||
13
prisma.config.ts
Normal file
13
prisma.config.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import 'dotenv/config'
|
||||
import { defineConfig, env } from 'prisma/config'
|
||||
|
||||
export default defineConfig({
|
||||
schema: 'prisma/schema.prisma',
|
||||
migrations: {
|
||||
path: 'prisma/migrations',
|
||||
},
|
||||
engine: 'classic',
|
||||
datasource: {
|
||||
url: env('DATABASE_URL'),
|
||||
},
|
||||
})
|
||||
24
tsconfig.base.json
Normal file
24
tsconfig.base.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"removeComments": false,
|
||||
"sourceMap": true,
|
||||
"resolveJsonModule": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"exactOptionalPropertyTypes": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user