@ -0,0 +1,5 @@ |
|||||||
|
# 变量必须以 VITE_ 为前缀才能暴露给外部读取 |
||||||
|
NODE_ENV = 'development' |
||||||
|
VITE_APP_TITLE = '教学一体化平台' |
||||||
|
VITE_APP_BASE_API = 'http://39.106.16.162:8080' |
||||||
|
# VITE_APP_BASE_API = 'http://127.0.0.1:8080' |
@ -0,0 +1,3 @@ |
|||||||
|
NODE_ENV = 'production' |
||||||
|
VITE_APP_TITLE = '教学一体化平台' |
||||||
|
# VITE_APP_BASE_API = '/api' |
@ -0,0 +1,4 @@ |
|||||||
|
# 变量必须以 VITE_ 为前缀才能暴露给外部读取 |
||||||
|
NODE_ENV = 'test' |
||||||
|
VITE_APP_TITLE = '教学一体化平台' |
||||||
|
# VITE_APP_BASE_API = '/api' |
@ -0,0 +1,2 @@ |
|||||||
|
dist |
||||||
|
node_modules |
@ -0,0 +1,60 @@ |
|||||||
|
// @see https://eslint.bootcss.com/docs/rules/ |
||||||
|
|
||||||
|
module.exports = { |
||||||
|
publicPath:"/portal", |
||||||
|
env: { |
||||||
|
browser: true, |
||||||
|
es2021: true, |
||||||
|
node: true, |
||||||
|
jest: true, |
||||||
|
}, |
||||||
|
/* 指定如何解析语法 */ |
||||||
|
parser: 'vue-eslint-parser', |
||||||
|
/** 优先级低于 parse 的语法解析配置 */ |
||||||
|
parserOptions: { |
||||||
|
ecmaVersion: 'latest', |
||||||
|
sourceType: 'module', |
||||||
|
parser: '@typescript-eslint/parser', |
||||||
|
jsxPragma: 'React', |
||||||
|
ecmaFeatures: { |
||||||
|
jsx: true, |
||||||
|
}, |
||||||
|
}, |
||||||
|
/* 继承已有的规则 */ |
||||||
|
extends: [ |
||||||
|
'eslint:recommended', |
||||||
|
'plugin:vue/vue3-essential', |
||||||
|
'plugin:@typescript-eslint/recommended', |
||||||
|
'plugin:prettier/recommended', |
||||||
|
], |
||||||
|
plugins: ['vue', '@typescript-eslint'], |
||||||
|
/* |
||||||
|
* "off" 或 0 ==> 关闭规则 |
||||||
|
* "warn" 或 1 ==> 打开的规则作为警告(不影响代码执行) |
||||||
|
* "error" 或 2 ==> 规则作为一个错误(代码不能执行,界面报错) |
||||||
|
*/ |
||||||
|
rules: { |
||||||
|
// eslint(https://eslint.bootcss.com/docs/rules/) |
||||||
|
'no-var': 'error', // 要求使用 let 或 const 而不是 var |
||||||
|
'no-multiple-empty-lines': ['warn', { max: 1 }], // 不允许多个空行 |
||||||
|
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', |
||||||
|
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', |
||||||
|
'no-unexpected-multiline': 'error', // 禁止空余的多行 |
||||||
|
'no-useless-escape': 'off', // 禁止不必要的转义字符 |
||||||
|
|
||||||
|
// typeScript (https://typescript-eslint.io/rules) |
||||||
|
'@typescript-eslint/no-unused-vars': 'warn', // 禁止定义未使用的变量 |
||||||
|
'@typescript-eslint/prefer-ts-expect-error': 'error', // 禁止使用 @ts-ignore |
||||||
|
'@typescript-eslint/no-explicit-any': 'off', // 禁止使用 any 类型 |
||||||
|
'@typescript-eslint/no-non-null-assertion': 'off', |
||||||
|
'@typescript-eslint/no-namespace': 'off', // 禁止使用自定义 TypeScript 模块和命名空间。 |
||||||
|
'@typescript-eslint/semi': 'off', |
||||||
|
|
||||||
|
// eslint-plugin-vue (https://eslint.vuejs.org/rules/) |
||||||
|
'vue/multi-word-component-names': 'off', // 要求组件名称始终为 “-” 链接的单词 |
||||||
|
'vue/script-setup-uses-vars': 'error', // 防止<script setup>使用的变量<template>被标记为未使用 |
||||||
|
'vue/no-mutating-props': 'off', // 不允许组件 prop的改变 |
||||||
|
'vue/attribute-hyphenation': 'off', // 对模板中的自定义组件强制执行属性命名样式 |
||||||
|
}, |
||||||
|
} |
||||||
|
|
@ -0,0 +1,24 @@ |
|||||||
|
# Logs |
||||||
|
logs |
||||||
|
*.log |
||||||
|
npm-debug.log* |
||||||
|
yarn-debug.log* |
||||||
|
yarn-error.log* |
||||||
|
pnpm-debug.log* |
||||||
|
lerna-debug.log* |
||||||
|
|
||||||
|
node_modules |
||||||
|
dist |
||||||
|
dist-ssr |
||||||
|
*.local |
||||||
|
|
||||||
|
# Editor directories and files |
||||||
|
.vscode/* |
||||||
|
!.vscode/extensions.json |
||||||
|
.idea |
||||||
|
.DS_Store |
||||||
|
*.suo |
||||||
|
*.ntvs* |
||||||
|
*.njsproj |
||||||
|
*.sln |
||||||
|
*.sw? |
@ -0,0 +1,7 @@ |
|||||||
|
/dist/* |
||||||
|
/html/* |
||||||
|
.local |
||||||
|
/node_modules/** |
||||||
|
**/*.svg |
||||||
|
**/*.sh |
||||||
|
/public/* |
@ -0,0 +1,9 @@ |
|||||||
|
{ |
||||||
|
"singleQuote": true, |
||||||
|
"semi": false, |
||||||
|
"bracketSpacing": true, |
||||||
|
"htmlWhitespaceSensitivity": "ignore", |
||||||
|
"endOfLine": "auto", |
||||||
|
"trailingComma": "all", |
||||||
|
"tabWidth": 2 |
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
/node_modules/* |
||||||
|
/dist/* |
||||||
|
/html/* |
||||||
|
/public/* |
@ -0,0 +1,53 @@ |
|||||||
|
// @see https://stylelint.bootcss.com/ |
||||||
|
|
||||||
|
module.exports = { |
||||||
|
extends: [ |
||||||
|
'stylelint-config-standard', // 配置stylelint拓展插件 |
||||||
|
'stylelint-config-html/vue', // 配置 vue 中 template 样式格式化 |
||||||
|
'stylelint-config-standard-scss', // 配置stylelint scss插件 |
||||||
|
'stylelint-config-recommended-vue/scss', // 配置 vue 中 scss 样式格式化 |
||||||
|
'stylelint-config-recess-order', // 配置stylelint css属性书写顺序插件, |
||||||
|
'stylelint-config-prettier', // 配置stylelint和prettier兼容 |
||||||
|
], |
||||||
|
overrides: [ |
||||||
|
{ |
||||||
|
files: ['**/*.(scss|css|vue|html)'], |
||||||
|
customSyntax: 'postcss-scss', |
||||||
|
}, |
||||||
|
{ |
||||||
|
files: ['**/*.(html|vue)'], |
||||||
|
customSyntax: 'postcss-html', |
||||||
|
}, |
||||||
|
], |
||||||
|
ignoreFiles: [ |
||||||
|
'**/*.js', |
||||||
|
'**/*.jsx', |
||||||
|
'**/*.tsx', |
||||||
|
'**/*.ts', |
||||||
|
'**/*.json', |
||||||
|
'**/*.md', |
||||||
|
'**/*.yaml', |
||||||
|
], |
||||||
|
/** |
||||||
|
* null => 关闭该规则 |
||||||
|
* always => 必须 |
||||||
|
*/ |
||||||
|
rules: { |
||||||
|
'value-keyword-case': null, // 在 css 中使用 v-bind,不报错 |
||||||
|
'no-descending-specificity': null, // 禁止在具有较高优先级的选择器后出现被其覆盖的较低优先级的选择器 |
||||||
|
'function-url-quotes': 'always', // 要求或禁止 URL 的引号 "always(必须加上引号)"|"never(没有引号)" |
||||||
|
'no-empty-source': null, // 关闭禁止空源码 |
||||||
|
'selector-class-pattern': null, // 关闭强制选择器类名的格式 |
||||||
|
'property-no-unknown': null, // 禁止未知的属性(true 为不允许) |
||||||
|
'block-opening-brace-space-before': 'always', //大括号之前必须有一个空格或不能有空白符 |
||||||
|
'value-no-vendor-prefix': null, // 关闭 属性值前缀 --webkit-box |
||||||
|
'property-no-vendor-prefix': null, // 关闭 属性前缀 -webkit-mask |
||||||
|
'selector-pseudo-class-no-unknown': [ |
||||||
|
// 不允许未知的选择器 |
||||||
|
true, |
||||||
|
{ |
||||||
|
ignorePseudoClasses: ['global', 'v-deep', 'deep'], // 忽略属性,修改element默认样式的时候能使用到 |
||||||
|
}, |
||||||
|
], |
||||||
|
}, |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
{ |
||||||
|
"recommendations": ["Vue.volar"] |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
<!doctype html> |
||||||
|
<html lang="en"> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8" /> |
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> |
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
||||||
|
<title>Vite + Vue + TS</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<div id="app"></div> |
||||||
|
<script type="module" src="/src/main.ts"></script> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,61 @@ |
|||||||
|
{ |
||||||
|
"name": "teaching-integration-platform-template", |
||||||
|
"private": true, |
||||||
|
"version": "0.0.0", |
||||||
|
"type": "module", |
||||||
|
"scripts": { |
||||||
|
"dev": "vite --open", |
||||||
|
"build:test": "vite build", |
||||||
|
"build:pro": "vue-tsc && vite build --mode production", |
||||||
|
"preview": "vite preview", |
||||||
|
"lint": "eslint src", |
||||||
|
"fix": "eslint src --fix", |
||||||
|
"format": "prettier --write \"./**/*.{html,vue,ts,js,json,md}\"", |
||||||
|
"lint:eslint": "eslint src/**/*.{ts,vue} --cache --fix", |
||||||
|
"lint:style": "stylelint src/**/*.{css,scss,vue} --cache --fix", |
||||||
|
"preinstall": "node ./scripts/preinstall.js" |
||||||
|
}, |
||||||
|
"dependencies": { |
||||||
|
|
||||||
|
"@element-plus/icons-vue": "^2.3.1", |
||||||
|
"axios": "^1.6.8", |
||||||
|
"element-plus": "^2.6.2", |
||||||
|
"pinia": "^2.1.7", |
||||||
|
"postcss-plugin-px2rem": "^0.8.1", |
||||||
|
"px2rem-loader": "^0.1.9", |
||||||
|
"vue": "^3.4.21", |
||||||
|
"vue-router": "^4.3.0" |
||||||
|
}, |
||||||
|
"devDependencies": { |
||||||
|
"@babel/eslint-parser": "^7.24.1", |
||||||
|
"@types/node": "^20.11.30", |
||||||
|
"@typescript-eslint/eslint-plugin": "^7.4.0", |
||||||
|
"@typescript-eslint/parser": "^7.4.0", |
||||||
|
"@vitejs/plugin-vue": "^5.0.4", |
||||||
|
"eslint": "^8.57.0", |
||||||
|
"eslint-config-prettier": "^9.1.0", |
||||||
|
"eslint-plugin-import": "^2.29.1", |
||||||
|
"eslint-plugin-node": "^11.1.0", |
||||||
|
"eslint-plugin-prettier": "^5.1.3", |
||||||
|
"eslint-plugin-vue": "^9.24.0", |
||||||
|
"postcss": "^8.4.38", |
||||||
|
"postcss-html": "^1.6.0", |
||||||
|
"postcss-scss": "^4.0.9", |
||||||
|
"prettier": "^3.2.5", |
||||||
|
"sass": "^1.72.0", |
||||||
|
"sass-loader": "^14.1.1", |
||||||
|
"stylelint": "^16.3.1", |
||||||
|
"stylelint-config-prettier": "^9.0.5", |
||||||
|
"stylelint-config-recess-order": "^5.0.0", |
||||||
|
"stylelint-config-recommended-scss": "^14.0.0", |
||||||
|
"stylelint-config-standard": "^36.0.0", |
||||||
|
"stylelint-config-standard-scss": "^13.0.0", |
||||||
|
"stylelint-config-standard-vue": "^1.0.0", |
||||||
|
"stylelint-order": "^6.0.4", |
||||||
|
"stylelint-scss": "^6.2.1", |
||||||
|
"typescript": "^5.2.2", |
||||||
|
"vite": "^5.2.0", |
||||||
|
"vite-plugin-svg-icons": "^2.0.1", |
||||||
|
"vue-tsc": "^2.0.6" |
||||||
|
} |
||||||
|
} |
After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,7 @@ |
|||||||
|
if (!/pnpm/.test(process.env.npm_execpath || '')) { |
||||||
|
console.warn( |
||||||
|
`\u001b[33mThis repository must using pnpm as the package manager ` + |
||||||
|
` for scripts to work properly.\u001b[39m\n`, |
||||||
|
) |
||||||
|
process.exit(1) |
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
<template> |
||||||
|
<router-view></router-view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang="ts" setup> |
||||||
|
import {} from 'vue' |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,23 @@ |
|||||||
|
<template> |
||||||
|
<div class="footer"> |
||||||
|
<h1>FOOTER</h1> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang="ts" setup> |
||||||
|
import {} from 'vue' |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.footer { |
||||||
|
// position: fixed; |
||||||
|
// bottom: 0; |
||||||
|
height: 300px; |
||||||
|
width: 100%; |
||||||
|
background-color: #252527; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: center; |
||||||
|
color: #fff; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,134 @@ |
|||||||
|
<template> |
||||||
|
<Tabbar /> |
||||||
|
<div class="main-container"> |
||||||
|
<Main /> |
||||||
|
</div> |
||||||
|
<Footer /> |
||||||
|
<div ref="totop" v-if="show" class="gotop" @click="scrollToTop"></div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang="ts" setup> |
||||||
|
// 导入顶部导航栏 |
||||||
|
import Tabbar from './tabbar/index.vue' |
||||||
|
// 导入二级路由容器 |
||||||
|
import Main from './main/index.vue' |
||||||
|
// 导入底部导航栏 |
||||||
|
import Footer from './footer/index.vue' |
||||||
|
import { onMounted, ref } from 'vue' |
||||||
|
const totop = ref() |
||||||
|
const flog = ref(false) |
||||||
|
const show = ref(true) |
||||||
|
const scrollToTop = () => { |
||||||
|
flog.value = true |
||||||
|
const dom = document.querySelector('.gotop') as Element |
||||||
|
console.log(dom) |
||||||
|
totop.value.style.backgroundPosition = '-6px -145px' |
||||||
|
setTimeout(() => { |
||||||
|
totop.value.style.backgroundPosition = '-363px -78px' |
||||||
|
}, 200) |
||||||
|
setTimeout(() => { |
||||||
|
totop.value.style.backgroundPosition = '-316px -78px' |
||||||
|
}, 400) |
||||||
|
setTimeout(() => { |
||||||
|
totop.value.style.backgroundPosition = '-6px -80px' |
||||||
|
totop.value.style.height = '60px' |
||||||
|
|
||||||
|
scrollTop() |
||||||
|
}, 500) |
||||||
|
} |
||||||
|
const scrollTop = () => { |
||||||
|
window.scrollTo({ |
||||||
|
top: 0, |
||||||
|
left: 0, |
||||||
|
behavior: 'smooth', |
||||||
|
}); |
||||||
|
setTimeout(() => { |
||||||
|
show.value = false |
||||||
|
},1500); |
||||||
|
setTimeout(() => { |
||||||
|
show.value = true |
||||||
|
flog.value = false |
||||||
|
num = 800 |
||||||
|
},1600); |
||||||
|
} |
||||||
|
let num = 800 |
||||||
|
onMounted(() => { |
||||||
|
// 页面滚动窗口监听事件 |
||||||
|
window.onscroll = function () { |
||||||
|
let high = document.documentElement.scrollTop || document.body.scrollTop //兼容各浏览器 |
||||||
|
// console.log(high,totop.value.offsetTop) |
||||||
|
|
||||||
|
if (flog.value) { |
||||||
|
num = num - 40 |
||||||
|
totop.value.style.top = num + 'px' |
||||||
|
return |
||||||
|
} |
||||||
|
// 获取浏览器卷去的高度 |
||||||
|
if (high >= 900) { |
||||||
|
totop.value.style.display = 'block' |
||||||
|
} else { |
||||||
|
totop.value.style.display = 'none' |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.main-container { |
||||||
|
width: 100%; |
||||||
|
min-height: 100vh; |
||||||
|
// padding-top: 80PX; |
||||||
|
} |
||||||
|
|
||||||
|
.gotop { |
||||||
|
display: none; |
||||||
|
width: 45PX; |
||||||
|
height: 45PX; |
||||||
|
z-index: 999; |
||||||
|
position: fixed; |
||||||
|
bottom: 50px; |
||||||
|
right: 50px; |
||||||
|
background-image: url('../assets/images/jinglingtu.png'); |
||||||
|
background-position: -264PX -78PX; |
||||||
|
transition: top 0.2s linear; |
||||||
|
animation: show 0.5s ease-in-out; |
||||||
|
} |
||||||
|
.gotop:hover { |
||||||
|
transition: background-image 0.2s ease-in; |
||||||
|
background-position: -215PX -78PX; |
||||||
|
} |
||||||
|
.bian { |
||||||
|
animation: bian 0.1s ease-in-out; |
||||||
|
} |
||||||
|
.fei { |
||||||
|
position: absolute; |
||||||
|
// animation: fei 3s ease-in-out; |
||||||
|
} |
||||||
|
@keyframes show { |
||||||
|
0% { |
||||||
|
opacity: 0; |
||||||
|
transform: translate3d(0, 100%, 0); |
||||||
|
} |
||||||
|
100% { |
||||||
|
opacity: 1; |
||||||
|
transform: none; |
||||||
|
} |
||||||
|
} |
||||||
|
@keyframes bian { |
||||||
|
0% { |
||||||
|
background-position: -6PX -145PX; |
||||||
|
} |
||||||
|
100% { |
||||||
|
background-position: -316PX -78PX; |
||||||
|
} |
||||||
|
} |
||||||
|
// @keyframes fei { |
||||||
|
// 0% { |
||||||
|
|
||||||
|
// bottom: 50px; |
||||||
|
// } |
||||||
|
// 100% { |
||||||
|
// top: 10%; |
||||||
|
// } |
||||||
|
// } |
||||||
|
</style> |
@ -0,0 +1,19 @@ |
|||||||
|
<template> |
||||||
|
<!-- <section class="app-main"> |
||||||
|
<transition name="fade-transform" mode="out-in"> |
||||||
|
<router-view :key="$route.path" /> |
||||||
|
</transition> |
||||||
|
</section> --> |
||||||
|
<router-view></router-view> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang="ts" setup> |
||||||
|
import {} from 'vue' |
||||||
|
import {useRoute } from 'vue-router' |
||||||
|
const $route = useRoute() |
||||||
|
console.log( $route); |
||||||
|
|
||||||
|
|
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped></style> |
@ -0,0 +1,213 @@ |
|||||||
|
<template> |
||||||
|
<div :class="!flog ? 'tabbar' : 'tabbar-active'"> |
||||||
|
<div class="container"> |
||||||
|
<div class="left"> |
||||||
|
<div class="logo-box"> |
||||||
|
<div class="lesson">LGOG</div> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="menu"> |
||||||
|
<ul> |
||||||
|
<li v-for="(item, index) in constRouter.children" :key="index"> |
||||||
|
{{ item.meta.title }} |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="right"> |
||||||
|
<div class="registered gradient">注册</div> |
||||||
|
<div class="login">登录</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang="ts" setup> |
||||||
|
import { constRouter } from '@/router/module/constRouter' |
||||||
|
// import { useRouter, useRoute } from 'vue-router' |
||||||
|
import { onMounted, ref } from 'vue' |
||||||
|
// const $router = useRouter() |
||||||
|
// const $route = useRoute() |
||||||
|
console.log(constRouter, '111') |
||||||
|
|
||||||
|
const flog = ref(false) |
||||||
|
onMounted(() => { |
||||||
|
window.addEventListener('scroll', () => { |
||||||
|
if (window.scrollY >= 50) { |
||||||
|
flog.value = true |
||||||
|
} else if (flog.value && window.scrollY <= 50) { |
||||||
|
flog.value = false |
||||||
|
} |
||||||
|
}) |
||||||
|
}) |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.logo-box { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
column-gap: 20px; |
||||||
|
.logo { |
||||||
|
width: 50px; |
||||||
|
|
||||||
|
img { |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.lesson { |
||||||
|
font-size: 30px; |
||||||
|
font-weight: bolder; |
||||||
|
color: #1d2129; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.tabbar { |
||||||
|
position: fixed; |
||||||
|
top: 0; |
||||||
|
z-index: 1; |
||||||
|
height: 80px; |
||||||
|
width: 100%; |
||||||
|
background-color: transparent; |
||||||
|
animation-duration: 0.3s; |
||||||
|
animation-name: tabber-to; |
||||||
|
} |
||||||
|
|
||||||
|
.tabbar-active { |
||||||
|
position: fixed; |
||||||
|
top: 0; |
||||||
|
height: 80px; |
||||||
|
width: 100%; |
||||||
|
background-color: #fff; |
||||||
|
animation-duration: 0.3s; |
||||||
|
animation-name: tabber; |
||||||
|
z-index: 999; |
||||||
|
box-shadow: 0px 0px 43px rgba(0, 0, 0, 0.2); |
||||||
|
} |
||||||
|
|
||||||
|
@keyframes tabber { |
||||||
|
0% { |
||||||
|
// transform: translateY(-80px); |
||||||
|
background-color: transparent; |
||||||
|
} |
||||||
|
|
||||||
|
100% { |
||||||
|
// transform: translateY(0); |
||||||
|
background-color: #fff; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@keyframes tabber-to { |
||||||
|
0% { |
||||||
|
// transform: translateY(-80px); |
||||||
|
background-color: #fff; |
||||||
|
} |
||||||
|
|
||||||
|
100% { |
||||||
|
// transform: translateY(0); |
||||||
|
background-color: transparent; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.container { |
||||||
|
height: 100%; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
justify-content: space-between; |
||||||
|
margin: 0 auto; |
||||||
|
width: $base-container-width; |
||||||
|
.left { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
.right { |
||||||
|
display: flex; |
||||||
|
div { |
||||||
|
width: 108px; |
||||||
|
height: 40px; |
||||||
|
text-align: center; |
||||||
|
line-height: 40px; |
||||||
|
border-radius: 5px; |
||||||
|
font-size: 14px; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
.registered{ |
||||||
|
color: #fff; |
||||||
|
} |
||||||
|
.login{ |
||||||
|
color: #1D2129; |
||||||
|
margin-left: 20px; |
||||||
|
border: 1px solid #E5E6EB; |
||||||
|
} |
||||||
|
} |
||||||
|
.menu { |
||||||
|
position: relative; |
||||||
|
padding: 0 20px; |
||||||
|
height: 100%; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
|
||||||
|
ul { |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
|
||||||
|
li { |
||||||
|
padding: 12px 20px; |
||||||
|
color: #1d2129; |
||||||
|
font-size: 14px; |
||||||
|
cursor: pointer; |
||||||
|
transition: all 0.2s; |
||||||
|
position: relative; |
||||||
|
} |
||||||
|
|
||||||
|
li:hover { |
||||||
|
color: #0033f7; |
||||||
|
transform: translateY(-5px); |
||||||
|
} |
||||||
|
|
||||||
|
.active::before { |
||||||
|
content: ' '; |
||||||
|
display: block; |
||||||
|
position: absolute; |
||||||
|
top: 0px; |
||||||
|
left: 50%; |
||||||
|
transform: translateX(-50%); |
||||||
|
width: 5px; |
||||||
|
height: 5px; |
||||||
|
border-radius: 50%; |
||||||
|
background-color: #fff; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.entry { |
||||||
|
position: absolute; |
||||||
|
top: 5px; |
||||||
|
right: 30px; |
||||||
|
display: flex; |
||||||
|
align-content: center; |
||||||
|
|
||||||
|
div { |
||||||
|
// padding: 5px; |
||||||
|
margin: 5px; |
||||||
|
margin-right: 0; |
||||||
|
padding: 0 10px; |
||||||
|
border-right: 1px solid #fff; |
||||||
|
color: #fff; |
||||||
|
font-size: 14px; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
|
||||||
|
div:last-child { |
||||||
|
border-right: none; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.logo { |
||||||
|
// height: 100%; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
After Width: | Height: | Size: 1.8 MiB |
After Width: | Height: | Size: 2.4 MiB |
After Width: | Height: | Size: 555 KiB |
After Width: | Height: | Size: 103 KiB |
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 496 B |
@ -0,0 +1,35 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<svg :style="{ width: width, height: height }"> |
||||||
|
<use :xlink:href="prefix + name" :fill="color"></use> |
||||||
|
</svg> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup lang="ts"> |
||||||
|
defineProps({ |
||||||
|
//xlink:href属性值的前缀 |
||||||
|
prefix: { |
||||||
|
type: String, |
||||||
|
default: '#icon-', |
||||||
|
}, |
||||||
|
//svg矢量图的名字 |
||||||
|
name: String, |
||||||
|
//svg图标的颜色 |
||||||
|
color: { |
||||||
|
type: String, |
||||||
|
default: '', |
||||||
|
}, |
||||||
|
//svg宽度 |
||||||
|
width: { |
||||||
|
type: String, |
||||||
|
default: '16px', |
||||||
|
}, |
||||||
|
//svg高度 |
||||||
|
height: { |
||||||
|
type: String, |
||||||
|
default: '16px', |
||||||
|
}, |
||||||
|
}) |
||||||
|
</script> |
||||||
|
<style scoped></style> |
@ -0,0 +1,10 @@ |
|||||||
|
import SvgIcon from './SvgIcon/index.vue' |
||||||
|
import type { App, Component } from 'vue' |
||||||
|
const components: { [name: string]: Component } = { SvgIcon } |
||||||
|
export default { |
||||||
|
install(app: App) { |
||||||
|
Object.keys(components).forEach((key: string) => { |
||||||
|
app.component(key, components[key]) |
||||||
|
}) |
||||||
|
}, |
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
import { createApp } from 'vue' |
||||||
|
// import G6 from '@antv/g6'
|
||||||
|
// 导入svg插件
|
||||||
|
import 'virtual:svg-icons-register' |
||||||
|
import App from './App.vue' |
||||||
|
// 引入elementplus组件库
|
||||||
|
import ElementPlus from 'element-plus' |
||||||
|
// 样式;
|
||||||
|
import 'element-plus/dist/index.css' |
||||||
|
//@ts-expect-error忽略当前文件ts类型的检测否则有红色提示(打包会失败)
|
||||||
|
import zhCn from 'element-plus/dist/locale/zh-cn.mjs' |
||||||
|
import gloablComponent from './components/index' |
||||||
|
// 引入全局样式
|
||||||
|
import '@/styles/index.scss' |
||||||
|
// 引入路由
|
||||||
|
import router from '@/router/index' |
||||||
|
// 引入仓库
|
||||||
|
import pinia from '@/store/index' |
||||||
|
import '@/utils/rem.js' |
||||||
|
// 创建vue实例
|
||||||
|
const app = createApp(App) |
||||||
|
// 注册element plus组件库
|
||||||
|
app.use(ElementPlus, { |
||||||
|
locale: zhCn, |
||||||
|
}) |
||||||
|
// 注册全局组件
|
||||||
|
app.use(gloablComponent) |
||||||
|
app.use(router) |
||||||
|
app.use(pinia) |
||||||
|
// app.use(G6)
|
||||||
|
// 挂载点
|
||||||
|
app.mount('#app') |
||||||
|
import * as ElementPlusIconsVue from '@element-plus/icons-vue' |
||||||
|
|
||||||
|
for (const [key, component] of Object.entries(ElementPlusIconsVue)) { |
||||||
|
app.component(key, component) |
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
import { createRouter, createWebHashHistory,createWebHistory } from 'vue-router' |
||||||
|
import { constRouter } from './module/constRouter' |
||||||
|
const router = createRouter({ |
||||||
|
history: createWebHashHistory(), |
||||||
|
routes: [constRouter], |
||||||
|
scrollBehavior() { |
||||||
|
return { |
||||||
|
left: 0, |
||||||
|
top: 0, |
||||||
|
} |
||||||
|
}, |
||||||
|
}) |
||||||
|
export default router |
@ -0,0 +1,55 @@ |
|||||||
|
export const constRouter: any =
|
||||||
|
{ |
||||||
|
path: '/', |
||||||
|
component: () => import('@/Layout/index.vue'), |
||||||
|
name: 'Layout', |
||||||
|
redirect: '/home', |
||||||
|
meta: { |
||||||
|
icon: '', |
||||||
|
title: '', |
||||||
|
hidden: false, |
||||||
|
}, |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
path: '/home', |
||||||
|
name: 'Home', |
||||||
|
component: () => import('@/views/home/index.vue'), |
||||||
|
meta: { |
||||||
|
icon: '', |
||||||
|
title: '首页', |
||||||
|
hidden: false, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
path: '/appraise', |
||||||
|
name: 'Appraise', |
||||||
|
component: () => import('@/views/appraise/index.vue'), |
||||||
|
meta: { |
||||||
|
icon: '', |
||||||
|
title: '竞赛评价', |
||||||
|
hidden: false, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
path: '/navigation', |
||||||
|
name: 'Navigation', |
||||||
|
component: () => import('@/views/navigation/index.vue'), |
||||||
|
meta: { |
||||||
|
icon: '', |
||||||
|
title: '竞赛导航', |
||||||
|
hidden: false, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
path: '/achievement', |
||||||
|
name: 'Achievement', |
||||||
|
component: () => import('@/views/achievement/index.vue'), |
||||||
|
meta: { |
||||||
|
icon: '', |
||||||
|
title: '竞赛成果', |
||||||
|
hidden: false, |
||||||
|
}, |
||||||
|
}, |
||||||
|
], |
||||||
|
} |
||||||
|
|
@ -0,0 +1,6 @@ |
|||||||
|
// 引入仓库
|
||||||
|
import { createPinia } from 'pinia' |
||||||
|
// 创建仓库
|
||||||
|
const pinia = createPinia() |
||||||
|
// 暴露仓库
|
||||||
|
export default pinia |
@ -0,0 +1,44 @@ |
|||||||
|
// 引入清除浏览器默认样式文件 |
||||||
|
@import './reset.scss'; |
||||||
|
|
||||||
|
.container-1420{ |
||||||
|
width: 1420px; |
||||||
|
margin: 0 auto; |
||||||
|
// background-color: #c2acac; |
||||||
|
} |
||||||
|
.gradient{ |
||||||
|
background: linear-gradient(90deg, rgba(66,217,172,1) 0%, rgba(0,208,208,1) 100%); |
||||||
|
} |
||||||
|
/* 设置滚动条的宽度和颜色 */ |
||||||
|
::-webkit-scrollbar { |
||||||
|
width: 10px; |
||||||
|
/* 滚动条宽度 */ |
||||||
|
} |
||||||
|
|
||||||
|
/* 设置滚动条的轨道背景色 */ |
||||||
|
::-webkit-scrollbar-track { |
||||||
|
background-color: #f1f1f1; |
||||||
|
} |
||||||
|
|
||||||
|
/* 设置滚动条上下按钮的样式 */ |
||||||
|
::-webkit-scrollbar-button { |
||||||
|
background-color: #bfbfbf; |
||||||
|
} |
||||||
|
|
||||||
|
/* 设置滚动条的滑块样式 */ |
||||||
|
::-webkit-scrollbar-thumb { |
||||||
|
background-color: #bfbfbf; |
||||||
|
border-radius: 5px; |
||||||
|
/* 滑块圆角 */ |
||||||
|
} |
||||||
|
|
||||||
|
/* 设置滑块在hover状态下的样式 */ |
||||||
|
::-webkit-scrollbar-thumb:hover { |
||||||
|
background-color: #999999; |
||||||
|
} |
||||||
|
|
||||||
|
.scene-tooltip { |
||||||
|
color: #6da0ff !important; |
||||||
|
font-weight: 700; |
||||||
|
opacity: .5; |
||||||
|
} |
@ -0,0 +1,188 @@ |
|||||||
|
/** |
||||||
|
* ENGINE |
||||||
|
* v0.2 | 20150615 |
||||||
|
* License: none (public domain) |
||||||
|
*/ |
||||||
|
|
||||||
|
*, |
||||||
|
*:after, |
||||||
|
*:before { |
||||||
|
box-sizing: border-box; |
||||||
|
|
||||||
|
outline: none; |
||||||
|
} |
||||||
|
|
||||||
|
html, |
||||||
|
body, |
||||||
|
div, |
||||||
|
span, |
||||||
|
applet, |
||||||
|
object, |
||||||
|
iframe, |
||||||
|
h1, |
||||||
|
h2, |
||||||
|
h3, |
||||||
|
h4, |
||||||
|
h5, |
||||||
|
h6, |
||||||
|
p, |
||||||
|
blockquote, |
||||||
|
pre, |
||||||
|
a, |
||||||
|
abbr, |
||||||
|
acronym, |
||||||
|
address, |
||||||
|
big, |
||||||
|
cite, |
||||||
|
code, |
||||||
|
del, |
||||||
|
dfn, |
||||||
|
em, |
||||||
|
img, |
||||||
|
ins, |
||||||
|
kbd, |
||||||
|
q, |
||||||
|
s, |
||||||
|
samp, |
||||||
|
small, |
||||||
|
strike, |
||||||
|
strong, |
||||||
|
sub, |
||||||
|
sup, |
||||||
|
tt, |
||||||
|
var, |
||||||
|
b, |
||||||
|
u, |
||||||
|
i, |
||||||
|
center, |
||||||
|
dl, |
||||||
|
dt, |
||||||
|
dd, |
||||||
|
ol, |
||||||
|
ul, |
||||||
|
li, |
||||||
|
fieldset, |
||||||
|
form, |
||||||
|
label, |
||||||
|
legend, |
||||||
|
table, |
||||||
|
caption, |
||||||
|
tbody, |
||||||
|
tfoot, |
||||||
|
thead, |
||||||
|
tr, |
||||||
|
th, |
||||||
|
td, |
||||||
|
article, |
||||||
|
aside, |
||||||
|
canvas, |
||||||
|
details, |
||||||
|
embed, |
||||||
|
figure, |
||||||
|
figcaption, |
||||||
|
footer, |
||||||
|
header, |
||||||
|
hgroup, |
||||||
|
menu, |
||||||
|
nav, |
||||||
|
output, |
||||||
|
ruby, |
||||||
|
section, |
||||||
|
summary, |
||||||
|
time, |
||||||
|
mark, |
||||||
|
audio, |
||||||
|
video { |
||||||
|
font: inherit; |
||||||
|
font-size: 100%; |
||||||
|
|
||||||
|
margin: 0; |
||||||
|
padding: 0; |
||||||
|
|
||||||
|
vertical-align: baseline; |
||||||
|
|
||||||
|
border: 0; |
||||||
|
} |
||||||
|
|
||||||
|
article, |
||||||
|
aside, |
||||||
|
details, |
||||||
|
figcaption, |
||||||
|
figure, |
||||||
|
footer, |
||||||
|
header, |
||||||
|
hgroup, |
||||||
|
menu, |
||||||
|
nav, |
||||||
|
section { |
||||||
|
display: block; |
||||||
|
} |
||||||
|
|
||||||
|
body { |
||||||
|
line-height: 1; |
||||||
|
} |
||||||
|
|
||||||
|
ol, |
||||||
|
ul { |
||||||
|
list-style: none; |
||||||
|
} |
||||||
|
|
||||||
|
blockquote, |
||||||
|
q { |
||||||
|
quotes: none; |
||||||
|
&:before, |
||||||
|
&:after { |
||||||
|
content: ''; |
||||||
|
content: none; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
sub, |
||||||
|
sup { |
||||||
|
font-size: 75%; |
||||||
|
line-height: 0; |
||||||
|
|
||||||
|
position: relative; |
||||||
|
|
||||||
|
vertical-align: baseline; |
||||||
|
} |
||||||
|
sup { |
||||||
|
top: -.5em; |
||||||
|
} |
||||||
|
sub { |
||||||
|
bottom: -.25em; |
||||||
|
} |
||||||
|
|
||||||
|
table { |
||||||
|
border-spacing: 0; |
||||||
|
border-collapse: collapse; |
||||||
|
} |
||||||
|
|
||||||
|
input, |
||||||
|
textarea, |
||||||
|
button { |
||||||
|
font-family: inhert; |
||||||
|
font-size: inherit; |
||||||
|
|
||||||
|
color: inherit; |
||||||
|
} |
||||||
|
|
||||||
|
select { |
||||||
|
text-indent: .01px; |
||||||
|
text-overflow: ''; |
||||||
|
|
||||||
|
border: 0; |
||||||
|
border-radius: 0; |
||||||
|
|
||||||
|
-webkit-appearance: none; |
||||||
|
-moz-appearance: none; |
||||||
|
} |
||||||
|
select::-ms-expand { |
||||||
|
display: none; |
||||||
|
} |
||||||
|
|
||||||
|
code, |
||||||
|
pre { |
||||||
|
font-family: monospace, monospace; |
||||||
|
font-size: 1em; |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
$base-container-width:1620px; |
@ -0,0 +1,118 @@ |
|||||||
|
|
||||||
|
;(function(win, lib) { |
||||||
|
var doc = win.document; |
||||||
|
var docEl = doc.documentElement; |
||||||
|
var metaEl = doc.querySelector('meta[name="viewport"]'); |
||||||
|
var flexibleEl = doc.querySelector('meta[name="flexible"]'); |
||||||
|
var dpr = 0; |
||||||
|
var scale = 0; |
||||||
|
var tid; |
||||||
|
var flexible = lib.flexible || (lib.flexible = {}); |
||||||
|
|
||||||
|
if (metaEl) { |
||||||
|
console.warn('将根据已有的meta标签来设置缩放比例'); |
||||||
|
var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/); |
||||||
|
if (match) { |
||||||
|
scale = parseFloat(match[1]); |
||||||
|
dpr = parseInt(1 / scale); |
||||||
|
} |
||||||
|
} else if (flexibleEl) { |
||||||
|
var content = flexibleEl.getAttribute('content'); |
||||||
|
if (content) { |
||||||
|
var initialDpr = content.match(/initial\-dpr=([\d\.]+)/); |
||||||
|
var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/); |
||||||
|
if (initialDpr) { |
||||||
|
dpr = parseFloat(initialDpr[1]); |
||||||
|
scale = parseFloat((1 / dpr).toFixed(2)); |
||||||
|
} |
||||||
|
if (maximumDpr) { |
||||||
|
dpr = parseFloat(maximumDpr[1]); |
||||||
|
scale = parseFloat((1 / dpr).toFixed(2)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (!dpr && !scale) { |
||||||
|
var isAndroid = win.navigator.appVersion.match(/android/gi); |
||||||
|
var isIPhone = win.navigator.appVersion.match(/iphone/gi); |
||||||
|
var devicePixelRatio = win.devicePixelRatio; |
||||||
|
if (isIPhone) { |
||||||
|
// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
|
||||||
|
if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) { |
||||||
|
dpr = 3; |
||||||
|
} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){ |
||||||
|
dpr = 2; |
||||||
|
} else { |
||||||
|
dpr = 1; |
||||||
|
} |
||||||
|
} else { |
||||||
|
// 其他设备下,仍旧使用1倍的方案
|
||||||
|
dpr = 1; |
||||||
|
} |
||||||
|
scale = 1 / dpr; |
||||||
|
} |
||||||
|
|
||||||
|
docEl.setAttribute('data-dpr', dpr); |
||||||
|
if (!metaEl) { |
||||||
|
metaEl = doc.createElement('meta'); |
||||||
|
metaEl.setAttribute('name', 'viewport'); |
||||||
|
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no'); |
||||||
|
if (docEl.firstElementChild) { |
||||||
|
docEl.firstElementChild.appendChild(metaEl); |
||||||
|
} else { |
||||||
|
var wrap = doc.createElement('div'); |
||||||
|
wrap.appendChild(metaEl); |
||||||
|
doc.write(wrap.innerHTML); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
function refreshRem(){ |
||||||
|
var width = docEl.getBoundingClientRect().width; |
||||||
|
if (width / dpr > 1920) { |
||||||
|
width = 1920 * dpr; |
||||||
|
} |
||||||
|
var rem = width / 10; |
||||||
|
docEl.style.fontSize = rem + 'px'; |
||||||
|
flexible.rem = win.rem = rem; |
||||||
|
} |
||||||
|
|
||||||
|
win.addEventListener('resize', function() { |
||||||
|
clearTimeout(tid); |
||||||
|
tid = setTimeout(refreshRem, 300); |
||||||
|
}, false); |
||||||
|
win.addEventListener('pageshow', function(e) { |
||||||
|
if (e.persisted) { |
||||||
|
clearTimeout(tid); |
||||||
|
tid = setTimeout(refreshRem, 300); |
||||||
|
} |
||||||
|
}, false); |
||||||
|
|
||||||
|
if (doc.readyState === 'complete') { |
||||||
|
doc.body.style.fontSize = 12 * dpr + 'px'; |
||||||
|
} else { |
||||||
|
doc.addEventListener('DOMContentLoaded', function(e) { |
||||||
|
doc.body.style.fontSize = 12 * dpr + 'px'; |
||||||
|
}, false); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
refreshRem(); |
||||||
|
|
||||||
|
flexible.dpr = win.dpr = dpr; |
||||||
|
flexible.refreshRem = refreshRem; |
||||||
|
flexible.rem2px = function(d) { |
||||||
|
var val = parseFloat(d) * this.rem; |
||||||
|
if (typeof d === 'string' && d.match(/rem$/)) { |
||||||
|
val += 'px'; |
||||||
|
} |
||||||
|
return val; |
||||||
|
} |
||||||
|
flexible.px2rem = function(d) { |
||||||
|
var val = parseFloat(d) / this.rem; |
||||||
|
if (typeof d === 'string' && d.match(/px$/)) { |
||||||
|
val += 'rem'; |
||||||
|
} |
||||||
|
return val; |
||||||
|
} |
||||||
|
|
||||||
|
})(window, window['lib'] || (window['lib'] = {})); |
@ -0,0 +1,20 @@ |
|||||||
|
// 引入第三方请求库axios
|
||||||
|
import axios from 'axios' |
||||||
|
// 创建axios实例
|
||||||
|
const server = axios.create({ |
||||||
|
baseURL: import.meta.env.VITE_APP_BASE_API, |
||||||
|
timeout:30000, |
||||||
|
}) |
||||||
|
// 创建请求拦截器
|
||||||
|
server.interceptors.request.use((config) => { |
||||||
|
return config |
||||||
|
|
||||||
|
}) |
||||||
|
// 创建相应拦截器
|
||||||
|
server.interceptors.response.use((response) => { |
||||||
|
return response.data |
||||||
|
}) |
||||||
|
|
||||||
|
// 暴露axios实例
|
||||||
|
|
||||||
|
export default server |
@ -0,0 +1,12 @@ |
|||||||
|
<template> |
||||||
|
<h1>404</h1> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang='ts' setup> |
||||||
|
import { } from 'vue' |
||||||
|
|
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang='scss' scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,14 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
成果 |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang='ts' setup> |
||||||
|
import { onMounted, reactive, ref, toRefs, watch } from 'vue' |
||||||
|
|
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang='scss' scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,14 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
评价 |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang='ts' setup> |
||||||
|
import { onMounted, reactive, ref, toRefs, watch } from 'vue' |
||||||
|
|
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang='scss' scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,188 @@ |
|||||||
|
<template> |
||||||
|
<div class="container-1420"> |
||||||
|
<div class="banner"> |
||||||
|
<div class="title">2024年度全国电子科技大赛火热报名中</div> |
||||||
|
<div class="description"> |
||||||
|
我是一段比赛简介我是一段比赛简介我是一段比赛简介我是一段比赛简介我是一段比赛简介我是一段比赛简介我是一段比赛简介我是一段比赛简介我是一段比赛简介 |
||||||
|
</div> |
||||||
|
<div class="application gradient">立即报名</div> |
||||||
|
<div class="nav-title"> |
||||||
|
<div class="top">竞赛导航</div> |
||||||
|
<div class="bottom">30+项目登陆后报名</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<!-- 比赛列表 --> |
||||||
|
<div class="race-list"> |
||||||
|
<div class="item" v-for="i in 8" :key="i"> |
||||||
|
<div class="image"> |
||||||
|
<img src="../../assets/images/item.png" alt="" /> |
||||||
|
</div> |
||||||
|
<div class="reac-info"> |
||||||
|
<div class="reac-title">全国计算机等级大赛</div> |
||||||
|
<div class="reac-project">全国计算机等级大赛项目</div> |
||||||
|
<div class="time">报名时间:2022-01-01 18:00-2022-01-01:18:00</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<!-- 新闻列表 --> |
||||||
|
<div class="news-list"> |
||||||
|
<div class="news-title"> |
||||||
|
<div class="top">竞赛导航</div> |
||||||
|
<div class="bottom">30+项目登陆后报名</div> |
||||||
|
</div> |
||||||
|
<div class="newa-panel"> |
||||||
|
<div class="tab"> |
||||||
|
<div :class="active === i ? 'item active gradient' : 'item'" v-for="i in 5" :key="i" @click="active = i">全部</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang="ts" setup> |
||||||
|
import { ref } from 'vue' |
||||||
|
const active = ref(1) |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.banner { |
||||||
|
position: relative; |
||||||
|
width: 100%; |
||||||
|
height: 692px; |
||||||
|
background: radial-gradient( |
||||||
|
circle, |
||||||
|
rgba(131, 255, 197, 1) 0%, |
||||||
|
rgba(255, 255, 255, 1) 50% |
||||||
|
); |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
.title { |
||||||
|
font-size: 50px; |
||||||
|
font-weight: 600; |
||||||
|
color: #333333; |
||||||
|
} |
||||||
|
.description { |
||||||
|
width: 1074px; |
||||||
|
text-align: center; |
||||||
|
font-size: 20px; |
||||||
|
color: #666; |
||||||
|
margin-top: 37px; |
||||||
|
} |
||||||
|
.application { |
||||||
|
width: 272px; |
||||||
|
height: 64px; |
||||||
|
text-align: center; |
||||||
|
line-height: 64px; |
||||||
|
border-radius: 10px; |
||||||
|
font-size: 24px; |
||||||
|
color: #fff; |
||||||
|
cursor: pointer; |
||||||
|
margin-top: 50px; |
||||||
|
} |
||||||
|
.nav-title { |
||||||
|
position: absolute; |
||||||
|
bottom: 0; |
||||||
|
color: #1e2033; |
||||||
|
.top { |
||||||
|
font-size: 40px; |
||||||
|
font-weight: 600; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
.bottom { |
||||||
|
font-size: 16px; |
||||||
|
text-align: center; |
||||||
|
margin-top: 10px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.race-list { |
||||||
|
width: 100%; |
||||||
|
display: flex; |
||||||
|
flex-wrap: wrap; |
||||||
|
justify-content: space-between; |
||||||
|
margin-top: 40px; |
||||||
|
.item { |
||||||
|
width: 340px; |
||||||
|
height: 360px; |
||||||
|
// background-color: pink; |
||||||
|
.image { |
||||||
|
width: 100%; |
||||||
|
height: 194px; |
||||||
|
img { |
||||||
|
width: 100%; |
||||||
|
height: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
.reac-info { |
||||||
|
.reac-title { |
||||||
|
margin-top: 19px; |
||||||
|
color: #c9c9c9; |
||||||
|
font-size: 12px; |
||||||
|
} |
||||||
|
.reac-project { |
||||||
|
font-size: 16px; |
||||||
|
font-weight: 600; |
||||||
|
color: #333333; |
||||||
|
margin-top: 10px; |
||||||
|
} |
||||||
|
.time { |
||||||
|
font-size: 14px; |
||||||
|
color: #8c8b8b; |
||||||
|
margin-top: 40px; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.item:nth-child(n) { |
||||||
|
margin-top: 20px; |
||||||
|
} |
||||||
|
} |
||||||
|
.news-list { |
||||||
|
margin-top: 170px; |
||||||
|
.news-title { |
||||||
|
.top { |
||||||
|
font-size: 40px; |
||||||
|
font-weight: 600; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
.bottom { |
||||||
|
font-size: 16px; |
||||||
|
text-align: center; |
||||||
|
margin-top: 10px; |
||||||
|
} |
||||||
|
} |
||||||
|
.newa-panel { |
||||||
|
width: 100%; |
||||||
|
height: 630px; |
||||||
|
background: rgba(255, 255, 255, 0.1); |
||||||
|
backdrop-filter: blur(10px); |
||||||
|
box-shadow: 2px 6px 14px rgba(0, 0, 0, 0.25); |
||||||
|
margin-top: 25px; |
||||||
|
padding: 46px 180px 70px 180px; |
||||||
|
.tab { |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
align-items: center; |
||||||
|
.item { |
||||||
|
width: 152px; |
||||||
|
height: 70px; |
||||||
|
border-radius: 10px; |
||||||
|
text-align: center; |
||||||
|
line-height: 70px; |
||||||
|
color: #1e2033; |
||||||
|
font-size: 18px; |
||||||
|
box-shadow: 7px 7px 22px -10px rgba(0, 0, 0, 0.22); |
||||||
|
cursor: pointer; |
||||||
|
transition: all 0.2s; |
||||||
|
} |
||||||
|
.item:hover{ |
||||||
|
transform: scale(1.1); |
||||||
|
} |
||||||
|
.active { |
||||||
|
color: #fff; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,14 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
导航 |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script lang='ts' setup> |
||||||
|
import { onMounted, reactive, ref, toRefs, watch } from 'vue' |
||||||
|
|
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang='scss' scoped> |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,5 @@ |
|||||||
|
declare module '*.vue' { |
||||||
|
import { DefineComponent } from "vue" |
||||||
|
const component: ReturnType<typeof DefineComponent> |
||||||
|
export default component |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
/// <reference types="vite/client" />
|
@ -0,0 +1,31 @@ |
|||||||
|
{ |
||||||
|
"compilerOptions": { |
||||||
|
"target": "ES2020", |
||||||
|
"useDefineForClassFields": true, |
||||||
|
"module": "ESNext", |
||||||
|
"lib": ["ES2020", "DOM", "DOM.Iterable"], |
||||||
|
"skipLibCheck": true, |
||||||
|
|
||||||
|
/* Bundler mode */ |
||||||
|
"moduleResolution": "bundler", |
||||||
|
"allowImportingTsExtensions": true, |
||||||
|
"resolveJsonModule": true, |
||||||
|
"isolatedModules": true, |
||||||
|
"noEmit": true, |
||||||
|
"jsx": "preserve", |
||||||
|
|
||||||
|
/* Linting */ |
||||||
|
"strict": true, |
||||||
|
"noUnusedLocals": true, |
||||||
|
"noUnusedParameters": true, |
||||||
|
"noFallthroughCasesInSwitch": true, |
||||||
|
"baseUrl": "./", // 解析非相对模块的基地址,默认是当前目录 |
||||||
|
"paths": { |
||||||
|
//路径映射,相对于baseUrl |
||||||
|
"@/*": ["src/*"] |
||||||
|
}, |
||||||
|
"types": ["vite/client"] |
||||||
|
}, |
||||||
|
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "src/utils/rem.js"], |
||||||
|
"references": [{ "path": "./tsconfig.node.json" }] |
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
{ |
||||||
|
"compilerOptions": { |
||||||
|
"composite": true, |
||||||
|
"skipLibCheck": true, |
||||||
|
"module": "ESNext", |
||||||
|
"moduleResolution": "bundler", |
||||||
|
"allowSyntheticDefaultImports": true, |
||||||
|
"strict": true |
||||||
|
}, |
||||||
|
"include": ["vite.config.ts"] |
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
import { defineConfig } from 'vite' |
||||||
|
import vue from '@vitejs/plugin-vue' |
||||||
|
import path from 'path' |
||||||
|
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' |
||||||
|
//@ts-ignore
|
||||||
|
import postcssPluginPx2rem from "postcss-plugin-px2rem"; //引入插件
|
||||||
|
|
||||||
|
|
||||||
|
//配置参数
|
||||||
|
const px2remOptions = { |
||||||
|
rootValue: 192, //换算基数, 默认100 ,也就是1440px ,这样的话把根标签的字体规定为1rem为50px,这样就可以从设计稿上量出多少个px直接在代码中写多少px了
|
||||||
|
unitPrecision: 5, //允许REM单位增长到的十进制数字,其实就是精度控制
|
||||||
|
// propWhiteList: [], // 默认值是一个空数组,这意味着禁用白名单并启用所有属性。
|
||||||
|
// propBlackList: [], // 黑名单
|
||||||
|
// exclude:false, //默认false,可以(reg)利用正则表达式排除某些文件夹的方法,例如/(node_module)/ 。如果想把前端UI框架内的px也转换成rem,请把此属性设为默认值
|
||||||
|
// selectorBlackList: [], //要忽略并保留为px的选择器
|
||||||
|
// ignoreIdentifier: false, //(boolean/string)忽略单个属性的方法,启用ignoreidentifier后,replace将自动设置为true。
|
||||||
|
// replace: true, // (布尔值)替换包含REM的规则,而不是添加回退。
|
||||||
|
mediaQuery: false, //(布尔值)允许在媒体查询中转换px
|
||||||
|
minPixelValue: 0 , //设置要替换的最小像素值(3px会被转rem)。 默认 0
|
||||||
|
} |
||||||
|
export default defineConfig({ |
||||||
|
plugins: [ |
||||||
|
vue(), |
||||||
|
// 配置svg插件
|
||||||
|
createSvgIconsPlugin({ |
||||||
|
// Specify the icon folder to be cached
|
||||||
|
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')], |
||||||
|
// Specify symbolId format
|
||||||
|
symbolId: 'icon-[dir]-[name]', |
||||||
|
}), |
||||||
|
], |
||||||
|
server:{ |
||||||
|
host: '0.0.0.0', |
||||||
|
port: 8866, |
||||||
|
}, |
||||||
|
resolve: { |
||||||
|
alias: { |
||||||
|
'@': path.resolve('./src'), // 相对路径别名配置,使用 @ 代替 src
|
||||||
|
// 'vue': 'vue/dist/vue.esm-bundler.js',
|
||||||
|
}, |
||||||
|
}, |
||||||
|
css: { |
||||||
|
preprocessorOptions: { |
||||||
|
scss: { |
||||||
|
javascriptEnabled: true, |
||||||
|
additionalData: '@import "./src/styles/variable.scss";', |
||||||
|
}, |
||||||
|
}, |
||||||
|
postcss: { |
||||||
|
plugins: [ |
||||||
|
// 配置响应式插件
|
||||||
|
postcssPluginPx2rem(px2remOptions) |
||||||
|
|
||||||
|
], |
||||||
|
}, |
||||||
|
}, |
||||||
|
}) |