diff --git a/.docker-compose/nginx/conf.d/my.conf b/.docker-compose/nginx/conf.d/my.conf new file mode 100644 index 0000000..9a1685d --- /dev/null +++ b/.docker-compose/nginx/conf.d/my.conf @@ -0,0 +1,26 @@ +server { + listen 8080; + server_name localhost; + + #charset koi8-r; + #access_log logs/host.access.log main; + + location / { + root /usr/share/nginx/html; + add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; + try_files $uri $uri/ /index.html; + } + + location /api { + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + rewrite ^/api/(.*)$ /$1 break; #重写 + proxy_pass http://177.7.0.12:8888; # 设置代理服务器的协议和地址 + } + + location /api/swagger/index.html { + proxy_pass http://127.0.0.1:8888/swagger/index.html; + } + } \ No newline at end of file diff --git a/.docker-compose/nginx/conf.d/nginx.conf b/.docker-compose/nginx/conf.d/nginx.conf new file mode 100644 index 0000000..29f68b8 --- /dev/null +++ b/.docker-compose/nginx/conf.d/nginx.conf @@ -0,0 +1,32 @@ +server { + listen 80; + server_name localhost; + + #charset koi8-r; + #access_log logs/host.access.log main; + + location / { + root /usr/share/nginx/html/dist; + add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; + try_files $uri $uri/ /index.html; + } + + location /api { + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + rewrite ^/api/(.*)$ /$1 break; #重写 + proxy_pass http://127.0.0.1:8888; # 设置代理服务器的协议和地址 + } + location /form-generator { + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_pass http://127.0.0.1:8888; + } + location /api/swagger/index.html { + proxy_pass http://127.0.0.1:8888/swagger/index.html; + } + } \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..31f329c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM node:16 + +WORKDIR /gva_web/ +COPY . . + +RUN yarn && yarn build + +FROM nginx:alpine +LABEL MAINTAINER="SliverHorn@sliver_horn@qq.com" + +COPY .docker-compose/nginx/conf.d/my.conf /etc/nginx/conf.d/my.conf +COPY --from=0 /gva_web/dist /usr/share/nginx/html +RUN cat /etc/nginx/nginx.conf +RUN cat /etc/nginx/conf.d/my.conf +RUN ls -al /usr/share/nginx/html diff --git a/README.md b/README.md new file mode 100644 index 0000000..2245bcd --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +# web + +## Project setup +``` +npm install +``` + +### Compiles and hot-reloads for development +``` +npm run serve +``` + +### Compiles and minifies for production +``` +npm run build +``` + +### Run your tests +``` +npm run test +``` + +### Lints and fixes files +``` +npm run lint +``` + + +整理代码结构 +``` lua +web + ├── babel.config.js + ├── Dockerfile + ├── favicon.ico + ├── index.html -- 主页面 + ├── limit.js -- 助手代码 + ├── package.json -- 包管理器代码 + ├── src -- 源代码 + │ ├── api -- api 组 + │ ├── App.vue -- 主页面 + │ ├── assets -- 静态资源 + │ ├── components -- 全局组件 + │ ├── core -- gva 组件包 + │ │ ├── config.js -- gva网站配置文件 + │ │ └── global.js -- 统一导入文件 + │ ├── directive -- v-auth 注册文件 + │ ├── main.js -- 主文件 + │ ├── permission.js -- 路由中间件 + │ ├── pinia -- pinia 状态管理器,取代vuex + │ │ ├── index.js -- 入口文件 + │ │ └── modules -- modules + │ │ ├── dictionary.js + │ │ ├── router.js + │ │ └── user.js + │ ├── router -- 路由声明文件 + │ │ └── index.js + │ ├── style -- 全局样式 + │ │ ├── base.scss + │ │ ├── basics.scss + │ │ ├── element_visiable.scss -- 此处可以全局覆盖 element-plus 样式 + │ │ ├── iconfont.css -- 顶部几个icon的样式文件 + │ │ ├── main.scss + │ │ ├── mobile.scss + │ │ └── newLogin.scss + │ ├── utils -- 方法包库 + │ │ ├── asyncRouter.js -- 动态路由相关 + │ │ ├── bus.js -- 全局mitt声明文件 + │ │ ├── date.js -- 日期相关 + │ │ ├── dictionary.js -- 获取字典方法 + │ │ ├── downloadImg.js -- 下载图片方法 + │ │ ├── format.js -- 格式整理相关 + │ │ ├── image.js -- 图片相关方法 + │ │ ├── page.js -- 设置页面标题 + │ │ ├── request.js -- 请求 + │ │ └── stringFun.js -- 字符串文件 + | ├── view -- 主要view代码 + | | ├── about -- 关于我们 + | | ├── dashboard -- 面板 + | | ├── error -- 错误 + | | ├── example --上传案例 + | | ├── iconList -- icon列表 + | | ├── init -- 初始化数据 + | | | ├── index -- 新版本 + | | | ├── init -- 旧版本 + | | ├── layout -- layout约束页面 + | | | ├── aside + | | | ├── bottomInfo -- bottomInfo + | | | ├── screenfull -- 全屏设置 + | | | ├── setting -- 系统设置 + | | | └── index.vue -- base 约束 + | | ├── login --登录 + | | ├── person --个人中心 + | | ├── superAdmin -- 超级管理员操作 + | | ├── system -- 系统检测页面 + | | ├── systemTools -- 系统配置相关页面 + | | └── routerHolder.vue -- page 入口页面 + ├── vite.config.js -- vite 配置文件 + └── yarn.lock + +``` diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000..ee520ce Binary files /dev/null and b/favicon.ico differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..4ed1384 --- /dev/null +++ b/index.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..10afc57 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "baseUrl": "./", + "paths": { + "@/*": ["src/*"], + } + }, + "exclude": ["node_modules", "dist"], + "include": ["src/**/*"] + } \ No newline at end of file diff --git a/limit.js b/limit.js new file mode 100644 index 0000000..6ba9d46 --- /dev/null +++ b/limit.js @@ -0,0 +1,37 @@ +// 运行项目前通过node执行此脚本 (此脚本与 node_modules 目录同级) +const fs = require('fs') +const path = require('path') +const wfPath = path.resolve(__dirname, './node_modules/.bin') + +fs.readdir(wfPath, (err, files) => { + if (err) { + console.log(err) + } else { + if (files.length !== 0) { + files.forEach((item) => { + if (item.split('.')[1] === 'cmd') { + replaceStr(`${wfPath}/${item}`, /"%_prog%"/, '%_prog%') + } + }) + } + } +}) + +// 参数:[文件路径、 需要修改的字符串、修改后的字符串] (替换对应文件内字符串的公共函数) +function replaceStr(filePath, sourceRegx, targetSrt) { + fs.readFile(filePath, (err, data) => { + if (err) { + console.log(err) + } else { + let str = data.toString() + str = str.replace(sourceRegx, targetSrt) + fs.writeFile(filePath, str, (err) => { + if (err) { + console.log(err) + } else { + console.log('\x1B[42m%s\x1B[0m', '文件修改成功') + } + }) + } + }) +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..ae000fe --- /dev/null +++ b/package.json @@ -0,0 +1,61 @@ +{ + "name": "web-admin", + "version": "2.6.1", + "private": true, + "scripts": { + "serve": "vite --host --mode development", + "build": "vite build --mode production", + "limit-build": "npm install increase-memory-limit-fixbug cross-env -g && npm run fix-memory-limit && node ./limit && npm run build", + "preview": "vite preview", + "fix-memory-limit": "cross-env LIMIT=4096 increase-memory-limit" + }, + "dependencies": { + "@element-plus/icons-vue": "^2.1.0", + "@vue-office/docx": "^1.3.0", + "@vue-office/excel": "^1.4.5", + "@vue-office/pdf": "^1.5.3", + "@vueuse/core": "^10.7.2", + "@wangeditor/editor": "^5.1.23", + "@wangeditor/editor-for-vue": "^5.1.12", + "axios": "^1.4.0", + "core-js": "^3.31.1", + "echarts": "5.4.3", + "element-plus": "^2.3.8", + "highlight.js": "^11.8.0", + "js-cookie": "^3.0.5", + "marked": "4.3.0", + "mitt": "^3.0.1", + "nprogress": "^0.2.0", + "path": "^0.12.7", + "pinia": "^2.1.4", + "qs": "^6.11.2", + "screenfull": "^6.0.2", + "spark-md5": "^3.0.2", + "tailwindcss": "^3.3.3", + "vue": "^3.4.21", + "vue-router": "^4.2.4" + }, + "devDependencies": { + "@babel/eslint-parser": "^7.22.9", + "@vitejs/plugin-legacy": "^4.1.0", + "@vitejs/plugin-vue": "^4.2.3", + "@vue/cli-plugin-babel": "~5.0.8", + "@vue/cli-plugin-eslint": "~5.0.8", + "@vue/cli-plugin-router": "~5.0.8", + "@vue/cli-plugin-vuex": "~5.0.8", + "@vue/cli-service": "~5.0.8", + "@vue/compiler-sfc": "^3.3.4", + "babel-plugin-import": "^1.13.6", + "chalk": "^4.1.2", + "dotenv": "^16.3.1", + "eslint": "^8.49.0", + "eslint-plugin-vue": "^9.15.1", + "sass": "^1.54.0", + "terser": "^5.19.1", + "unplugin-auto-import": "^0.16.6", + "unplugin-vue-components": "^0.25.1", + "vite": "^4.4.6", + "vite-plugin-banner": "^0.7.0", + "vite-plugin-importer": "^0.2.5" + } +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..33ad091 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..9931524 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,33 @@ + + + + diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..36862e2 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,20 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + "./index.html", + "./src/**/*.{vue,js,ts,jsx,tsx}", + ], + important: true, + theme: { + extend: { + backgroundColor: { + "main": "#F5F5F5", + } + }, + }, + plugins: [], + corePlugins: { + preflight: false + } +} + diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..67f73a0 --- /dev/null +++ b/vite.config.js @@ -0,0 +1,115 @@ +import legacyPlugin from '@vitejs/plugin-legacy' +import AutoImport from 'unplugin-auto-import/vite' +import Components from 'unplugin-vue-components/vite' +import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' +import Banner from 'vite-plugin-banner' +import * as path from 'path' +import * as dotenv from 'dotenv' +import * as fs from 'fs' +import vuePlugin from '@vitejs/plugin-vue' +import GvaPosition from './vitePlugin/gvaPosition' +import GvaPositionServer from './vitePlugin/codeServer' +import fullImportPlugin from './vitePlugin/fullImport/fullImport.js' +import { svgBuilder } from './vitePlugin/svgIcon/svgIcon.js' +// @see https://cn.vitejs.dev/config/ +export default ({ + command, + mode +}) => { + const NODE_ENV = mode || 'development' + const envFiles = [ + `.env.${NODE_ENV}` + ] + for (const file of envFiles) { + const envConfig = dotenv.parse(fs.readFileSync(file)) + for (const k in envConfig) { + process.env[k] = envConfig[k] + } + } + + const timestamp = Date.parse(new Date()) + + const optimizeDeps = {} + + const alias = { + '@': path.resolve(__dirname, './src'), + 'vue$': 'vue/dist/vue.runtime.esm-bundler.js', + } + + const esbuild = {} + + const rollupOptions = { + output: { + entryFileNames: 'assets/087AC4D233B64EB0[name].[hash].js', + chunkFileNames: 'assets/087AC4D233B64EB0[name].[hash].js', + assetFileNames: 'assets/087AC4D233B64EB0[name].[hash].[ext]', + }, + } + + const config = { + base: './', // index.html文件所在位置 + root: './', // js导入的资源路径,src + resolve: { + alias, + }, + define: { + 'process.env': {} + }, + server: { + // 如果使用docker-compose开发模式,设置为false + open: true, + port: process.env.VITE_CLI_PORT, + proxy: { + // 把key的路径代理到target位置 + // detail: https://cli.vuejs.org/config/#devserver-proxy + [process.env.VITE_BASE_API]: { // 需要代理的路径 例如 '/api' + target: `${process.env.VITE_BASE_PATH}:${process.env.VITE_SERVER_PORT}/`, // 代理到 目标路径 + changeOrigin: false, + rewrite: path => path.replace(new RegExp('^' + process.env.VITE_BASE_API), ''), + } + }, + }, + build: { + minify: 'terser', // 是否进行压缩,boolean | 'terser' | 'esbuild',默认使用terser + manifest: false, // 是否产出manifest.json + sourcemap: false, // 是否产出sourcemap.json + outDir: 'dist', // 产出目录 + rollupOptions, + }, + esbuild, + optimizeDeps, + plugins: [ + process.env.VITE_POSITION === 'open' && GvaPositionServer(), + process.env.VITE_POSITION === 'open' && GvaPosition(), + legacyPlugin({ + targets: ['Android > 39', 'Chrome >= 60', 'Safari >= 10.1', 'iOS >= 10.3', 'Firefox >= 54', 'Edge >= 15'], + }), + vuePlugin(), + svgBuilder('./src/assets/icons/'), + [Banner(`\n \n Time : ${timestamp}`)] + ], + css: { + preprocessorOptions: { + scss: { + additionalData: `@use "@/style/element/index.scss" as *;`, + } + } + }, + } + + if (NODE_ENV === 'development') { + config.plugins.push( + fullImportPlugin() + ) + } else { + config.plugins.push(AutoImport({ + resolvers: [ElementPlusResolver()] + }), + Components({ + resolvers: [ElementPlusResolver({ + importStyle: 'sass' + })] + })) + } + return config +}