Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
43750b306c | ||
|
|
28aa8b5f62 | ||
|
|
e71181f0a3 |
@@ -1,31 +0,0 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# Matches multiple files with brace expansion notation
|
||||
[*.{js,jsx,ts,tsx,vue}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# Matches multiple files with brace expansion notation
|
||||
[*.{json,md,yml,yaml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# Matches multiple files with brace expansion notation
|
||||
[*.scss]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# The above files are for code, but for config files we want no indentation
|
||||
[{package.json,.eslintrc.cjs,.prettierrc}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
@@ -1,3 +0,0 @@
|
||||
# 开发环境配置
|
||||
VITE_API_BASE_URL=http://localhost:8000/api/v1
|
||||
VITE_APP_TITLE=资产管理系统
|
||||
+35
-3
@@ -1,3 +1,35 @@
|
||||
# 生产环境配置
|
||||
VITE_API_BASE_URL=https://zc.workyai.cn/api/v1
|
||||
VITE_APP_TITLE=资产管理系统
|
||||
APP_NAME=资产管理系统
|
||||
APP_VERSION=1.0.0
|
||||
APP_ENVIRONMENT=production
|
||||
DEBUG=False
|
||||
HOST=0.0.0.0
|
||||
PORT=8001
|
||||
API_V1_PREFIX=/api/v1
|
||||
|
||||
# 数据库配置(从服务器获取)
|
||||
DATABASE_URL=postgresql+asyncpg://asset_user:PASSWORD@118.145.218.2:5433/asset_management
|
||||
DATABASE_ECHO=False
|
||||
|
||||
# Redis配置
|
||||
REDIS_URL=redis://:PASSWORD@118.145.218.2:6380/0
|
||||
REDIS_MAX_CONNECTIONS=50
|
||||
|
||||
# JWT配置
|
||||
SECRET_KEY=请生成强密钥
|
||||
ALGORITHM=HS256
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES=15
|
||||
REFRESH_TOKEN_EXPIRE_DAYS=7
|
||||
|
||||
# CORS配置
|
||||
CORS_ORIGINS=["https://zc.workyai.cn"]
|
||||
CORS_ALLOW_CREDENTIALS=True
|
||||
CORS_ALLOW_METHODS=["GET","POST","PUT","DELETE","PATCH"]
|
||||
CORS_ALLOW_HEADERS=["*"]
|
||||
|
||||
# 文件上传配置
|
||||
UPLOAD_DIR=uploads
|
||||
MAX_UPLOAD_SIZE=104857600
|
||||
|
||||
# 日志配置
|
||||
LOG_LEVEL=INFO
|
||||
LOG_FILE=logs/app.log
|
||||
|
||||
@@ -1,312 +0,0 @@
|
||||
{
|
||||
"globals": {
|
||||
"Component": true,
|
||||
"ComponentPublicInstance": true,
|
||||
"ComputedRef": true,
|
||||
"DirectiveBinding": true,
|
||||
"EffectScope": true,
|
||||
"ExtractDefaultPropTypes": true,
|
||||
"ExtractPropTypes": true,
|
||||
"ExtractPublicPropTypes": true,
|
||||
"InjectionKey": true,
|
||||
"MaybeRef": true,
|
||||
"MaybeRefOrGetter": true,
|
||||
"PropType": true,
|
||||
"Ref": true,
|
||||
"VNode": true,
|
||||
"WritableComputedRef": true,
|
||||
"acceptHMRUpdate": true,
|
||||
"asyncComputed": true,
|
||||
"autoResetRef": true,
|
||||
"computed": true,
|
||||
"computedAsync": true,
|
||||
"computedEager": true,
|
||||
"computedInject": true,
|
||||
"computedWithControl": true,
|
||||
"controlledComputed": true,
|
||||
"controlledRef": true,
|
||||
"createApp": true,
|
||||
"createEventHook": true,
|
||||
"createGlobalState": true,
|
||||
"createInjectionState": true,
|
||||
"createPinia": true,
|
||||
"createReactiveFn": true,
|
||||
"createReusableTemplate": true,
|
||||
"createSharedComposable": true,
|
||||
"createTemplatePromise": true,
|
||||
"createUnrefFn": true,
|
||||
"customRef": true,
|
||||
"debouncedRef": true,
|
||||
"debouncedWatch": true,
|
||||
"defineAsyncComponent": true,
|
||||
"defineComponent": true,
|
||||
"defineStore": true,
|
||||
"eagerComputed": true,
|
||||
"effectScope": true,
|
||||
"extendRef": true,
|
||||
"getActivePinia": true,
|
||||
"getCurrentInstance": true,
|
||||
"getCurrentScope": true,
|
||||
"h": true,
|
||||
"ignorableWatch": true,
|
||||
"inject": true,
|
||||
"injectLocal": true,
|
||||
"isDefined": true,
|
||||
"isProxy": true,
|
||||
"isReactive": true,
|
||||
"isReadonly": true,
|
||||
"isRef": true,
|
||||
"makeDestructurable": true,
|
||||
"mapActions": true,
|
||||
"mapGetters": true,
|
||||
"mapState": true,
|
||||
"mapStores": true,
|
||||
"mapWritableState": true,
|
||||
"markRaw": true,
|
||||
"nextTick": true,
|
||||
"onActivated": true,
|
||||
"onBeforeMount": true,
|
||||
"onBeforeRouteLeave": true,
|
||||
"onBeforeRouteUpdate": true,
|
||||
"onBeforeUnmount": true,
|
||||
"onBeforeUpdate": true,
|
||||
"onClickOutside": true,
|
||||
"onDeactivated": true,
|
||||
"onErrorCaptured": true,
|
||||
"onKeyStroke": true,
|
||||
"onLongPress": true,
|
||||
"onMounted": true,
|
||||
"onRenderTracked": true,
|
||||
"onRenderTriggered": true,
|
||||
"onScopeDispose": true,
|
||||
"onServerPrefetch": true,
|
||||
"onStartTyping": true,
|
||||
"onUnmounted": true,
|
||||
"onUpdated": true,
|
||||
"onWatcherCleanup": true,
|
||||
"pausableWatch": true,
|
||||
"provide": true,
|
||||
"provideLocal": true,
|
||||
"reactify": true,
|
||||
"reactifyObject": true,
|
||||
"reactive": true,
|
||||
"reactiveComputed": true,
|
||||
"reactiveOmit": true,
|
||||
"reactivePick": true,
|
||||
"readonly": true,
|
||||
"ref": true,
|
||||
"refAutoReset": true,
|
||||
"refDebounced": true,
|
||||
"refDefault": true,
|
||||
"refThrottled": true,
|
||||
"refWithControl": true,
|
||||
"resolveComponent": true,
|
||||
"resolveRef": true,
|
||||
"resolveUnref": true,
|
||||
"setActivePinia": true,
|
||||
"setMapStoreSuffix": true,
|
||||
"shallowReactive": true,
|
||||
"shallowReadonly": true,
|
||||
"shallowRef": true,
|
||||
"storeToRefs": true,
|
||||
"syncRef": true,
|
||||
"syncRefs": true,
|
||||
"templateRef": true,
|
||||
"throttledRef": true,
|
||||
"throttledWatch": true,
|
||||
"toRaw": true,
|
||||
"toReactive": true,
|
||||
"toRef": true,
|
||||
"toRefs": true,
|
||||
"toValue": true,
|
||||
"triggerRef": true,
|
||||
"tryOnBeforeMount": true,
|
||||
"tryOnBeforeUnmount": true,
|
||||
"tryOnMounted": true,
|
||||
"tryOnScopeDispose": true,
|
||||
"tryOnUnmounted": true,
|
||||
"unref": true,
|
||||
"unrefElement": true,
|
||||
"until": true,
|
||||
"useActiveElement": true,
|
||||
"useAnimate": true,
|
||||
"useArrayDifference": true,
|
||||
"useArrayEvery": true,
|
||||
"useArrayFilter": true,
|
||||
"useArrayFind": true,
|
||||
"useArrayFindIndex": true,
|
||||
"useArrayFindLast": true,
|
||||
"useArrayIncludes": true,
|
||||
"useArrayJoin": true,
|
||||
"useArrayMap": true,
|
||||
"useArrayReduce": true,
|
||||
"useArraySome": true,
|
||||
"useArrayUnique": true,
|
||||
"useAsyncQueue": true,
|
||||
"useAsyncState": true,
|
||||
"useAttrs": true,
|
||||
"useBase64": true,
|
||||
"useBattery": true,
|
||||
"useBluetooth": true,
|
||||
"useBreakpoints": true,
|
||||
"useBroadcastChannel": true,
|
||||
"useBrowserLocation": true,
|
||||
"useCached": true,
|
||||
"useClipboard": true,
|
||||
"useClipboardItems": true,
|
||||
"useCloned": true,
|
||||
"useColorMode": true,
|
||||
"useConfirmDialog": true,
|
||||
"useCounter": true,
|
||||
"useCssModule": true,
|
||||
"useCssVar": true,
|
||||
"useCssVars": true,
|
||||
"useCurrentElement": true,
|
||||
"useCycleList": true,
|
||||
"useDark": true,
|
||||
"useDateFormat": true,
|
||||
"useDebounce": true,
|
||||
"useDebounceFn": true,
|
||||
"useDebouncedRefHistory": true,
|
||||
"useDeviceMotion": true,
|
||||
"useDeviceOrientation": true,
|
||||
"useDevicePixelRatio": true,
|
||||
"useDevicesList": true,
|
||||
"useDisplayMedia": true,
|
||||
"useDocumentVisibility": true,
|
||||
"useDraggable": true,
|
||||
"useDropZone": true,
|
||||
"useElementBounding": true,
|
||||
"useElementByPoint": true,
|
||||
"useElementHover": true,
|
||||
"useElementSize": true,
|
||||
"useElementVisibility": true,
|
||||
"useEventBus": true,
|
||||
"useEventListener": true,
|
||||
"useEventSource": true,
|
||||
"useEyeDropper": true,
|
||||
"useFavicon": true,
|
||||
"useFetch": true,
|
||||
"useFileDialog": true,
|
||||
"useFileSystemAccess": true,
|
||||
"useFocus": true,
|
||||
"useFocusWithin": true,
|
||||
"useFps": true,
|
||||
"useFullscreen": true,
|
||||
"useGamepad": true,
|
||||
"useGeolocation": true,
|
||||
"useId": true,
|
||||
"useIdle": true,
|
||||
"useImage": true,
|
||||
"useInfiniteScroll": true,
|
||||
"useIntersectionObserver": true,
|
||||
"useInterval": true,
|
||||
"useIntervalFn": true,
|
||||
"useKeyModifier": true,
|
||||
"useLastChanged": true,
|
||||
"useLink": true,
|
||||
"useLocalStorage": true,
|
||||
"useMagicKeys": true,
|
||||
"useManualRefHistory": true,
|
||||
"useMediaControls": true,
|
||||
"useMediaQuery": true,
|
||||
"useMemoize": true,
|
||||
"useMemory": true,
|
||||
"useModel": true,
|
||||
"useMounted": true,
|
||||
"useMouse": true,
|
||||
"useMouseInElement": true,
|
||||
"useMousePressed": true,
|
||||
"useMutationObserver": true,
|
||||
"useNavigatorLanguage": true,
|
||||
"useNetwork": true,
|
||||
"useNow": true,
|
||||
"useObjectUrl": true,
|
||||
"useOffsetPagination": true,
|
||||
"useOnline": true,
|
||||
"usePageLeave": true,
|
||||
"useParallax": true,
|
||||
"useParentElement": true,
|
||||
"usePerformanceObserver": true,
|
||||
"usePermission": true,
|
||||
"usePointer": true,
|
||||
"usePointerLock": true,
|
||||
"usePointerSwipe": true,
|
||||
"usePreferredColorScheme": true,
|
||||
"usePreferredContrast": true,
|
||||
"usePreferredDark": true,
|
||||
"usePreferredLanguages": true,
|
||||
"usePreferredReducedMotion": true,
|
||||
"usePrevious": true,
|
||||
"useRafFn": true,
|
||||
"useRefHistory": true,
|
||||
"useResizeObserver": true,
|
||||
"useRoute": true,
|
||||
"useRouter": true,
|
||||
"useScreenOrientation": true,
|
||||
"useScreenSafeArea": true,
|
||||
"useScriptTag": true,
|
||||
"useScroll": true,
|
||||
"useScrollLock": true,
|
||||
"useSessionStorage": true,
|
||||
"useShare": true,
|
||||
"useSlots": true,
|
||||
"useSorted": true,
|
||||
"useSpeechRecognition": true,
|
||||
"useSpeechSynthesis": true,
|
||||
"useStepper": true,
|
||||
"useStorage": true,
|
||||
"useStorageAsync": true,
|
||||
"useStyleTag": true,
|
||||
"useSupported": true,
|
||||
"useSwipe": true,
|
||||
"useTemplateRef": true,
|
||||
"useTemplateRefsList": true,
|
||||
"useTextDirection": true,
|
||||
"useTextSelection": true,
|
||||
"useTextareaAutosize": true,
|
||||
"useThrottle": true,
|
||||
"useThrottleFn": true,
|
||||
"useThrottledRefHistory": true,
|
||||
"useTimeAgo": true,
|
||||
"useTimeout": true,
|
||||
"useTimeoutFn": true,
|
||||
"useTimeoutPoll": true,
|
||||
"useTimestamp": true,
|
||||
"useTitle": true,
|
||||
"useToNumber": true,
|
||||
"useToString": true,
|
||||
"useToggle": true,
|
||||
"useTransition": true,
|
||||
"useUrlSearchParams": true,
|
||||
"useUserMedia": true,
|
||||
"useVModel": true,
|
||||
"useVModels": true,
|
||||
"useVibrate": true,
|
||||
"useVirtualList": true,
|
||||
"useWakeLock": true,
|
||||
"useWebNotification": true,
|
||||
"useWebSocket": true,
|
||||
"useWebWorker": true,
|
||||
"useWebWorkerFn": true,
|
||||
"useWindowFocus": true,
|
||||
"useWindowScroll": true,
|
||||
"useWindowSize": true,
|
||||
"watch": true,
|
||||
"watchArray": true,
|
||||
"watchAtMost": true,
|
||||
"watchDebounced": true,
|
||||
"watchDeep": true,
|
||||
"watchEffect": true,
|
||||
"watchIgnorable": true,
|
||||
"watchImmediate": true,
|
||||
"watchOnce": true,
|
||||
"watchPausable": true,
|
||||
"watchPostEffect": true,
|
||||
"watchSyncEffect": true,
|
||||
"watchThrottled": true,
|
||||
"watchTriggerable": true,
|
||||
"watchWithFilter": true,
|
||||
"whenever": true
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
node: true
|
||||
},
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:vue/vue3-recommended'
|
||||
],
|
||||
parser: 'vue-eslint-parser',
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
parser: '@typescript-eslint/parser',
|
||||
sourceType: 'module'
|
||||
},
|
||||
plugins: ['@typescript-eslint', 'vue'],
|
||||
rules: {
|
||||
// Vue 规则
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'vue/no-v-html': 'off',
|
||||
|
||||
// TypeScript 规则
|
||||
'@typescript-eslint/no-explicit-any': 'warn',
|
||||
'@typescript-eslint/no-unused-vars': ['error', {
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_'
|
||||
}],
|
||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||
|
||||
// 通用规则
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
'prefer-const': 'error',
|
||||
'no-var': 'error'
|
||||
}
|
||||
}
|
||||
+102
-33
@@ -1,38 +1,107 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Environment variables
|
||||
# PyInstaller
|
||||
*.manifest
|
||||
.spec
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
tests/.pytest_cache/
|
||||
tests/*.png
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.production
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Logs
|
||||
logs/
|
||||
*.log
|
||||
|
||||
# Database
|
||||
*.db
|
||||
*.sqlite
|
||||
*.sqlite3
|
||||
|
||||
# Uploads
|
||||
uploads/*
|
||||
!uploads/.gitkeep
|
||||
|
||||
# Alembic
|
||||
alembic/versions/*.py
|
||||
!alembic/versions/__init__.py
|
||||
|
||||
# MyPy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre
|
||||
.pyre/
|
||||
|
||||
# Jupyter
|
||||
.ipynb_checkpoints
|
||||
|
||||
# PyCharm
|
||||
.idea/
|
||||
|
||||
# VSCode
|
||||
.vscode/
|
||||
|
||||
# Testing
|
||||
coverage
|
||||
.nyc_output/
|
||||
test_*.py
|
||||
*_test.py
|
||||
tests/
|
||||
|
||||
# Documentation
|
||||
*.md
|
||||
@@ -41,7 +110,6 @@ PHASE*.md
|
||||
DELIVERY*.md
|
||||
SUMMARY*.md
|
||||
!README.md
|
||||
!src/components/charts/README.md
|
||||
|
||||
# Temporary files
|
||||
*.tmp
|
||||
@@ -49,7 +117,8 @@ SUMMARY*.md
|
||||
*.bak
|
||||
*.backup
|
||||
|
||||
# Lock files
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
pnpm-lock.yaml
|
||||
# Docker
|
||||
.dockerignore
|
||||
|
||||
# Test reports
|
||||
test_reports/
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"printWidth": 100,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "none",
|
||||
"arrowParens": "avoid",
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
图表组件库文件清单
|
||||
===================
|
||||
|
||||
核心组件
|
||||
--------
|
||||
src/components/charts/BaseChart.vue
|
||||
src/components/charts/PieChart.vue
|
||||
src/components/charts/BarChart.vue
|
||||
src/components/charts/LineChart.vue
|
||||
src/components/charts/GaugeChart.vue
|
||||
src/components/charts/FunnelChart.vue
|
||||
|
||||
业务图表组件
|
||||
------------
|
||||
src/components/charts/business/AssetStatusChart.vue
|
||||
src/components/charts/business/AssetDistributionChart.vue
|
||||
src/components/charts/business/AssetValueTrendChart.vue
|
||||
src/components/charts/business/AssetUtilizationChart.vue
|
||||
|
||||
统计卡片组件
|
||||
------------
|
||||
src/components/statistics/StatCard.vue
|
||||
src/components/statistics/StatCardGroup.vue
|
||||
|
||||
Composables
|
||||
-----------
|
||||
src/composables/useECharts.ts
|
||||
src/composables/useChartData.ts
|
||||
|
||||
工具函数
|
||||
--------
|
||||
src/utils/echarts.ts
|
||||
src/utils/echarts/performance.ts
|
||||
|
||||
类型定义
|
||||
--------
|
||||
src/types/charts.ts
|
||||
src/components/charts/charts.d.ts
|
||||
|
||||
组件导出
|
||||
--------
|
||||
src/components/charts/index.ts
|
||||
src/components/charts/README.md
|
||||
src/components/statistics/index.ts
|
||||
|
||||
文档
|
||||
----
|
||||
CHARTS_README.md - 完整使用文档
|
||||
CHARTS_DELIVERY.md - 交付文档
|
||||
CHARTS_QUICKSTART.md - 快速开始指南
|
||||
CHARTS_SUMMARY.md - 项目总结
|
||||
CHARTS_FILES.txt - 本文件
|
||||
|
||||
示例和测试
|
||||
----------
|
||||
src/views/examples/ChartsExample.vue
|
||||
tests/unit/components/PieChart.test.ts
|
||||
tests/unit/composables/useECharts.test.ts
|
||||
|
||||
路由配置
|
||||
--------
|
||||
src/router/index.ts (已添加示例页面路由)
|
||||
|
||||
总计:25 个文件
|
||||
+21
-7
@@ -1,12 +1,26 @@
|
||||
FROM nginx:alpine
|
||||
FROM python:3.10-slim
|
||||
|
||||
# 复制构建产物
|
||||
COPY dist /usr/share/nginx/html
|
||||
WORKDIR /app
|
||||
|
||||
# 复制Nginx配置
|
||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||
# 安装系统依赖
|
||||
RUN apt-get update && apt-get install -y \
|
||||
gcc \
|
||||
postgresql-client \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 复制依赖文件
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# 复制应用代码
|
||||
COPY . .
|
||||
|
||||
# 创建必要的目录
|
||||
RUN mkdir -p logs uploads uploads/qrcodes
|
||||
|
||||
# 暴露端口
|
||||
EXPOSE 3000
|
||||
EXPOSE 8001
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
# 启动命令
|
||||
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8001"]
|
||||
|
||||
@@ -1,217 +1,284 @@
|
||||
# 资产管理系统前端
|
||||
# 资产管理系统 - 后端API
|
||||
|
||||
> 基于 Vue 3 + TypeScript + Element Plus 构建的现代化资产管理系统前端应用
|
||||
基于 FastAPI + SQLAlchemy + PostgreSQL 的企业级资产管理系统后端API
|
||||
|
||||
## 技术栈
|
||||
|
||||
- **框架**: Vue 3.4+ (Composition API + `<script setup>`)
|
||||
- **语言**: TypeScript 5.0+
|
||||
- **构建工具**: Vite 5
|
||||
- **UI组件库**: Element Plus
|
||||
- **状态管理**: Pinia
|
||||
- **路由**: Vue Router 4
|
||||
- **HTTP客户端**: Axios
|
||||
- **表单验证**: VeeValidate + Yup
|
||||
- **图表**: ECharts
|
||||
- **工具库**: dayjs, lodash-es, qrcode
|
||||
- **组合式函数**: @vueuse/core
|
||||
- **代码规范**: ESLint + Prettier
|
||||
- **测试**: Vitest
|
||||
- **框架**: FastAPI 0.104+
|
||||
- **ORM**: SQLAlchemy 2.0+ (异步模式)
|
||||
- **数据库**: PostgreSQL 14+
|
||||
- **缓存**: Redis
|
||||
- **认证**: JWT (python-jose)
|
||||
- **密码加密**: bcrypt
|
||||
- **数据验证**: Pydantic v2
|
||||
- **数据库迁移**: Alembic
|
||||
- **测试**: pytest
|
||||
- **ASGI服务器**: Uvicorn
|
||||
|
||||
## 功能特性
|
||||
|
||||
### Phase 1: 项目基础搭建 ✅
|
||||
- [x] Vite + Vue 3项目初始化
|
||||
- [x] TypeScript配置
|
||||
- [x] ESLint + Prettier配置
|
||||
- [x] 路由配置(Vue Router 4)
|
||||
- [x] 状态管理(Pinia)
|
||||
- [x] Axios请求封装
|
||||
- [x] UI主题配置(青灰配色 #475569)
|
||||
|
||||
### Phase 2: 认证与布局 ✅
|
||||
- [x] 登录页面(Login.vue)
|
||||
- [x] 主应用布局(MainLayout.vue)
|
||||
- [x] 侧边菜单组件
|
||||
- [x] 顶部导航栏
|
||||
- [x] 认证状态管理
|
||||
- [x] 路由守卫
|
||||
|
||||
### Phase 3: 后台管理模块(开发中)
|
||||
- [ ] 用户管理页面
|
||||
- [ ] 角色权限页面
|
||||
- [ ] 设备类型管理页面
|
||||
- [ ] 动态表单设计器
|
||||
- [ ] 机构网点管理页面
|
||||
|
||||
### Phase 4: 资产管理模块(部分完成)
|
||||
- [x] 资产列表页面
|
||||
- [x] 资产详情对话框
|
||||
- [x] 资产入库页面
|
||||
- [x] 资产编辑对话框
|
||||
- [ ] 批量导入组件
|
||||
- [ ] 批量导出组件
|
||||
- [ ] 扫码查询页面
|
||||
- [ ] 二维码对话框
|
||||
- [ ] 资产状态追踪组件
|
||||
|
||||
### Phase 5: 资产分配模块(待开发)
|
||||
- [ ] 分配单列表页面
|
||||
- [ ] 创建分配单对话框
|
||||
- [ ] 审批对话框
|
||||
- [ ] 资产选择器
|
||||
|
||||
### Phase 6: 维修与统计(待开发)
|
||||
- [ ] 维修管理页面
|
||||
- [ ] 统计报表页面
|
||||
- [ ] ECharts图表集成
|
||||
|
||||
### Phase 7: 系统管理(待开发)
|
||||
- [ ] 系统配置页面
|
||||
- [ ] 操作日志页面
|
||||
- [ ] 消息通知组件
|
||||
- [ ] 个人中心页面
|
||||
|
||||
## 目录结构
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
src/
|
||||
├── api/ # API接口
|
||||
│ ├── request.ts # Axios封装
|
||||
│ ├── auth.ts # 认证接口
|
||||
│ ├── assets.ts # 资产接口
|
||||
│ ├── users.ts # 用户接口
|
||||
│ └── index.ts # 统一导出
|
||||
├── assets/ # 静态资源
|
||||
│ └── styles/ # 全局样式
|
||||
│ ├── variables.scss # 主题变量
|
||||
│ └── index.scss # 全局样式
|
||||
├── components/ # 通用组件
|
||||
├── composables/ # 组合式函数
|
||||
│ ├── usePagination.ts # 分页
|
||||
│ └── useTable.ts # 表格
|
||||
├── layouts/ # 布局组件
|
||||
│ └── MainLayout.vue # 主布局
|
||||
├── router/ # 路由配置
|
||||
│ └── index.ts
|
||||
├── stores/ # Pinia状态管理
|
||||
│ ├── modules/
|
||||
│ │ ├── user.ts # 用户状态
|
||||
│ │ └── app.ts # 应用状态
|
||||
│ └── index.ts
|
||||
├── types/ # TypeScript类型定义
|
||||
│ └── index.ts
|
||||
├── utils/ # 工具函数
|
||||
│ ├── auth.ts # 认证工具
|
||||
│ ├── format.ts # 格式化工具
|
||||
│ ├── validate.ts # 验证工具
|
||||
│ └── constants.ts # 常量定义
|
||||
├── views/ # 页面组件
|
||||
│ ├── auth/ # 认证相关
|
||||
│ │ └── Login.vue
|
||||
│ ├── admin/ # 后台管理
|
||||
│ │ ├── UserManagement.vue
|
||||
│ │ ├── RoleManagement.vue
|
||||
│ │ ├── DeviceTypeManagement.vue
|
||||
│ │ └── OrganizationManagement.vue
|
||||
│ ├── assets/ # 资产管理
|
||||
│ │ ├── AssetList.vue
|
||||
│ │ ├── AssetCreate.vue
|
||||
│ │ ├── AssetAllocation.vue
|
||||
│ │ ├── AssetScan.vue
|
||||
│ │ ├── MaintenanceManagement.vue
|
||||
│ │ ├── StatisticsDashboard.vue
|
||||
│ │ └── components/ # 资产相关组件
|
||||
│ │ ├── AssetDetailDialog.vue
|
||||
│ │ ├── AssetEditDialog.vue
|
||||
│ │ └── QrcodeDialog.vue
|
||||
│ └── error/ # 错误页面
|
||||
│ └── 404.vue
|
||||
├── App.vue # 根组件
|
||||
└── main.ts # 应用入口
|
||||
asset_management_backend/
|
||||
├── app/
|
||||
│ ├── api/ # API路由
|
||||
│ │ └── v1/
|
||||
│ │ ├── auth.py # 认证相关API
|
||||
│ │ └── __init__.py
|
||||
│ ├── core/ # 核心模块
|
||||
│ │ ├── config.py # 配置管理
|
||||
│ │ ├── security.py # 安全相关
|
||||
│ │ ├── deps.py # 依赖注入
|
||||
│ │ ├── exceptions.py # 自定义异常
|
||||
│ │ └── response.py # 统一响应
|
||||
│ ├── crud/ # 数据库CRUD操作
|
||||
│ │ ├── user.py # 用户CRUD
|
||||
│ │ └── ...
|
||||
│ ├── db/ # 数据库相关
|
||||
│ │ ├── base.py # 模型基类
|
||||
│ │ └── session.py # 会话管理
|
||||
│ ├── models/ # SQLAlchemy模型
|
||||
│ │ ├── user.py # 用户模型
|
||||
│ │ └── ...
|
||||
│ ├── schemas/ # Pydantic Schema
|
||||
│ │ ├── user.py # 用户Schema
|
||||
│ │ └── ...
|
||||
│ ├── services/ # 业务逻辑层
|
||||
│ │ ├── auth_service.py # 认证服务
|
||||
│ │ └── ...
|
||||
│ └── utils/ # 工具函数
|
||||
│ └── ...
|
||||
├── alembic/ # 数据库迁移
|
||||
│ └── versions/
|
||||
├── tests/ # 测试
|
||||
├── logs/ # 日志文件
|
||||
├── uploads/ # 上传文件
|
||||
├── .env.example # 环境变量示例
|
||||
├── requirements.txt # 依赖包
|
||||
├── run.py # 开发服务器启动脚本
|
||||
└── README.md # 项目说明
|
||||
```
|
||||
|
||||
## 开发指南
|
||||
## 快速开始
|
||||
|
||||
### 安装依赖
|
||||
### 1. 环境准备
|
||||
|
||||
确保已安装:
|
||||
- Python 3.10+
|
||||
- PostgreSQL 14+
|
||||
- Redis
|
||||
|
||||
### 2. 安装依赖
|
||||
|
||||
```bash
|
||||
npm install
|
||||
# 创建虚拟环境
|
||||
python -m venv venv
|
||||
|
||||
# 激活虚拟环境
|
||||
# Windows:
|
||||
venv\Scripts\activate
|
||||
# Linux/Mac:
|
||||
source venv/bin/activate
|
||||
|
||||
# 安装依赖包
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 启动开发服务器
|
||||
### 3. 配置环境变量
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# 复制环境变量示例文件
|
||||
cp .env.example .env
|
||||
|
||||
# 编辑 .env 文件,配置数据库等信息
|
||||
```
|
||||
|
||||
访问 `http://localhost:3000`
|
||||
|
||||
### 构建生产版本
|
||||
### 4. 初始化数据库
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
# 创建数据库
|
||||
createdb asset_management
|
||||
|
||||
# 运行数据库迁移
|
||||
alembic upgrade head
|
||||
|
||||
# 或在开发环境直接初始化(会自动创建表)
|
||||
# 修改 app/main.py 中的 lifespan 函数,取消注释 init_db()
|
||||
```
|
||||
|
||||
### 代码检查
|
||||
### 5. 启动服务
|
||||
|
||||
```bash
|
||||
npm run lint
|
||||
# 开发模式(支持热重载)
|
||||
python run.py
|
||||
|
||||
# 或使用 uvicorn
|
||||
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
|
||||
```
|
||||
|
||||
### 代码格式化
|
||||
### 6. 访问API文档
|
||||
|
||||
```bash
|
||||
npm run format
|
||||
```
|
||||
启动成功后,访问以下地址:
|
||||
|
||||
### 运行测试
|
||||
- Swagger UI: http://localhost:8000/docs
|
||||
- ReDoc: http://localhost:8000/redoc
|
||||
- OpenAPI JSON: http://localhost:8000/openapi.json
|
||||
|
||||
```bash
|
||||
npm run test
|
||||
```
|
||||
## API端点
|
||||
|
||||
## 环境配置
|
||||
### 认证模块
|
||||
|
||||
### 开发环境 (.env.development)
|
||||
```
|
||||
VITE_API_BASE_URL=http://localhost:8000/api/v1
|
||||
VITE_APP_TITLE=资产管理系统
|
||||
```
|
||||
- `POST /api/v1/auth/login` - 用户登录
|
||||
- `POST /api/v1/auth/refresh` - 刷新令牌
|
||||
- `POST /api/v1/auth/logout` - 用户登出
|
||||
- `PUT /api/v1/auth/change-password` - 修改密码
|
||||
- `GET /api/v1/auth/captcha` - 获取验证码
|
||||
|
||||
### 生产环境 (.env.production)
|
||||
```
|
||||
VITE_API_BASE_URL=https://api.yourcompany.com/api/v1
|
||||
VITE_APP_TITLE=资产管理系统
|
||||
```
|
||||
### 用户管理
|
||||
|
||||
## 主题定制
|
||||
- `GET /api/v1/users` - 用户列表
|
||||
- `POST /api/v1/users` - 创建用户
|
||||
- `GET /api/v1/users/{user_id}` - 获取用户详情
|
||||
- `PUT /api/v1/users/{user_id}` - 更新用户
|
||||
- `DELETE /api/v1/users/{user_id}` - 删除用户
|
||||
- `POST /api/v1/users/{user_id}/reset-password` - 重置密码
|
||||
- `GET /api/v1/users/me` - 获取当前用户信息
|
||||
|
||||
主题色采用青灰配色方案 (#475569),在 `src/assets/styles/variables.scss` 中可以自定义主题变量。
|
||||
### 角色权限
|
||||
|
||||
## API接口规范
|
||||
- `GET /api/v1/roles` - 角色列表
|
||||
- `POST /api/v1/roles` - 创建角色
|
||||
- `GET /api/v1/roles/{role_id}` - 获取角色详情
|
||||
- `PUT /api/v1/roles/{role_id}` - 更新角色
|
||||
- `DELETE /api/v1/roles/{role_id}` - 删除角色
|
||||
- `GET /api/v1/permissions/tree` - 权限树列表
|
||||
|
||||
详见 `complete_api_reference.md` 文档。
|
||||
更多API请查看Swagger文档。
|
||||
|
||||
## 开发规范
|
||||
|
||||
详见 `development_standards_guide.md` 文档。
|
||||
请参考 `development_standards_guide.md` 文件。
|
||||
|
||||
## 页面原型
|
||||
### 代码风格
|
||||
|
||||
详见 `frontend_page_prototypes.md` 文档。
|
||||
- 遵循 PEP 8 规范
|
||||
- 使用 Black 进行代码格式化
|
||||
- 使用 isort 管理导入
|
||||
- 使用 flake8 进行代码检查
|
||||
- 使用 mypy 进行类型检查
|
||||
|
||||
## 浏览器支持
|
||||
### 提交规范
|
||||
|
||||
- Chrome >= 90
|
||||
- Firefox >= 88
|
||||
- Safari >= 14
|
||||
- Edge >= 90
|
||||
遵循 Conventional Commits 规范:
|
||||
|
||||
## 作者
|
||||
```
|
||||
feat: 新功能
|
||||
fix: Bug修复
|
||||
docs: 文档更新
|
||||
style: 代码格式
|
||||
refactor: 重构
|
||||
perf: 性能优化
|
||||
test: 测试
|
||||
chore: 构建/工具
|
||||
```
|
||||
|
||||
老王
|
||||
示例:
|
||||
```bash
|
||||
git commit -m "feat(auth): 实现用户登录功能"
|
||||
git commit -m "fix(asset): 修复资产状态转换问题"
|
||||
```
|
||||
|
||||
## 测试
|
||||
|
||||
```bash
|
||||
# 运行所有测试
|
||||
pytest
|
||||
|
||||
# 运行特定测试文件
|
||||
pytest tests/api/test_auth.py
|
||||
|
||||
# 生成覆盖率报告
|
||||
pytest --cov=app --cov-report=html
|
||||
|
||||
# 查看覆盖率报告
|
||||
open htmlcov/index.html
|
||||
```
|
||||
|
||||
## 数据库迁移
|
||||
|
||||
```bash
|
||||
# 创建新的迁移
|
||||
alembic revision --autogenerate -m "描述信息"
|
||||
|
||||
# 执行迁移
|
||||
alembic upgrade head
|
||||
|
||||
# 回滚迁移
|
||||
alembic downgrade -1
|
||||
|
||||
# 查看迁移历史
|
||||
alembic history
|
||||
|
||||
# 查看当前版本
|
||||
alembic current
|
||||
```
|
||||
|
||||
## 生产部署
|
||||
|
||||
### 使用 Docker
|
||||
|
||||
```bash
|
||||
# 构建镜像
|
||||
docker build -t asset-management-backend .
|
||||
|
||||
# 运行容器
|
||||
docker run -d \
|
||||
--name asset-backend \
|
||||
-p 8000:8000 \
|
||||
--env-file .env \
|
||||
asset-management-backend
|
||||
```
|
||||
|
||||
### 使用 Gunicorn + Uvicorn
|
||||
|
||||
```bash
|
||||
pip install gunicorn
|
||||
|
||||
gunicorn app.main:app \
|
||||
--workers 4 \
|
||||
--worker-class uvicorn.workers.UvicornWorker \
|
||||
--bind 0.0.0.0:8000 \
|
||||
--access-logfile - \
|
||||
--error-logfile -
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 数据库连接失败
|
||||
|
||||
检查 `DATABASE_URL` 是否正确配置,确保PostgreSQL服务正在运行。
|
||||
|
||||
### Redis连接失败
|
||||
|
||||
检查 `REDIS_URL` 是否正确配置,确保Redis服务正在运行。
|
||||
|
||||
### Token验证失败
|
||||
|
||||
确保 `SECRET_KEY` 配置正确,并检查Token是否过期。
|
||||
|
||||
## 贡献指南
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 创建功能分支 (`git checkout -b feature/AmazingFeature`)
|
||||
3. 提交更改 (`git commit -m 'feat: Add some AmazingFeature'`)
|
||||
4. 推送到分支 (`git push origin feature/AmazingFeature`)
|
||||
5. 创建 Pull Request
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT
|
||||
本项目采用 MIT 许可证。
|
||||
|
||||
## 联系方式
|
||||
|
||||
- 项目负责人: 老王
|
||||
- 创建时间: 2025-01-24
|
||||
- 版本: v1.0.0
|
||||
|
||||
@@ -207,6 +207,9 @@ class AuthService:
|
||||
Returns:
|
||||
包含captcha_key和captcha_base64的字典
|
||||
"""
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
from app.utils.redis_client import redis_client
|
||||
import random
|
||||
import string
|
||||
@@ -214,8 +217,10 @@ class AuthService:
|
||||
from io import BytesIO
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
|
||||
try:
|
||||
# 生成4位随机验证码,使用更清晰的字符组合(排除易混淆的字符)
|
||||
captcha_text = ''.join(random.choices('23456789', k=4)) # 排除0、1
|
||||
logger.info(f"生成验证码: {captcha_text}")
|
||||
|
||||
# 生成验证码图片
|
||||
width, height = 200, 80 # 增大图片尺寸
|
||||
@@ -260,6 +265,7 @@ class AuthService:
|
||||
|
||||
# 生成captcha_key
|
||||
captcha_key = ''.join(random.choices(string.ascii_letters + string.digits, k=32))
|
||||
logger.info(f"生成验证码Key: {captcha_key}")
|
||||
|
||||
# 存储到Redis,5分钟过期
|
||||
await redis_client.setex(
|
||||
@@ -267,11 +273,15 @@ class AuthService:
|
||||
300,
|
||||
captcha_text
|
||||
)
|
||||
logger.info(f"验证码已存储到Redis: captcha:{captcha_key}, 值: {captcha_text}")
|
||||
|
||||
return {
|
||||
"captcha_key": captcha_key,
|
||||
"captcha_base64": f"data:image/png;base64,{image_base64}"
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"生成验证码失败: {str(e)}", exc_info=True)
|
||||
raise
|
||||
|
||||
async def _verify_captcha(self, captcha_key: str, captcha: str) -> bool:
|
||||
"""
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user