default codes.

This commit is contained in:
zhouwentao 2024-04-17 17:50:36 +08:00
commit 082d0e44a1
69 changed files with 6645 additions and 0 deletions

12
.env.development Normal file
View File

@ -0,0 +1,12 @@
# .env.production 和这个一样
# the APP baseURL
VITE_APP_BASE_URL = 'http://192.168.0.102:8080/jeecg-boot/'
# the token key
VITE_APP_TOKEN_KEY = 'your_token_key'
# the upload url
VITE_UPLOAD_URL = '/'
# app title
VITE_APP_TITLE = '艺体志愿宝'

24
.gitignore vendored Normal file
View File

@ -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?

7
README.md Normal file
View File

@ -0,0 +1,7 @@
# Vue 3 + Vite
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
## Recommended IDE Setup
- [VS Code](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar)

13
index.html Normal file
View File

@ -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</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

3346
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

28
package.json Normal file
View File

@ -0,0 +1,28 @@
{
"name": "vite-vue",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"axios": "^1.3.2",
"element-plus": "^2.2.16",
"less": "^4.2.0",
"swiper": "^7.4.1",
"vue": "^3.2.37",
"vue-i18n": "^9.2.2",
"vue-router": "^4.0.13",
"vuex": "^4.1.0"
},
"devDependencies": {
"@types/node": "^20.12.7",
"@vitejs/plugin-vue": "^3.1.0",
"unplugin-auto-import": "^0.11.5",
"unplugin-vue-components": "^0.22.12",
"vite": "^3.1.0"
}
}

1
public/vite.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

94
src/App.vue Normal file
View File

@ -0,0 +1,94 @@
<!-- src/App.vue -->
<template>
<div class="common-layout">
<el-container>
<el-header><Header/></el-header>
<div class="ebody">
<router-view/>
</div>
<el-footer style="padding: 0">
<Footer/>
</el-footer>
</el-container>
</div>
<div v-if="false">
<el-config-provider :locale="elLocale">
<div>
<a href="https://vitejs.dev" target="_blank">
<img src="/vite.svg" class="logo" alt="Vite logo" />
</a>
<a href="https://vuejs.org/" target="_blank">
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
</a>
</div>
<el-switch
v-model="langSwitch"
style="
--el-switch-on-color: #13ce66;
--el-switch-off-color: #ff4949;
margin: 10px auto 20px;
display: block;
"
inline-prompt
active-text="中"
inactive-text="英"
@change="handleChangeI18n"
/>
<el-color-picker v-model="colorPicker" />
<!-- <Login /> -->
<router-view></router-view>
</el-config-provider>
</div>
</template>
<script setup>
import { ref, computed } from "vue";
// i18n
import { useI18n } from "vue-i18n";
// Element Plus
import zhCn from "element-plus/dist/locale/zh-cn.mjs";
import en from "element-plus/dist/locale/en.mjs";
import Header from "@/components/Header.vue";
const { locale } = useI18n({ useScope: "global" }); // vue-i18n useI18n(),locale
if (localStorage.getItem("locale") === undefined ||localStorage.getItem("locale") === null || localStorage.getItem("locale") === '') {
//
localStorage.setItem("locale",'zh_CN')
}
locale.value = localStorage.getItem("locale") || "zh_CN"; //
const elLocale = computed(() => (locale.value === "zh_CN" ? zhCn : en)); // Element Plus
//
const langSwitch = ref(locale.value === "zh_CN");
//
const handleChangeI18n = (val) => {
// console.log(val);
locale.value = val ? "zh_CN" : "en_US"; // truefalse
localStorage.setItem("locale", locale.value); //
};
//
const colorPicker = ref("#409EFF");
</script>
<style scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
.ebody{
margin: 0;
padding: 10px 0;
width: auto;
}
</style>

71
src/App2.vue Normal file
View File

@ -0,0 +1,71 @@
<!-- src/App.vue -->
<template>
<el-config-provider :locale="elLocale">
<div>
<a href="https://vitejs.dev" target="_blank">
<img src="/vite.svg" class="logo" alt="Vite logo" />
</a>
<a href="https://vuejs.org/" target="_blank">
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
</a>
</div>
<el-switch
v-model="langSwitch"
style="
--el-switch-on-color: #13ce66;
--el-switch-off-color: #ff4949;
margin: 10px auto 20px;
display: block;
"
inline-prompt
active-text="中"
inactive-text="英"
@change="handleChangeI18n"
/>
<el-color-picker v-model="colorPicker" />
<!-- <Login /> -->
<router-view></router-view>
</el-config-provider>
</template>
<script setup>
// import Login from "./components/Login.vue";
import { ref, computed } from "vue";
// i18n
import { useI18n } from "vue-i18n";
// Element Plus
import zhCn from "element-plus/dist/locale/zh-cn.mjs";
import en from "element-plus/dist/locale/en.mjs";
const { locale } = useI18n({ useScope: "global" }); // vue-i18n useI18n(),locale
locale.value = localStorage.getItem("locale") || "zh_CN"; //
const elLocale = computed(() => (locale.value === "zh_CN" ? zhCn : en)); // Element Plus
//
const langSwitch = ref(locale.value === "zh_CN");
//
const handleChangeI18n = (val) => {
// console.log(val);
locale.value = val ? "zh_CN" : "en_US"; // truefalse
localStorage.setItem("locale", locale.value); //
};
//
const colorPicker = ref("#409EFF");
</script>
<style scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
</style>

21
src/assets/css/base.css Normal file
View File

@ -0,0 +1,21 @@
.wrap {
width: 1210px;
}
.flexWrap {
display: flex;
flex-direction: row;
flex-wrap: wrap
}
.main-container {
margin: 0 auto;
}
.cms-back-to-top:before {
content: "\e903";
}
.margin-top-5 {
margin-top: 5px;
}

View File

@ -0,0 +1,38 @@
//注意Sass定义私有成员是使用-或开头例如定义$--color-black-10这种是私有变量使用additionalData: `@use 引入时无法读取
//黑色
$color-black-10: #f7f8fa;
$color-black-20: #f2f3f5;
$color-black-23: #eeeff2;
$color-black-25: #ebecf0;
$color-black-30: #e5e6eb;
$color-black-35: #d7dae0;
$color-black-40: #c9cdd4;
$color-black-45: #b9bdc6;
$color-black-50: #a9aeb8;
$color-black-60: #86909c;
$color-black-70: #6b7785;
$color-black-80: #4e5969;
$color-black-90: #272e3b;
$color-black-100: #1d2129;
//蓝色
$color-blue-10:#ecf5ff;
$color-blue-20:#d9ecff;
$color-blue-30:#c6e2ff;
$color-blue-40:#a0cfff;
$color-blue-50:#79bbff;
$color-blue-60:#409eff;
$color-blue-70:#337ecc;
//外边距
@for $i from 5 through 50 {
.margin-#{$i} {
margin: #{$i}px;
}
}
.a-button{
cursor: pointer;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
src/assets/images/logo.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
src/assets/images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 765 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>

After

Width:  |  Height:  |  Size: 814 B

BIN
src/assets/images/pyxz.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1587309384021" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1846" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M1010.8 628c0-141.2-141.3-256.2-299.9-256.2-168 0-300.3 115.1-300.3 256.2 0 141.4 132.3 256.2 300.3 256.2 35.2 0 70.7-8.9 106-17.7l96.8 53-26.6-88.2c70.9-53.2 123.7-123.7 123.7-203.3zM618 588.8c-22.1 0-40-17.9-40-40s17.9-40 40-40 40 17.9 40 40c0 22-17.9 40-40 40z m194.3-0.3c-22.1 0-40-17.9-40-40s17.9-40 40-40 40 17.9 40 40-17.9 40-40 40z" fill="#00C800" p-id="1847"></path><path d="M366.3 106.9c-194.1 0-353.1 132.3-353.1 300.3 0 97 52.9 176.6 141.3 238.4l-35.3 106.2 123.4-61.9c44.2 8.7 79.6 17.7 123.7 17.7 11.1 0 22.1-0.5 33-1.4-6.9-23.6-10.9-48.3-10.9-74 0-154.3 132.5-279.5 300.2-279.5 11.5 0 22.8 0.8 34 2.1C692 212.6 539.9 106.9 366.3 106.9zM247.7 349.2c-26.5 0-48-21.5-48-48s21.5-48 48-48 48 21.5 48 48-21.5 48-48 48z m246.6 0c-26.5 0-48-21.5-48-48s21.5-48 48-48 48 21.5 48 48-21.5 48-48 48z" fill="#00C800" p-id="1848"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

1
src/assets/vue.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

After

Width:  |  Height:  |  Size: 496 B

68
src/axios/api.js Normal file
View File

@ -0,0 +1,68 @@
// src/axios/api.js
import service from "./request";
// 登录
export const Login = (data) => {
return service({
url: "/login",
method: "post",
data,
});
};
// Get请求
export const Get = (url, data) => {
return service({
url,
method: "get",
params: data,
});
};
// Delete请求
export const Delete = (url) => {
return service({
url,
method: "delete",
});
};
// Post请求
export const Post = (url, data) => {
return service({
url,
method: "post",
data,
});
};
// 上传文件请求
export const PostFile = (url, data, onUploadProgress) => {
return service({
url,
method: "post",
data,
headers: {
"Content-Type": "multipart/form-data",
},
onUploadProgress,
});
};
// Put请求
export const Put = (url, data) => {
return service({
url,
method: "put",
data,
});
};
// Patch请求
export const Patch = (url, data) => {
return service({
url,
method: "patch",
data,
});
};

62
src/axios/request.js Normal file
View File

@ -0,0 +1,62 @@
// src/axios/request.js
import axios from "axios";
import { ElMessage } from "element-plus";
import router from "../router";
/**
* axios基础配置
*/
const service = axios.create({
baseURL: "/api", // api的base_url
timeout: 60000, // 请求超时时间
// headers: {
// "Access-Control-Allow-Credentials": true
// }, // 请求头信息
withCredentials: false, // 跨域请求时是否需要使用凭证,默认 false
responseType: "json", // 服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream',默认 json
});
/**
* 请求拦截器
* 函数参数1在发送请求之前做些什么
* 函数参数2对请求错误做些什么
*/
service.interceptors.request.use(
(config) => {
//判断token是否存在存在即已登录
if (localStorage.token) {
// 请求头携带token
config.headers.Authorization = `Bearer ${localStorage.token}`;
} else {
// token不存在即未登录跳转登录页
router.replace("/login");
}
return config;
},
(error) => {
ElMessage(error);
return Promise.reject(error);
}
);
/**
* 响应拦截器
* 函数参数1对响应数据做点什么
* 函数参数2对响应错误做点什么
*/
service.interceptors.response.use(
(response) => {
console.log(`code: ${response.data.code}`);
if (response.data.code === 401) {
console.log("token过期");
localStorage.removeItem( "token");
router.replace("/login");
}
return response;
},
(error) => {
return Promise.reject(error);
}
);
export default service;

71
src/components/Footer.vue Normal file
View File

@ -0,0 +1,71 @@
<!-- 页脚 -->
<template>
<div class="footer">
<div class="message"></div>
<div class="copyright">版权所有<em>&copy;xxx.com</em>
<router-link tag="a" :to="'/feedback'" target="_blank">联系我们</router-link>
</div>
</div>
</template>
<style scoped lang="scss">
/* 页脚 border-top: 1px solid #e1e1e1; */
.footer {
margin: 0 auto;
left: 0;
bottom: 0;
background: #fff;
height: 90px;
box-shadow: 0 0 3px 0 rgba(0, 0, 0, .02), 0 4px 8px 0 rgba(0, 0, 0, .02);
.message {
margin: 0 auto;
height: 18px;
font-size: 0;
line-height: 0;
a, em {
font-size: 12px;
line-height: 18px;
display: inline-block;
color: $color-black-60;
margin-top: 10px;
font-style: normal;
}
a:hover {
color: #1890ff;
text-decoration: none;
}
}
.copyright {
margin: 0 auto;
color: $color-black-60;
text-align: center;
margin-top: 18px;
font-size: 14px;
em {
font-family: Tahoma;
margin-left: 3px;
font-style: normal;
}
a {
font-family: Tahoma;
margin-left: 19px;
color: $color-black-60;
}
a:hover {
text-decoration: none;
color: #1890ff;
}
span {
margin-left: 17px;
}
}
}
</style>

199
src/components/Header.vue Normal file
View File

@ -0,0 +1,199 @@
<template>
<nav class="navbar"
:class="{ 'collapsed': !state.isNavVisible && state.scrolledPastThreshold, 'animatable': state.isNavVisible || !state.isNavVisible }">
<div class="box">
<!--导航栏-->
<div class="nav">
<ul>
<li v-for="column in state.columnList" :key="column.id">
<router-link tag="a" :to="'/'+column.url" :class="{ 'active': $route.path === '/'+column.url }">
{{ column.name }}
</router-link>
</li>
</ul>
</div>
<!--登录菜单项-->
<div class="menu">
<ul>
<li>
<router-link tag="a" :to="'/register'">注册</router-link>
</li>
<li>
<a @click="openLogin" class="a-button">登录</a>
</li>
</ul>
</div>
</div>
</nav>
<el-dialog
v-model="state.loginDialogVisible"
title=" "
width="30%"
:closeOnClickModal="false"
>
<template #header>
<div style="display: flex; justify-content: space-between; align-items: center;">
<h3 style="margin: 0;">登录</h3>
<button @click="closeDialog" class="el-dialog__headerbtn">
<i class="el-icon-close"></i>
</button>
</div>
</template>
<!-- 在这里放置登录内容 -->
<Login/>
</el-dialog>
</template>
<script setup lang="ts">
import {reactive, onMounted, ref} from "vue";
import {ElMessage} from 'element-plus'
const state = reactive({
activeIndex: '/index',
columnList: [] as Array<Object>,
isNavVisible: ref(true), //
prevScrollPos: ref(0), //
scrolledPastThreshold: ref(false), //
loginDialogVisible:ref(false),
})
// token
onMounted(() => {
let columnList = [{
"id": 1,
"name": "首页",
"parentId": 0,
"childColumn": [],
"sort": 100,
"linkMode": 3,
"url": "index"
},
{
"id": 2,
"name": "模拟报志愿",
"parentId": 0,
"childColumn": [],
"sort": 30,
"linkMode": 3,
"url": "fillVolunteer"
},
{"id": 3, "name": "找大学", "parentId": 0, "childColumn": [], "sort": 75, "linkMode": 3, "url": "school/search"},
{"id": 4, "name": "查专业", "parentId": 0, "childColumn": [], "sort": 75, "linkMode": 3, "url": "major/search"},
];
state.columnList = columnList
});
//
window.addEventListener('scroll', () => {
const currentScrollPos = window.pageYOffset;
if (currentScrollPos > 200) {
state.scrolledPastThreshold = true;
} else {
state.scrolledPastThreshold = false;
}
if (state.scrolledPastThreshold) {
if (currentScrollPos > state.prevScrollPos) {
//
state.isNavVisible = false;
} else {
//
state.isNavVisible = true;
}
}
state.prevScrollPos = currentScrollPos;
});
function openLogin(){
console.log('登录')
state.loginDialogVisible = true
}
function closeDialog() {
//
state.loginDialogVisible = false
}
</script>
<style scoped lang="scss">
.custom-menu {
border: none;
border-radius: 0;
}
/*导航栏*/
.navbar {
position: fixed;
left: 0;
width: 100%;
background-color: #ffffff;
color: #000000;
z-index: 1000; /* 可以根据需要调整 z-index 值 */
margin: 0;
padding: 0;
box-shadow: 0 0 3px rgba(0, 0, 0, .02), 0 4px 8px rgba(0, 0, 0, .02);
ul {
list-style: none;
display: flex;
flex-direction: row;
flex-wrap: wrap;
li {
margin-right: 20px;
}
}
/*导航栏左侧*/
.box {
margin: 0 auto;
width: 1210px;
display: flex;
flex-direction: row;
flex-wrap: wrap
}
/*导航栏右侧*/
.menu{
margin: 0 0 0 auto;
a{
color:$color-blue-60;
background-color: $color-blue-20;
padding: 8px 15px;
border-radius: 5px;
}
}
}
.navbar a {
color: #000000;
text-decoration: none;
}
.navbar a:hover {
color: $color-blue-60;
/*text-decoration: underline;*/
}
.navbar a.active {
font-weight: bold;
color: $color-blue-60; /* 设置高亮颜色,可以根据需求调整 */
}
/*导航栏折叠动画*/
.navbar {
transition: transform 0.3s; /* 添加平滑的过渡效果 */
}
.navbar.collapsed {
transform: translateY(-100%); /* 上滑以隐藏导航栏 */
}
.el-dialog__headerbtn {
border: none;
cursor: pointer;
}
</style>

View File

@ -0,0 +1,73 @@
<template>
<!-- 当前路由如果包含已登录字段则隐藏该按钮并显示已登录 -->
<el-button
type="danger"
@click="toLogin"
v-if="!isLogged"
style="width: 100%; margin: 20px auto"
>
{{ t("button.login") }}
</el-button>
<h1 v-else>{{ t("button.isLogged") }}</h1>
<!-- 退出登录 -->
<el-button
type="warning"
@click="toLogout"
v-if="isLogged"
style="width: 100%; margin: 20px auto"
>
{{ t("button.logout") }}
</el-button>
<!-- 打开抽屉 -->
<el-button
type="success"
@click="handleOpenChildrenDrawer"
style="width: 100%; margin: 20px auto"
>
{{ t("button.openDrawer") }}
</el-button>
<SideDrawer></SideDrawer>
</template>
<script setup>
import { onMounted, ref, provide } from "vue";
import { useRouter, useRoute } from "vue-router";
import { useI18n } from "vue-i18n";
import SideDrawer from "./SideDrawer.vue";
/**
* vue-router
*/
// t
const { t } = useI18n();
//
const router = useRouter();
//
const route = useRoute();
const isLogged = route.params.isLogged;
//
const toLogin = () => {
router.push("/login");
};
// 退
const toLogout = () => {
localStorage.removeItem("token");
router.push("/login");
};
// token
onMounted(() => {
localStorage.removeItem("token");
});
/**
* 自定义组件
*/
const isDrawerOpen = ref(false);
//
provide("isDrawerOpen", isDrawerOpen);
const handleOpenChildrenDrawer = () => {
isDrawerOpen.value = true;
};
</script>

157
src/components/Login.vue Normal file
View File

@ -0,0 +1,157 @@
<template>
<!-- <div style="padding: 50px 0 0">
<h1 style="font-size: 50px; font-weight: bolder">{{ t("title.login") }}</h1>
</div>-->
<el-form
ref="loginFormRef"
:model="loginForm"
status-icon
:rules="loginFormRules"
label-width="120px"
>
<el-form-item :label="t('label.phone')" prop="phone">
<el-input v-model="loginForm.phone"></el-input>
</el-form-item>
<el-form-item :label="t('label.password')" prop="pass">
<el-input v-model="loginForm.pass" type="password" autocomplete="off" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm(loginFormRef)">
{{ t("button.submit") }}
</el-button>
<el-button @click="resetForm(loginFormRef)">
{{ t("button.reset") }}
</el-button>
</el-form-item>
</el-form>
</template>
<script setup lang="ts">
import { ref, reactive} from "vue";
import { useRouter } from "vue-router";
// t
import { useI18n } from "vue-i18n";
import ApiConstant from "@/utils/ApiConstant";
import axiosInstance from '@/utils/http'
import { ElMessage } from "element-plus";
import { json } from "stream/consumers";
const { t } = useI18n();
// Element-Plus
// import { ElMessage } from "element-plus";
//
const router = useRouter();
//
const loginFormRef = ref();
const loginForm = reactive({
phone: "",
pass: "",
});
//
const validatePass = (rule, value, callback) => {
if (value === "") {
callback(new Error(t("placeholder.password")));
} else {
// if (loginForm.checkPass !== "") {
// if (!loginFormRef.value) return;
// loginFormRef.value.validateField("checkPass", () => null);
// }
callback();
}
};
const loginFormRules = reactive({
phone: [
{
required: true,
message: t("placeholder.phone"),
trigger: "blur",
},
/*{
type: "phone",
message: t("placeholder.phone"),
trigger: ["blur", "change"],
},*/
],
pass: [
{
required: true,
validator: validatePass,
trigger: "blur",
},
],
});
//
const submitForm = (formEl) => {
if (!formEl) return;
formEl.validate((valid) => {
if (valid) {
axiosInstance({
url: ApiConstant.User.login,
method: 'post',
data: {
username:loginForm.phone,
password:loginForm.pass
},
/*showLoading: false,//是否显示加载图标*/
}).then((response) => {
return response.data
}).then((data) => {
console.log('q')
if(data.success){
//
localStorage.setItem('vipInfo',JSON.stringify(data.result.vipInfo))
localStorage.setItem('userInfo',JSON.stringify(data.result.userInfo))
localStorage.setItem("token", data.result.token);
ElMessage.success(
localStorage.getItem("locale") === "zh_CN" ? "登录成功!" : "Submitted!"
);
//window.location.reload()
}else{
ElMessage.error(data.message);
}
//
}).catch((error: any) => {
console.log(error);
}).finally(() => {
});
// // axios
/*Login(loginForm).then((response) => {
const { code, msg, data: res } = response.data;
if (code === 0) {
localStorage.setItem("token", res.token);
ElMessage.success(msg ?? "Submitted!");
router.push({
path: "/", // HelloWorld.vue
params: {
isLogged: true,
},
});
} else {
ElMessage.error(msg);
}
});*/
// Demo
//localStorage.setItem("token", "test token");
/*router.push({
// path: "/", // HelloWorld.vue
name: "/index", // name params path query
params: {
isLogged: true,
},
});*/
//window.location.reload()
} else {
ElMessage.error(localStorage.getItem("locale") === "zh_CN" ? "登录失败!" : "Oops, error submit!");
return false;
}
});
};
const resetForm = (formEl) => {
if (!formEl) return;
formEl.resetFields();
};
</script>

View File

@ -0,0 +1,21 @@
<template>
<el-drawer
v-model="drawer"
title="I am the title"
direction="rtl"
:before-close="handleClose"
>
<span>Hi, there!</span>
</el-drawer>
</template>
<script setup>
import { inject } from "vue";
// 使
const drawer = inject("isDrawerOpen", false);
const handleClose = (done) => {
ElMessage("Drawer closed.");
done();
};
</script>

24
src/lang/en_US.js Normal file
View File

@ -0,0 +1,24 @@
// src/lang/en_US.js
const en_US = {
title: {
login: "Login",
},
button: {
login: "Login",
logout: "Logout",
isLogged: "Logged",
submit: "Submit",
reset: "Reset",
openDrawer: "Open Drawer",
},
label: {
phone:'Phone',
email: "Email",
password: "Password",
},
placeholder:{
phone:'Please input the Phone',
password:'Please input the Password'
}
};
export default en_US;

18
src/lang/index.js Normal file
View File

@ -0,0 +1,18 @@
// src/lang/index.js
import { createI18n } from "vue-i18n";
// 自定义语言文件
import zh_CN from "./zh_CN";
import en_US from "./en_US";
const i18n = createI18n({
legacy: false, // 使用 Composition API 模式
locale: "zh_CN", // 语言库
messages: {
zh_CN,
en_US,
},
});
// 将i18n暴露出去在main.js中引入挂载
export default i18n;

25
src/lang/zh_CN.js Normal file
View File

@ -0,0 +1,25 @@
// src/lang/zh_CN.js
const zh_CN = {
title: {
login: "登录",
},
button: {
login: "登录",
logout: "退出登录",
isLogged: "已登录",
submit: "提交",
reset: "重置",
openDrawer: "打开抽屉",
},
label: {
username:'用户名',
phone:'手机号',
email: "邮箱",
password: "密码",
},
placeholder:{
phone:'请输入手机号',
password:'请输入密码'
}
};
export default zh_CN;

57
src/main.js Normal file
View File

@ -0,0 +1,57 @@
// src/main.js
import { createApp } from "vue";
import "./style.css";
import ElementPlus from "element-plus";
//import VueAxios from 'vue-axios'
import 'element-plus/theme-chalk/el-message.css'//全局 Message 消息提示(js文件中使用不支持自动导入的样式)
import "element-plus/theme-chalk/el-message-box.css";// messageBox的样式
import "element-plus/theme-chalk/el-overlay.css";// 遮罩层样式
import "element-plus/theme-chalk/el-loading.css";// loading的样式
import "element-plus/theme-chalk/el-notification.css";//Notification的样式
//import 'element-plus/dist/index.css'//全部引入
import 'element-plus/es/components/form/style/css'//script setup中使用组件时不支持自动导入的样式
import 'element-plus/theme-chalk/el-affix.css'//全局 固钉
import App from "./App.vue";
// 引入Vue-Router
import Router from "./router";
// 引入Vue-i18n
import i18n from "./lang";
// Element Plus全局配置国际化
import zhCn from "element-plus/dist/locale/zh-cn.mjs";
import en from "element-plus/dist/locale/en.mjs";
// 导入请求拦截器
import axiosInstance from '@/utils/http'//导入请求拦截器request
const app = createApp(App);
//axios
app.config.globalProperties.$axios=axiosInstance;
// // 引入Axios
// import axios from "axios";
// // 后端接口域名
// axios.defaults.baseURL = "https://XXX.com";
// /**
// * 将axios挂载为app的全局自定义属性后每个组件可以通过this直接访问到全局挂载的自定义属性
// * e.g. this.$http.get('/login');
// * ===================================
// * 如果使用组合式API【setup()语法】由于vue3.0没有this需要使用getCurrentInstance来获取上下文
// * e.g.如下
// */
// // const { proxy } = getCurrentInstance();
// // proxy.$http.get("/api/getNewsList").then((response) => {
// // console.log(response);
// // });
// app.config.globalProperties.$http = axios; // 关键语句
// app.use(ElementPlus);
app.use(ElementPlus, {
// locale: zhCn,
locale: localStorage.getItem("locale") === "zh_CN" ? zhCn : en,
});
app.use(Router);
app.use(i18n);
app.mount("#app");

101
src/router/index.js Normal file
View File

@ -0,0 +1,101 @@
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/index',//首页
name: 'index',
component: () => import('@/views/index.vue')
},
/*{
path: '/fillVolunteer',//模拟填报
name: 'fillVolunteer',
component: () => import('@/views/fillVolunteer/index.vue')
},
{
path: '/myVolunteer',//我的志愿表
name: 'myVolunteer',
component: () => import('@/views/fillVolunteer/my.vue')
},*/
{
path: '/school/search',//找大学
name: 'schoolSearch',
component: () => import('@/views/school/search.vue')
},
/*{
path: '/school/:schoolCode',//学校详情页
name: 'school',
component: () => import('@/views/school/schoolInfo.vue'),
meta:{
title:"学院介绍"
}
},*/
{
path: '/major/search',//查专业
name: 'majorSearch',
component: () => import('@/views/major/search.vue')
},
/*{
path: '/major/:majorCode',//专业详情页
name: 'major',
component: () => import('@/views/major/majorInfo.vue'),
meta:{
title:"专业概括"
}
},*/
/*{
path: '/scoreControlLine',//省控线
name: 'scoreControlLine',
component: () => import('@/views/other/historyScoreControlLine.vue'),
meta:{
title:"省控线"
}
},
{
path: '/search',//搜索
name: 'search',
component: () => import('@/views/search.vue')
},
{
path: '/membershipCardList',//会员卡列表
name: 'membershipCardList',
component: () => import('@/views/membershipCardList.vue')
},
{
path: '/membershipCard',//会员卡明细
name: 'membershipCard',
component: () => import('@/views/membershipCard.vue')
},
{
path: '/help',//帮助中心
name: 'help',
component: () => import('@/views/help.vue')
},
{
path: '/helpDetail',//帮助内容
name: 'helpDetail',
component: () => import('@/views/helpDetail.vue')
},
{
path: '/login',//登录
name: 'login',
component: () => import('@/views/login.vue')
},
{
path: '/register',//注册
name: 'register',
component: () => import('@/views/register.vue')
},*/
// {path : '/:pathMatch(.*)*', redirect:{name:'index'}}//其余路由重定向至首页。
{ path: '/:pathMatch(.*)*', redirect: () => {
return { name: 'index' };//重定向的 字符串路径/路径对象
}},
]
export default createRouter({
history: createWebHistory(),
routes
})

92
src/store/index.ts Normal file
View File

@ -0,0 +1,92 @@
import {App, InjectionKey } from 'vue';
import { createStore, useStore, Store } from 'vuex';
import { TypeRootState,SystemUser } from "@/store/interface";
// 创建一个新的 store 实例
const store = createStore<TypeRootState>({
state() {
return {
apiUrl: import.meta.env.VITE_APP_BASE_URL,//后端地址
baseURL :'',//系统路径
commonPath:'',//后端资源路径
contextPath:'',//后端系统虚拟目录
templateDir:'',//后端模板目录名称
title: '',//站点名称
keywords:'',//站点关键词
description:'',//站点描述
systemUser: {} as SystemUser,//登录用户
baseURI:'',//系统资源标识符
fileStorageSystem: 0,//文件存储系统 0.本地系统 10.SeaweedFS 20.MinIO 30.阿里云OSS
supportAccessDevice: 1,//支持访问设备 1.自动识别终端 2.电脑端 3.移动端
weixin_oa_appid:'',//微信公众号appid
transparentImage:'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',//透明1像素图片
userInfoVersion: 0 //用户信息信息版本 App.vue监听本参数当数值变化时执行刷新登录用户信息
};
},
//修改状态数据的同步方法
mutations: {
//设置后端地址
setApiUrl(state: TypeRootState,value:string) {
state.apiUrl = value;
},
setBaseURL(state: TypeRootState, value:string) {
state.baseURL = value;
},
setCommonPath(state: TypeRootState, value:string) {
state.commonPath = value;
},
setContextPath(state: TypeRootState, value:string) {
state.contextPath = value;
},
setTemplateDir(state: TypeRootState, value:string) {
state.templateDir = value;
},
setTitle(state: TypeRootState, value:string) {
state.title = value;
},
setKeywords(state: TypeRootState, value:string) {
state.keywords = value;
},
setDescription(state: TypeRootState, value:string) {
state.description = value;
},
setSystemUser(state: TypeRootState, value:SystemUser) {
state.systemUser = value;
},
setBaseURI(state: TypeRootState, value:string) {
state.baseURI = value;
},
setFileStorageSystem(state: TypeRootState, value:number ) {
state.fileStorageSystem = value;
},
setSupportAccessDevice(state: TypeRootState, value:number ) {
state.supportAccessDevice = value;
},
setWeixin_oa_appid(state: TypeRootState, value:string) {
state.weixin_oa_appid = value;
},
setUserInfoVersion(state: TypeRootState, value:number) {
state.userInfoVersion = value;
},
},
//修改状态数据的异步方法
actions: {},
});
export default store;
/*
// 定义 injection key
const key: InjectionKey<Store<TypeRootState>> = Symbol();
// 定义自己的 `useStore` 组合式函数
export function appStore() {
return useStore(key);
}
export const setupStore = (app: App) => {
app.use(store, key);
};
*/

38
src/store/interface.ts Normal file
View File

@ -0,0 +1,38 @@
/**
* root层state类型定义
*/
export interface TypeRootState {
apiUrl: string;//后端地址
baseURL: string;//系统路径
commonPath: string;//后端资源路径
contextPath: string;//后端系统虚拟目录
templateDir: string;//后端模板目录名称
title: string;//站点名称
keywords: string;//站点关键词
description: string;//站点描述
systemUser: SystemUser;//登录用户
baseURI: string;//系统资源标识符
fileStorageSystem: number;//文件存储系统 0.本地系统 10.SeaweedFS 20.MinIO 30.阿里云OSS
supportAccessDevice: number,//支持访问设备 1.自动识别终端 2.电脑端 3.移动端
weixin_oa_appid: string;//微信公众号appid
transparentImage: string;//透明1像素图片
userInfoVersion: number //用户信息版本 App.vue监听本参数当数值变化时执行刷新登录用户信息
}
/**
*
*/
export interface SystemUser {
userId: string;//ID
userName: string;//会员用户名
account: string;//账号
nickname: string;//呢称
avatarPath: string;//头像路径
avatarName: string;//头像名称
openId: string;//第三方用户的唯一标识 例如微信的openid
loginInterface: number;//登录接口 0.本地 10.微信 50.其他开放平台
}

10
src/store/vuex.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
import { ComponentCustomProperties } from "vue";
import { Store } from "vuex";
import { TypeRootState } from "@/store/interface";
declare module "@vue/runtime-core" {
// 为 `this.$store` 提供类型声明
interface ComponentCustomProperties {
$store: Store<TypeRootState>;
}
}

98
src/style.css Normal file
View File

@ -0,0 +1,98 @@
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
width: 100%;
height: 100%;
}
.el-main{
padding: 10px;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
/*min-width: 320px;*/
/*min-height: 100vh;*/
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
.card {
padding: 2em;
}
#app {
width: 100%;
height: 100%;
margin: 0 auto;
/*max-width: 1280px;*/
/*padding: 2rem;*/
/*text-align: center;*/
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #f7f8fa;
/*background-color: #ffffff;*/
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}

68
src/types/index.d.ts vendored Normal file
View File

@ -0,0 +1,68 @@
///艺考
export interface FillVolunteer{
type:string,
tkcj:string,
gkkm:string,
whcj:string,
ywcj:string,
yyfs:string
}
//志愿
export interface VolunteerEntity {
indexs:string,//志愿顺序
schoolCode:string,//学校编码
majorCode:string,//专业编码
createBy:string,//用户id
createTime:string,//填报时间
}
export interface MajorEntity{
id:string,
firstLevelDiscipline:string,
educationalLevel:string,
educationalLevel_dictText:string,
schoolCode:string,//学校编码
schoolName:string,//学校名称
majorCode:string,//专业编码
majorName:string,//专业名称
majorDesc:string,//专业描述
batch:string,//批次
degree:string,//授予学位
semester:string,//学制
ssm:string,//是什么
xsm:string,//学什么
}
export interface SchoolEntity{
schoolName:string,
schoolCode:string,
schoolIcon:string,
province:string,//省
city:string,//市
area:string,//区
street:string,//详细信息
schoolType:string,//本科/专科
websiteAddressList:Array<string>,
institutionType:string,
schoolNature:string,
tagsList:Array<string>,
schoolPhone:string,//学校电话
baseInfo:string,//基本介绍
affiliation:string,//隶属于
schoolOpenDate:string,//办学日期
}
//省控线对象
export interface ScoreControlLineEntity{
id:string,//主键
year:string,//年份
professionalCategory:string,//专业类别
educationalLevel:string,//学历层次
category:string,//文科/理科
culturalScore:string,//文化成绩分数
specialScore:string,//专业成绩分数
batch:string,//批次
}
//========================================

46
src/utils/ApiConstant.ts Normal file
View File

@ -0,0 +1,46 @@
// @ts-ignore
const Major={
recommendMajorPage:'/art/recommendMajor/page',//获取推荐专业列表
recommendMajorList:'/art/recommendMajor/list',//获取学校的其他专业
schoolMajorDtoPage:'/yx/yxSchoolMajor/dtoPage',//获取学校开设专业分页数据
schoolHistoryMajorEnrollList:'/yx/yxHistoryMajorEnroll/list',//获取学校的分数计划
schoolMajorList:'/yx/yxSchoolMajor/list',//获取school_major 数据
majorList:'/yx/yxMajor/list',//获取专业信息表-分页列表查询
majorInfo:'/art/major/majorInfo',//获取专业详情
}
//用户类
const User={
exchangeVipCard:'/yx/yxVipCard/exchange',//兑换vip卡
login:'/web/user/login/passwd',//登录
register:'/web/user/register',//注册
}
const System={
findPassWord:'/sys/findPassWord',//找回密码
}
//高考分数类
const Score={
scoreSave:"/yx/yxScore/save",//保存用户专业得分
getScore:"/yx/yxScore/getUserScoreInfo",//获取当前用户的高考分数信息
conversionScoreBatch:"/yx/yxHistoryScoreBatch/conversionScoreBatch",//获取分数批次段
historyScoreControlLineList:'/yx/yxHistoryScoreControlLine/list',//省控线分页列表
}
//学校类
const School = {
searchSchoolList:"/art/school/search",//搜索 学校列表
schoolInfo:"/art/school/schoolInfo",//学校介绍详情
hotSchoolList:'/art/school/hotList',//热门院校 列表
}
//志愿
const Volunteer={
volunteerSave:"/art/volunteer/save",//保存用户的志愿
volunteerList:'/art/volunteer/list',
volunteerInfo:'/art/volunteer/info',
volunteerPage:'/art/volunteer/page',
volunteerRecordDel:'/art/volunteer/recordDel',//删除志愿明细
volunteerRecordReplace:'/art/volunteer/replaceVolunteer',//替换志愿明细
}
export default
{
Major,User,Score,School,Volunteer,System
}

154
src/utils/StaticConstant.ts Normal file
View File

@ -0,0 +1,154 @@
// @ts-ignore
/*就读地域编码列表*/
const addressList = [
{name: "北京", code: "北京"},
{name: "天津", code: "天津"},
{name: "河北", code: "河北"},
{name: "山西", code: "山西"},
{name: "辽宁", code: "辽宁"},
{name: "吉林", code: "吉林"},
{name: "上海", code: "上海"},
{name: "江苏", code: "江苏"},
{name: "浙江", code: "浙江"},
{name: "安徽", code: "安徽"},
{name: "福建", code: "福建"},
{name: "江西", code: "江西"},
{name: "山东", code: "山东"},
{name: "河南", code: "河南"},
{name: "湖北", code: "湖北"},
{name: "湖南", code: "湖南"},
{name: "广东", code: "广东"},
{name: "广西", code: "广西"},
{name: "海南", code: "海南"},
{name: "重庆", code: "重庆"},
{name: "四川", code: "四川"},
{name: "贵州", code: "贵州"},
{name: "云南", code: "云南"},
{name: "陕西", code: "陕西"},
{name: "甘肃", code: "甘肃"},
{name: "青海", code: "青海"},
{name: "宁夏", code: "宁夏"},
{name: "新疆", code: "新疆"},
{name: "黑龙江", code: "黑龙江"},
{name: "内蒙古", code: "内蒙古"},
]
/*院校类型*/
const institutionTypeList = [
{name: "综合", code: "综合"},
{name: "师范", code: "师范"},
{name: "理工", code: "理工"},
{name: "其他", code: "其他"},
{name: "农林", code: "农林"},
{name: "医药", code: "医药"},
{name: "语言", code: "语言"},
{name: "财经", code: "财经"},
{name: "政法", code: "政法"},
{name: "体育", code: "体育"},
{name: "艺术", code: "艺术"},
{name: "民族", code: "民族"}
]
/*学校类型标签*/
const schoolTypeList = [
{name: "本科", code: "本科"},
{name: "专科", code: "专科"},
{name: "公办", code: "公办"},
{name: "民办", code: "民办"},
{name: "中外合作办学", code: "中外合作办学"},
{name: "内地与港澳台地区合作办学", code: "内地与港澳台地区合作办学"},
]
const tagsList = [
{name: "985", code: "985"},
{name: "211", code: "211,"},
{name: "双一流", code: "双一流"},
{name: "教育部直属", code: "教育部直属"},
{name: "中央部委", code: "中央部委"},
{name: "强基计划", code: "强基计划"},
]
const tagsList2 = [
{name: "公办", code: "公办"},
{name: "民办", code: "民办"},
{name: "中外合作办学", code: "中外合作办学"},
{name: "985", code: "985"},
{name: "211", code: "211"},
]
//录取方式
const rulesEnrollProbabilityList = [
{name: "文过专排", code: "文过专排"},
{name: "专过文排", code: "专过文排"},
{name: "文0.07专0.17", code: "文0.07专0.17"},
{name: "文1.00专2.50", code: "文1.00专2.50"},
{name: "文0.50专1.25", code: "文0.50专1.25"},
]
//历年份
const hostoryYear = [
{label: "2022"},
{label: "2021"},
{label: "2020"}
]
const allYear = [
{label: "2023"},
{label: "2022"},
{label: "2021"},
{label: "2020"}
]
//批次列表
const batchOptions = [
{value: "提前批", label: "提前批"},
{value: "本科A段", label: "本科A段"},
{value: "本科B段", label: "本科B段"},
{value: "本科", label: "本科"},
{value: "高职高专", label: "高职高专"}
]
//专业类型
const zyOptions = [
{value: '美术类', label: '美术类', scoreMax: 300},
{value: '体育类', label: '体育类', scoreMax: 150},
{value: '音乐类', label: '音乐类', scoreMax: 200},
{value: '艺术舞蹈类', label: '艺术舞蹈类', scoreMax: 200},
{value: '国际标准舞类', label: '国际标准舞类', scoreMax: 200},
{value: '播音类', label: '播音类', scoreMax: 400},
{value: '表演类', label: '表演类', scoreMax: 200},
{value: '书法类', label: '书法类', scoreMax: 200}
]
const klOptions = [
{value: '物理', label: '物理'},
{value: '化学', label: '化学'},
{value: '生物', label: '生物'},
{value: '政治', label: '政治'},
{value: '历史', label: '历史'},
{value: '地理', label: '地理'},
]
//专业门类
const subjectCategorys = {
ben: [
{id: '1693636614636453889', subjectCategoryName: '设计类'},
{id: '1693636948259782657', subjectCategoryName: '美术类'},
{id: '1722224567122784257', subjectCategoryName: '体育类'},
{id: '1729330561128599553', subjectCategoryName: '戏剧与影视学类'},
{id: '1729330693307895810', subjectCategoryName: '艺术学理论类'},
{id: '1729330817086001154', subjectCategoryName: '音乐与舞蹈学类'},
{id: '1731184415533244417', subjectCategoryName: '体育类(职业教育)'},
{id: '1731184193902026753', subjectCategoryName: '艺术设计类(职业教育)'},
{id: '1731184290459099137', subjectCategoryName: '表演艺术类(职业教育)'},
{id: '1731184354581618689', subjectCategoryName: '文化服务类(职业教育)'},
],
zhuan:[
{id:'1731488738330918913', subjectCategoryName: '体育类'},
{id:'1729376220997316609', subjectCategoryName: '文化服务类'},
{id:'1729376034648584193', subjectCategoryName: '艺术设计类'},
{id:'1729376091326214145', subjectCategoryName: '表演艺术类'},
{id:'1729375855455334402', subjectCategoryName: '广播影视类'},
{id:'1729376162675519489', subjectCategoryName: '民族文化艺术类'},
]
}
export default {
addressList, institutionTypeList, schoolTypeList, tagsList, tagsList2, hostoryYear, batchOptions, zyOptions, klOptions,subjectCategorys,allYear,rulesEnrollProbabilityList
}

19
src/utils/env.d.ts vendored Normal file
View File

@ -0,0 +1,19 @@
/// <reference types="vite/client" />
export interface ImportMetaEnv {
readonly VITE_APP_TITLE: string
readonly VITE_APP_BASE_URL: string
readonly VITE_APP_TOKEN_KEY?: string
readonly VITE_UPLOAD_URL?: string
}
interface ImportMeta {
readonly env: ImportMetaEnv
}
declare module '*.vue' {
import type { DefineComponent } from 'vue'
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
}

28
src/utils/extension.ts Normal file
View File

@ -0,0 +1,28 @@
// 原型扩展 不要对原型方法使用箭头函数 引入方法import * as extension from "@/utils/extension";const extensionFunction = extension;
export {}
declare global {
interface Array<T> {
contains(item:string): boolean;
}
}
/**
*
*/
if (!Array.prototype.contains) {
//使用Object.defineProperty以确保该属性不可枚举
Object.defineProperty(Array.prototype, 'contains', {
enumerable: false,
writable: false,
configurable: false,
value: function contains(this: any, item:string): boolean {
return RegExp("\\b"+item+"\\b").test(this);
}
});
//Array.prototype.contains = function(item:string):boolean{
// return RegExp("\\b"+item+"\\b").test(this as any);
//}
}

386
src/utils/http.ts Normal file
View File

@ -0,0 +1,386 @@
// AJAX请求
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'
import {ElLoading, ElMessage, ElMessageBox} from 'element-plus'
import { LoadingInstance } from 'element-plus/lib/components/loading/src/loading'
import createRouter from '@/router'
import debounce from "lodash/debounce";
import store from "@/store";
import {isNotNull, isNull} from "@/utils/tool";
//获取TOken
export const getAccessToken = ()=>{
return window.localStorage.getItem('X-Access-Token')
}
//清除Token
export const removeAccessToken = ()=>{
window.localStorage.removeItem('X-Access-Token')
window.localStorage.removeItem('bbsToken')
}
//loading对象
let loadingInstance :LoadingInstance | null;
//loading当前正在请求的数量
let needLoadingRequestCount: number = 0;
//显示loading
const showLoading = (target:string | HTMLElement | undefined, mask:boolean=true) => {
//解决加载图标抖动问题. 关闭时loading对象可能还存在但needLoadingRequestCount已经变成0.避免这种情况下会重新创建loading
if (needLoadingRequestCount === 0 && !loadingInstance) {
loadingInstance = ElLoading.service({
// lock: mask ? true :false,//加载时全屏幕锁定
// text: '加载中...',
// fullscreen: mask ? true :false,//全屏遮罩
// target: target || "document.body",
background: mask ? 'rgba(255, 255, 255, 0.5)' :'rgba(255, 255, 255, 0)',
customClass : mask ? '' :'loading-noOverlay-custom'//遮罩层
});
}
needLoadingRequestCount++;
}
//隐藏loading
const hideLoading = () => {
needLoadingRequestCount--;
needLoadingRequestCount = Math.max(needLoadingRequestCount, 0); //做个保护
if (needLoadingRequestCount === 0) {
//关闭loading
toHideLoading();
}
}
//防抖:将 300ms 间隔内的关闭 loading 便合并为一次。防止连续请求时, loading闪烁的问题。
let toHideLoading = debounce(()=>{
if(loadingInstance){
loadingInstance.close();
loadingInstance = null;
}
}, 300);
//MessageBox当前正在显示的数量
let needMessageBoxRequestCount: number = 0;
//显示MessageBox
const showMessageBox = (message: string) => {
if (needMessageBoxRequestCount === 0) {//只显示第一个
ElMessageBox.alert(message, '通知', {
showClose: false,
showConfirmButton: false,
});
}
needMessageBoxRequestCount++;
}
const axiosInstance = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_URL,
// 定义请求超时时间
timeout: 20000,
// 请求带上 cookie
//withCredentials: true,
// 定义消息头
headers: {
// 'X-Requested-With': 'XMLHttpRequest',
post: {
'Content-Type': 'application/json;charset=UTF-8'//application/x-www-form-urlencoded
}
},
//设置csrf请求头。前后端分离使用localStorage保存登录状态时可以不配置xsrf
xsrfCookieName : 'cms_token',
// xsrfHeaderName : 'BBS-XSRF-TOKEN'
})
export default axiosInstance
//请求拦截器
axiosInstance.interceptors.request.use((config: any) => {
if (config.headers === undefined) {
config.headers = {};
}
//上传到第三方文件存储系统时可能只允许提交CORS默认响应头
if(config.isCorsDefaultHeaders == undefined || config.isCorsDefaultHeaders == false){
config.headers['X-Requested-With'] = 'XMLHttpRequest';
}
//判断当前请求是否设置了不显示Loading
if(config.showLoading !== false){
showLoading(config.loadingTarget as string | HTMLElement,config.loadingMask as boolean);
}
if (config.method === 'get' && config.timestamp !== false){
if(config.params != undefined){
//增加时间戳
Object.assign(config.params, { //如果get请求本身带有参数给options.params 再添加一个key值_t,值为时间戳
_t: new Date().getTime(),
})
}else{
config.params={_t: new Date().getTime()}
}
}
//从localStorage中获取登录令牌
let accessToken= getAccessToken() as string
if(isNotNull(accessToken)){
//让每个请求携带会话token ['Authorization']
config.headers['X-Access-Token'] = accessToken
config.headers['Authorization'] = 'Bearer '+accessToken+","+accessToken;//如果将过期的access_token提交到后端让令牌提取器解析会返回401错误。注意:不需要登录后才能查看的页面不要携带本参数,如登录页和刷新令牌页不要提交此参数,目前无需登录的页面携带了本参数的请求由后端过滤去掉
}
return config
},
(error: any) => {
//判断当前请求是否设置了不显示Loading
if(error.config.showLoading !== false){
hideLoading();
}
return Promise.resolve(error)
});
let isRefreshing:boolean = false // 标记是否正在刷新 token
let requests: ((sessionToken: any) => void)[] = [] // 存储待重发请求的数组
//响应拦截器
axiosInstance.interceptors.response.use((response: AxiosResponse) => {
if (response.config.headers === undefined) {
response.config.headers = {};
}
// console.log("响应拦截器 ",createRouter.currentRoute.value);
if(response.config.url?.includes('/baseInfo')){//如果是请求基本信息
const result: any = response.data;
if(result != ""){
let resultData = JSON.parse(result);
let bbsToken = window.localStorage.getItem('bbsToken');
if(bbsToken != null && resultData.systemUser == null){
if (!isRefreshing) {
isRefreshing = true;
new Promise(resolve => {
return refreshToken().then(res=> {
if(res){
let result: any = res.data;
if(result){
let resultObject = JSON.parse(result);
let accessToken = resultObject.accessToken;
let refreshToken = resultObject.refreshToken;
let systemUser = resultObject.systemUser;
//访问令牌和刷新令牌存储到localStorage
window.localStorage.setItem("bbsToken", JSON.stringify({accessToken : accessToken, refreshToken : refreshToken}));
store.commit('setSystemUser', systemUser);
}
}
}).catch(err => {
return Promise.reject(err)
}).finally(() => {
isRefreshing = false;
});
})
}
}
}
}
//判断当前请求是否设置了不显示Loading
if(response.config.showLoading !== false){
hideLoading();
}
return response;
},
// 请求失败
(error: any) => {
if(error.response){
switch (error.response.status) {
case 400:
ElMessage({
duration :0,
showClose: true,
message: '请求无效400',
type: 'error',
})
break;
case 401:
console.log('登录失效')
//有token情况
if (isNull(getAccessToken() as string)) {
//如果没有登录过
//直接跳转到登录页
//删除会话token
removeAccessToken()
ElMessage({
showClose: true,
message: '请先登录',
type: 'error',
})
createRouter.push({
path : '/login'
});
break;
}
case 403:
ElMessage({
showClose: true,
message: '权限不足(您没有当前功能的操作权限)',
type: 'error',
})
break;
case 404:
ElMessage({
duration :0,
showClose: true,
message: '找不到您尝试加载的网页404'+error.response.config.url,
type: 'error',
})
break;
case 500:
ElMessage({
duration :0,
showClose: true,
message: '服务器错误500',
type: 'error',
})
break;
case 503: //关闭网站提示
showMessageBox(error.response.data);
break;
case 508:
//清理登录信息
window.localStorage.clear();//清空localStorage中所有信息
store.commit('setSystemUser', {});
break;
default:
ElMessage({
duration :0,
showClose: true,
message: '请求错误('+error.response.status+'',
type: 'error',
})
}
}else{
//网络连接失败
//ElMessage({
// duration :0,
// showClose: true,
// message: '请求失败('+error.code+''+error.message+'',
// type: 'error',
//})
}
//判断当前请求是否设置了不显示Loading
if(error.config.showLoading !== false){
hideLoading();
}
return Promise.reject(error.response);
});
//刷新令牌
export let refreshToken = () =>{
let formData = new FormData();
return axiosInstance({
method: 'post',
url: 'refreshToken',
data: formData,
showLoading: false,//是否显示加载图标
loadingMask:false,// 是否显示遮罩层
});
//.then(function (response) {
// return Promise.resolve(response);
//});
};
//本地刷新会话续期
export let localRefreshToken = async () =>{
await refreshToken().then(res=> {
if(res){
let result: any = res.data;
if(result){
let tokenObject = JSON.parse(result);
//访问令牌和刷新令牌存储到localStorage
window.localStorage.setItem("bbsToken", JSON.stringify({accessToken : tokenObject.accessToken, refreshToken : tokenObject.refreshToken}));
};
}
});
};
//原生ajax刷新会话续期在Hls.js监听事件里调用axios会发生错误这里用原生方法代替
export let nativeRefreshToken = () =>{
let xmlhttp = new window.XMLHttpRequest();
xmlhttp.open('POST', import.meta.env.VITE_APP_BASE_URL+"refreshToken" , false);//同步
xmlhttp.setRequestHeader("X-Requested-With","XMLHttpRequest");//标记报头为AJAX
//从localStorage中获取登录令牌
let bbsToken = window.localStorage.getItem('bbsToken');
if(bbsToken != null){
let tokenObject = JSON.parse(bbsToken);
//会话token
let sessionToken = tokenObject.accessToken+","+tokenObject.refreshToken;
// header 添加参数
xmlhttp.setRequestHeader("Authorization", 'Bearer '+sessionToken);
}
xmlhttp.onreadystatechange = function(){
if (xmlhttp.readyState == 4) {//readystate
if(xmlhttp.status == 200){
let result = xmlhttp.responseText;
if(result != ""){
let tokenObject = JSON.parse(result);
//访问令牌和刷新令牌存储到localStorage
window.localStorage.setItem("bbsToken", JSON.stringify({accessToken : tokenObject.accessToken, refreshToken : tokenObject.refreshToken}));
}
}
}
};
xmlhttp.send(null);
};
//原生ajax查询视频重定向在Hls.js监听事件里调用axios会发生错误这里用原生方法代替
export let nativeQueryVideoRedirect = (url:string,callback:any) =>{
let xmlhttp = new window.XMLHttpRequest();
xmlhttp.open('GET', url , false);//同步
xmlhttp.setRequestHeader("X-Requested-With","XMLHttpRequest");//标记报头为AJAX
//从localStorage中获取登录令牌
let bbsToken = window.localStorage.getItem('bbsToken');
if(bbsToken != null){
let tokenObject = JSON.parse(bbsToken);
//会话token
let sessionToken = tokenObject.accessToken+","+tokenObject.refreshToken;
// header 添加参数
xmlhttp.setRequestHeader("Authorization", 'Bearer '+sessionToken);
}
xmlhttp.onreadystatechange = function(){
if (xmlhttp.readyState == 4) {//readystate
if(xmlhttp.status == 200){
let result = xmlhttp.responseText;
if(result != ""){
let date = JSON.parse(result);
callback(date);
}
}
}
};
xmlhttp.send(null);
};

76
src/utils/tool.ts Normal file
View File

@ -0,0 +1,76 @@
import { ElMessageBox, MessageBoxState } from 'element-plus'
import type { Action } from 'element-plus'
/**
* Array null且其size不等于0
* @param array
*/
export function collectionUtilsIsNotEmpty(array:Array<object>){
if (array == undefined || array == null || array.length == 0) {
return false;
}
return true;
}
/**
* Array null size等于0
* @param array
*/
export function collectionUtilsIsEmpty(array:Array<object>){
if (array == undefined || array == null || array.length == 0) {
return true;
}
return false;
}
export function isNull(str:string){
if (str == undefined || str == null || str=='') {
return true;
}else{
return false;
}
}
export function isNotNull(str:string){
if (str == undefined || str == null || str=='') {
return false;
}else{
return true;
}
}
/**
*
* @param num
*/
export function convertToChinaNum(num: number) {
var arr1 = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
var arr2 = ['', '十', '百', '千', '万', '十', '百', '千', '亿', '十', '百', '千','万', '十', '百', '千','亿'];//可继续追加更高位转换值
if(!num || isNaN(num)){
return "零";
}
var english = num.toString().split("")
var result = "";
for (var i = 0; i < english.length; i++) {
var des_i = english.length - 1 - i;//倒序排列设值
result = arr2[i] + result;
var arr1_index = english[des_i];
result = arr1[Number(arr1_index)] + result;
}
//将【零千、零百】换成【零】 【十零】换成【十】
result = result.replace(/零(千|百|十)/g, '零').replace(/十零/g, '十');
//合并中间多个零为一个零
result = result.replace(/零+/g, '零');
//将【零亿】换成【亿】【零万】换成【万】
result = result.replace(/零亿/g, '亿').replace(/零万/g, '万');
//将【亿万】换成【亿】
result = result.replace(/亿万/g, '亿');
//移除末尾的零
result = result.replace(/零+$/, '')
//将【零一十】换成【零十】
//result = result.replace(/零一十/g, '零十');//貌似正规读法是零一十
//将【一十】换成【十】
result = result.replace(/^一十/g, '十');
return result;
}

11
src/views/Major.vue Normal file
View File

@ -0,0 +1,11 @@
<script setup>
</script>
<template>
Major
</template>
<style scoped>
</style>

View File

@ -0,0 +1,11 @@
<script setup>
</script>
<template>
fillVolunteer
</template>
<style scoped>
</style>

652
src/views/index.vue Normal file
View File

@ -0,0 +1,652 @@
<script lang="ts" setup>
import {ref, getCurrentInstance, ComponentInternalInstance, reactive} from 'vue'
import {ElMessage} from 'element-plus'
//
import image1 from '@/assets/images/gk/2023/sxznps.jpg';
import image2 from '@/assets/images/gk/2023/ddps.jpg';
import image3 from '@/assets/images/gk/2023/gzdz1200.jpg';
//=============
import {Swiper, SwiperSlide} from "swiper/vue";
import {Navigation, Pagination, Scrollbar, A11y, Autoplay} from 'swiper';
import "swiper/css";
import {SchoolEntity} from "@/types";
import ApiConstant from "@/utils/ApiConstant";
//
const {proxy} = getCurrentInstance() as ComponentInternalInstance;
const modules = [Navigation, Pagination, Scrollbar, A11y, Autoplay];
const onSwiper = (swiper: any) => {
console.log(swiper);
};
const navigation = ref({
nextEl: '.button-next',
prevEl: '.button-prev',
})
const prevEl = () => {
// console.log('' + index + item)
}
const nextEl = () => {
// console.log('')
}
//
const state = reactive({
hotSchoolList: [] as Array<SchoolEntity>,
hotTabActive: 1
})
const hotSchoolList = reactive({
nowProvinceBenSchoolList: [],//
nowProvinceZhuanSchoolList: [],//
otherProvinceBenSchoolList: [],//
otherProvinceZhuanSchoolList: []//
})
getHotSchoolList()
//
function getHotSchoolList() {
proxy?.$axios({
url: ApiConstant.School.hotSchoolList,
method: 'get',
params: {},
showLoading: false,//
}).then((response) => {
return response.data
}).then((data) => {
console.log(data)
//
hotSchoolList.nowProvinceBenSchoolList = data.result.nowProvinceBenSchoolList
hotSchoolList.nowProvinceZhuanSchoolList = data.result.nowProvinceZhuanSchoolList
hotSchoolList.otherProvinceBenSchoolList = data.result.otherProvinceBenSchoolList
hotSchoolList.otherProvinceZhuanSchoolList = data.result.otherProvinceZhuanSchoolList
if (state.hotTabActive == 1) {
state.hotSchoolList = hotSchoolList.nowProvinceBenSchoolList
}
}).catch((error: any) => {
console.log(error);
}).finally(() => {
});
}
function copyText(textToCopy) {
const textField = document.createElement('textarea');
textField.innerText = textToCopy;
document.body.appendChild(textField);
textField.select();
document.execCommand('copy');
textField.remove();
ElMessage({
message: '已复制.',
type: 'success',
})
}
//
function switchHotTab(index: number) {
state.hotTabActive = index
//
if (index == 1) {
state.hotSchoolList = hotSchoolList.nowProvinceBenSchoolList
} else if (index == 2) {
state.hotSchoolList = hotSchoolList.nowProvinceZhuanSchoolList
} else if (index == 3) {
state.hotSchoolList = hotSchoolList.otherProvinceBenSchoolList
} else if (index == 4) {
state.hotSchoolList = hotSchoolList.otherProvinceZhuanSchoolList
}
}
</script>
<template>
<div class="margin-5"></div>
<div class="main-container wrap main-fullScreen">
<el-row :gutter="20">
<!-- 轮播图-->
<el-col :span="18">
<div class="header_swiper">
<Swiper
:modules="modules"
:pagination="true"
:mousewheel="true"
:keyboard="true"
@swiper="onSwiper"
:navigation="navigation"
:autoplay="{ delay: 3000, disableOnInteraction: false }"
:loop="true"
>
<swiper-slide style="width: 1200px">
<img :src="image1" alt="Image"/>
</swiper-slide>
<swiper-slide style="width: 1200px">
<img :src="image2" alt="Image"/>
</swiper-slide>
<swiper-slide style="width: 1200px">
<img :src="image3" alt="Image"/>
</swiper-slide>
</Swiper>
</div>
<div class="swiper-scrollbar"></div>
<div class='button-prev' @click.stop='prevEl'><img
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAwCAYAAAAPfWqeAAADpUlEQVRYR73YX2gcRRwH8N9v7vyDIiJSqtJaFEVRLBSs+CAotNogRZTs7s2sUEgFhQr1QR/aBxVsH3xRWvtQqf9Q4TZOdtOeOUOjbc4HoYpBQfClD75JIzHV9BrTO2/zlc3NJmtzyf3bu31clt9nfjO/mZ0Zph49ANjzRg4x0xDAR7kXDgAxPDxyAqAXovjM9HvqUIR4nv8JEfbESTDzgVQhrXUmDPlzACqBHFbKfj01qFQqZaen/8wDsGNECHpTSuetpe5LY4ympqauOX/+N01EzyaQg1I6by9n1i00Pj5+3dzcvA9g90osfs117XeSsbvKqFQqXT89PXMSoIGVMRGvKGW9d3UCHUNjY2M3lMsLBSLaWS9hBjNeltI53qiXOoImJiZuvHjxUhHAEyboohD8kpT2h2sNRdtQoVC4aX6+Mk5Ej8UIkdjrutan6413W5DW+uYwpNMAPWpmfEhEe5Ry8s2KqmWoWCzeUi7/MwHQdjMmNYCfd10rKuumT0vQ6OjorZVK+A2AbSbiv8yUU8o52VQwHzSFtNYbwpDPANhqMqkIwXYuZ421ijRdGfL5wkaiyiQRPWCCXiGi51zXOd0Osi7keYU7gCXkPjPwC0JknsnlBs+0i6wJBUGwqVoNSwDdY4LOM/NupexvO0EaQkEQbDHIXfWgXM5m8bTjON91iqyCgiC4u1JZnCTCFhP0UjZLA47jnOsG+R/k+/691SoiZJPJ5G8hxFNSDv7YLbIM+b5/v0FuN8isQX5KA1mC8nn/QebFswBtNNU1A4idrmv9khZiIP0DET1ikD8AscN1rV/TRPoN9anrorQaFQMzP6mU9XNaXbi8qK4ub/pLiMyuVMs7bnU0Yc2qcKcpjjnmzICUg993m9mq30RflqC41Z53ajNRdbKni+oK1offRIxprW+r1ehsT398CWyDwR6qFwhXmMmS0i62UyBN9wxRsL5sTuJW17dbC18DeNhkVmMmV0p7pJXMWsoo0Y2930DGWKMtsRA8JKX92XqZtZVRHCja5M/Ozn1FRI+bd4vM9KJSzkdrYR1BUbDo2HL58pUvAewwYwYi3qeU9X4jrGMoChYdxC5cmDlFRLtWgvN+17WPXY11BUXBGh0thaBXpXTeTWJdQ1EwrfW1tRp90dPDctzq+vF/xgPIit8x8xtK2YeWxrCVydbqN3250EhM6kytxh8nr2iEoIOpZhRj9Usn/wMAe+ul34NLpwTGw8P+YYCGiOjIf5yH1rQHeb5wAAAAAElFTkSuQmCC"
alt="">
</div>
<div class='button-next' @click.stop='nextEl'><img
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAwCAYAAAAPfWqeAAADa0lEQVRYR9XYX4hUVRwH8O9v7zTjto5buy6N9OaDL0FQrJBQ0IzW2jbb6M7sae+CiSRhD/2hIHrQQHvopR4KCgp0Qejeu/fOmoTFmgoFPYQFgYIUiWIuqUREhKI1c74x3jPuqOvuzu6Zge7rDL8P5/x+55zfOeJ50RsifIXEuOuO7BIRogWf+H44TeL+WmwR7B0dHXlBRLRtS4IgfFNrvDMTWPa7bmmbbUxqgO9Hb5PcWcdExHccblFKVW2N7DpU+4IgfEtr7G7Aokxm5Vg2m63YwG5ABrtlGnFwzZrVqr+//9+lYjdBtWCeF70O8N2GkR3q7u4qDQ4OXlsKdhsU56z8Mqnfn8Ewlcn0bc5ms1cXi80KmWl8kZQPSdb/czSd7iwMDQ1dWQx2RyjGou1a82MAHfE6k697elbkBwYGLjeLzQnFOStvBfS+Ogbg266u1GChUPi7GWxeKM5ZOAZgPwnH7CDfOQ42KqX+Wii2IMiMTInwU5IJg32fTt89kM/n/1wItmDIjGwziQkAd5mc/ZhKOU8MDw//MR/WFFQLNjFRHtKaEcmUwU44DjcopX6fC2saMtX4lNY8AGCZCX4KSOXGxgqX7oQtCopHNrlB6+rnJDpN8J9FUjnXLfw2G7ZoKM5Z9DjJQwC6TIGcTiadbLFYnL4VWxJksMdIfAEwbbCzBjvXiC0ZqgULw3BdpYIpACvi4HIulerIFYvFM3XMChQXyORarfVXAO8x2HQyKblSqfTLdXq++m/m9yCYfJisHiHRY7ALBvvJKmR2kAdF9FESfSZnl8iO9dYhgz0goo+RuM/MyPH/L+R55dZPne+XHyJ5BGBvy4ohLu/qYQD3tqy8g2DyEbI6RaLbVNqvZnewt2DDMHy0UpEvW7oFzbapAsmc6246b21Tbcsx4XnhRgCfNR58iQTWK6UuWjv4giDKkyjXj3IAJw1i7yj3/bD1zUkQRCMkvJl2S35IpzuftNputaWBDILoOa053tKW2PfD50l80oB809vb/bTVJt/3yzsAflS/tojIseXLlz1j9driedFLAD9oWBOHV63q22T1IhYE4Wta470b3YuI/avl7W8OOJhI4Fml1D/NNClzdqq+H+0iuWdmJChnMn2u1et/Wx402vZE07ZHp9ozGoBXRTA+Olra2apntP8AQCOqBFQ0cxQAAAAASUVORK5CYII="
alt="">
</div>
</el-col>
<!-- 表单-->
<el-col :span="6" style="z-index: 5">
<div class="" style="background-color: #ffffff;height:420px ">待补充</div>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<div class="hot_school" v-if="state.hotSchoolList && state.hotSchoolList.length>0">
<div class="l_title clearfix">
<div class="left_title">热门院校</div>
<div class="right_tab clearfix">
<div class="hot_school_tab am_l set_hoverl" :class="{'active':1==state.hotTabActive}"
@click="switchHotTab(1)">河南本科院校
</div>
<div class="hot_school_tab am_l set_hoverl" :class="{'active':2==state.hotTabActive}"
@click="switchHotTab(2)">河南专科院校
</div>
<div class="hot_school_tab am_l set_hoverl" :class="{'active':3==state.hotTabActive}"
@click="switchHotTab(3)">省外本科院校
</div>
<div class="hot_school_tab am_l set_hoverl" :class="{'active':4==state.hotTabActive}"
@click="switchHotTab(4)">省外专科院校
</div>
<!-- <div class="change_group">换一换<i></i></div>-->
</div>
</div>
<div class="hot_school_box clearfix">
<div class="left" style="background: rgb(255, 141, 66);">
<a :href="'/school/'+state.hotSchoolList[0].schoolCode" target="_blank">
<h3>{{ state.hotSchoolList[0].schoolName }}</h3>
<p class="tag">
<span v-for="item in state.hotSchoolList[0].tagsList">{{ item }}</span>
</p>
<div class="tuijian" v-if="state.hotSchoolList[0].schoolIcon">
<div class="school_tuijian">
<div class="school_img"><img :src="state.hotSchoolList[0].schoolIcon" alt=""></div>
</div>
</div>
</a></div>
<div class="right">
<div v-for="(item,index) in state.hotSchoolList">
<div class="school_item" data-growing-container="" v-if="index>0">
<a :href="'/school/'+item.schoolCode" target="_blank">
<img :src="item.schoolIcon" alt="">
<div class="school_msg"><h3>{{ item.schoolName }}</h3>
<div class="clearfix check_btn">
<span class="school_class">{{ item.institutionType + '类' }}</span>
<span>查看院校<i></i></span>
</div>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</el-col>
</el-row>
<el-row :gutter="20" class="margin-top-5">
<el-col :span="14">
<div class="school-footer_footerBox">
<div class="school-footer_leftIntroduce">
<div class="school-footer_useIntro"><h3>系统使用说明</h3>
</div>
<p>1本查询系统的信息仅供参考具体数据请以学校官网或考试院公布为准</p>
<p>2本站数据未经授权严禁转载违者将依法追究责任</p>
<p>3如有任何疑问可发送邮件至<a @click="copyText('yitisheng@163.com')" class="a-button hover_style"
style="color:var(--el-color-primary);">yitisheng@163.com</a></p>
<p>4志愿填报服务客服专线xxx-xxxx-xxx高校合作或其他商务客服电话xxx-xxxx-xxx</p>
<p class="school-footer_friendChain"><span>友情链接</span><a href="https://www.eol.cn/"
target="_blank">中国教育在线</a><a
href="https://gaokao.eol.cn/" target="_blank">高考频道</a><a href="https://www.kaoyan.cn/"
target="_blank">掌上考研</a><a
href="https://kaoyan.eol.cn/" target="_blank">考研频道</a><a href="https://www.zhijiao.cn/"
target="_blank">职教网</a><a
href="https://www.gaokao.cn/px/" target="_blank">掌上培训</a><a href="https://www.jiuyeqiao.cn/"
target="_blank">就业桥</a><a
href="https://yun.eol.cn/" target="_blank">数智云服</a></p></div>
<!-- <div class="school-footer_rightCode__3VuW7 clearfix">
<div class="school-footer_codeItem__1Spmk"><img src="/static/media/gzh.ab190311.jpg">
<p>掌上高考公众号</p></div>
<div class="school-footer_codeItem__1Spmk"><img src="/static/media/app.289cbf0b.png">
<p>掌上高考APP</p></div>
</div>-->
</div>
</el-col>
<el-col :span="2"></el-col>
<el-col :span="8">
<div class="qrcode">
<div class="qrcode-item">
<img src="@/assets/images/qrcode/wx_gh_cbefbadc1f1f_344.jpg" alt="" width="135">
<div class="qrcode-text" style="">微信小程序</div>
</div>
</div>
</el-col>
</el-row>
</div>
<el-backtop :bottom="100" :visibility-height="100">
<el-icon color="#409efc" class="no-inherit">
<Share/>
</el-icon>
</el-backtop>
<div class="margin-5"></div>
</template>
<style scoped lang="scss">
root {
width: 100%;
}
/*轮播图 start*/
.header_swiper {
z-index: -1;
width: 1200px !important;
height: 420px !important;
}
.swiper {
width: 100%;
height: 100%;
}
.swiper-wrapper {
position: relative;
width: 100%;
height: 100%;
z-index: 1;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-transition-property: -webkit-transform;
transition-property: -webkit-transform;
-o-transition-property: transform;
transition-property: transform;
transition-property: transform, -webkit-transform;
-webkit-box-sizing: content-box;
box-sizing: content-box;
}
.swiper-slide {
text-align: center;
font-size: 18px;
background: #fff;
/* Center slide text vertically */
display: flex;
justify-content: center;
align-items: center;
width: 1200px;
height: 420px !important;
}
.swiper-slide img {
-webkit-flex-shrink: 0;
flex-shrink: 0;
width: 100%;
height: 100%;
position: relative;
-webkit-transition-property: -webkit-transform;
transition-property: -webkit-transform;
-o-transition-property: transform;
transition-property: transform;
transition-property: transform, -webkit-transform;
}
swiper-slide img {
display: block;
margin: 0 auto;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.button-prev {
position: absolute;
top: 185px;
left: 10px;
z-index: 99;
cursor: pointer;
}
.button-next {
position: absolute;
top: 185px;
right: 300px;
z-index: 99;
cursor: pointer;
}
/*轮播图 end*/
//
.hot_school {
margin-bottom: 40px;
/*padding: 0 20px;*/
.l_title {
height: 44px;
line-height: 44px;
border-bottom: 2px solid var(--el-color-primary);
width: 100%;
.left_title {
font-size: 20px;
color: #000;
position: relative;
padding-left: 12px;
width: 330px;
float: left;
font-weight: 700;
.right_tab {
margin-left: 10px;
float: left;
width: 820px;
}
}
.right_tab .hot_school_tab.active {
color: var(--el-color-primary);
}
.right_tab .hot_school_tab {
float: left;
font-size: 18px;
color: #000;
margin-right: 32px;
cursor: pointer;
font-weight: 700;
}
.right_tab .hot_school_tab:hover {
color: var(--el-color-primary);
}
.am_l {
transition: all .4s;
}
.change_group {
float: right;
color: #f60;
font-size: 14px;
text-align: right;
cursor: pointer;
width: 68px;
height: 44px;
position: relative;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
}
.hot_school_box {
.left {
float: left;
width: 330px;
height: 332px;
background: #ffeaea;
text-align: center;
padding-top: 28px;
cursor: pointer;
h3 {
font-size: 24px;
color: #fff;
margin-bottom: 20px;
overflow: hidden;
/*text-overflow: ellipsis;*/
white-space: nowrap;
transition: all .4s;
padding: 0 10px;
font-weight: 700;
}
.tag {
margin-bottom: 54px;
span {
display: inline-block;
padding: 4px 5px;
margin-right: 10px;
border-radius: 4px;
border: 1px solid hsla(0, 0%, 100%, .4);
color: #fff;
}
span:last-child {
margin: 0;
}
}
.tuijian {
width: 195px;
height: 159px;
position: relative;
margin: 0 auto;
.school_tuijian {
width: 170px;
height: 187px;
background: #fff;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
}
.school_img {
height: 100%;
position: relative;
img {
width: 128px;
height: 128px;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
}
}
.right {
float: right;
width: 820px;
height: 350px;
margin: 10px 0 0 10px;
.school_item:hover {
top: -2px;
box-shadow: 0 10px 20px rgb(0 0 0 / 10%);
}
.school_item:hover .school_msg h3 {
color: var(--el-color-primary);
}
.school_item {
cursor: pointer;
float: left;
height: 110px;
width: 263px;
overflow: hidden;
margin-right: 10px;
margin-bottom: 10px;
position: relative;
transition: all .2s linear;
top: 0;
box-shadow: 0 0 15px #e6e6e6;
background-color: white;
img {
width: 65px;
height: 65px;
position: absolute;
left: 15px;
top: 50%;
-webkit-transform: translateY(-50%);
transform: translateY(-50%);
border: 0;
vertical-align: top;
}
.school_msg {
margin-left: 100px;
margin-top: 21px;
padding-right: 16px;
h3 {
color: #000;
font-size: 16px;
margin-bottom: 23px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
transition: all .4s;
font-weight: 700;
}
.check_btn {
.school_class {
display: inline-block;
padding: 0 6px;
border: 1px solid #eee;
}
span {
float: left;
font-size: 12px;
color: #999;
}
span + span {
margin-right: 12px;
float: right;
display: flex;
justify-content: center;
align-items: center;
}
span + span i {
display: inline-block;
width: 5px;
height: 9px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAASCAYAAABit09LAAAAoklEQVQoU43SsQ0CMQwFUPsaZqOlp4wLdDRQMAUVXBEzABWiSwkbMEX2+OgiOOlIHOL6+cuyPlPj8OhU9UpEDxG5WHsJeu9vRLTquq53zg0lnGAIYRFjvANYWjjBFjzBf3gGaziDFi7CAl6b8PPfAcCGiA4mVNUTgJ6ZzyKyLcJfNKZnsIQyaKEZrKEJquoRwO57uFkK7/2LmZ8isq/WrKW7b6OXhYE4bznBAAAAAElFTkSuQmCC);
background-size: cover;
margin: 0 0 0 5px;
}
}
}
}
}
}
}
.l_title .change_group i {
display: inline-block;
width: 16px;
height: 13px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAaCAYAAADWm14/AAADS0lEQVRIS73WXYjUZRTH8c8ZV8ylV8J8IagwCqOiqKTwppIogjIMC40oQmdmV0zWCgyKll4IwcwybeeP0U0k1UUpRV70Kt3ZC3RRhGhZmVEWdtFW6848Mf9mZXVndnYd6H875/k93/Ob85xzwiS+1ONqNcsk84VzcJrksPCz5DMFO9W8G5nBicpGu8DUr+CgxVgjueaY+FCTFI7TOCRscIrnY70/2+mPC5BWOdWQbZKbc6HwHQaE3abYa4Yf/KLbsLOFa7FYckMj9hthaQz4YjyIlgCp1/mG7cA87FfQ53o74g7V8QRT2eWSTZIFwj+4LSp2tjrTFCCtMsOQLyWzhA8kd0bmUDs7R35Pr5vifU9IHsbfwo1RsavZ+eYAJTsktwhvWmhJu6xbgaWix9AvHDDdxbHR4eNjxwCksnvVvJzb3u2yZocm6kQ9Lo0kw9bIrGgP0K/LQbfi+6j4dDKXNYtNq830l32YquC8GHBgdFzbZ9gpQO5C0XO4X3gyKh79/wF6XKGau7k7MvNbAuTV+5ELYouvO8089TgDl+Y6Sb1lvYNpprgJR1RVI/PJ0b8gv/w9r+F2YW1UrOsEIpXdp+allhphWDg3B2i021ckS48eCA9FxfqOIEqekawZo1G/PFkWmTci1e0p5c/unjGBBWtiwLMdQmyUrB6lURXuikrutkhFW9AzjlXLozKOlROgSyUvSFbmlZDcHZlXR47VAdYJsxrFsgBzRd4264On/u3qGOA/lx/Ensi81foVlJXUDODFyPROILmOQ45pRKnsLDU/YtBUc2Oz3zq+oY3A2FlQslnKs69EptwpQD6eT/Jtq5kyFqBoNr7C6eiLzMYThUi9rlL1sSTpcmWzBtdqHC+S8mKpl8+KEynC1Guear5L1Av8qcg80iyR1htR0QNY33g6j5vj6eg3NBE3UklRyvtHt/C22RZFv9qkAPIOWbRc5G94mrAHGyTbIvPH8WKpz3SDlqB8dHmtL6fJ2sgcaQXedhynkouwddRGXN8JP8de4XfJzHpPx4WSkxsX/ST0RsX2do61BRgRSEXXYSUWNgp0jAnCh8IWs2yPfsPtLs9b8USCRsc0RvYlquYIZ0p+1WWfgv2xKd+CJ/X9Czm9FazO5CrrAAAAAElFTkSuQmCC);
position: absolute;
right: 0;
top: 36%;
margin-top: -6 px;
transition: all .4s;
-webkit-transform-origin: center;
transform-origin: center;
background-size: cover;
}
//使
.school-footer_footerBox {
width: 1200px;
/*margin: 0 auto;*/
background: hsla(0, 0%, 98%, .96);
display: flex;
align-items: center;
justify-content: space-between;
.school-footer_leftIntroduce {
padding: 18px;
h3 {
font-size: 20px;
color: #000;
margin: 0 20px 0 0;
}
a {
color: #666;
text-decoration: none !important;
}
.school-footer_useIntro {
display: flex;
align-items: center;
margin-bottom: 30px;
}
.school-footer_friendChain a {
margin-right: 15px;
transition: all .3s;
}
.school-footer_friendChain a:hover {
color: var(--el-color-primary);
}
p {
font-size: 14px;
color: #000;
margin-bottom: 15px;
word-break: break-all;
a {
font-size: 14px;
color: #000;
}
}
p:last-child {
margin: 0;
}
}
}
// start
.qrcode {
margin: 50px 0;
}
.qrcode .qrcode-item {
width: 135px;
text-align: center;
}
.qrcode .qrcode-item .qrcode-text {
font-weight: bold;
color: #000000;
}
// end
</style>

View File

@ -0,0 +1,15 @@
<script lang="ts">
import {defineComponent} from 'vue'
export default defineComponent({
name: "MajorInfo"
})
</script>
<template>
</template>
<style scoped>
</style>

View File

@ -0,0 +1,15 @@
<script lang="ts">
import {defineComponent} from 'vue'
export default defineComponent({
name: "search"
})
</script>
<template>
</template>
<style scoped>
</style>

316
src/views/school/search.vue Normal file
View File

@ -0,0 +1,316 @@
<script setup lang="ts">
import StaticConstant from "@/utils/StaticConstant";
document.title = '全国大学名单|排名排行榜';
import {ComponentInternalInstance, getCurrentInstance, reactive, ref} from 'vue'
import type {TabsPaneContext} from 'element-plus'
import apiConstant from "@/utils/ApiConstant";
import {AxiosResponse} from "axios";
import {SchoolEntity} from "@/types";
const {proxy} = getCurrentInstance() as ComponentInternalInstance;
const selectForm = ref({
schoolName: '',
addressList: [],
institutionType: "",
schoolType: "",
tagsList: [],
pageNum: 1,
pageSize: 10,
})
//tabs
const activeTabsName = ref('yxk')
const state = reactive({
schoolList: [] as Array<SchoolEntity>,
size: 10,
total: 0,
current: 1,
loading: false,//? true /false
})
schoolList()
//
function schoolList() {
state.loading = true;
state.schoolList = []
proxy?.$axios({
url: apiConstant.School.searchSchoolList,
method: 'get',
params: selectForm.value,
showLoading: false,//
}).then((response: AxiosResponse) => {
return response?.data
}).then((data) => {
state.loading = false;
if (data.success) {
let dataResult = data.result
console.log(dataResult)
let tags = []
if (dataResult.records != null && dataResult.records != undefined) {
for (let i = 0; i < dataResult.records.length; i++) {
tags = []
let dre = dataResult.records[i]
if (dataResult.records[i].tagsList != null && dataResult.records[i].tagsList != undefined) {
tags.push(...dre.tagsList)
}
dataResult.records[i].tagsList = tags
}
}
state.schoolList = dataResult.records
state.size = data.result.size
state.current = data.result.current
state.total = data.result.total
}
}).catch((error: any) => {
console.log(error);
}).finally(() => {
});
}
const handlePage = (page: number) => {
if (page) {
selectForm.value.pageNum = page
schoolList()
}
}
//
const handleTabsClick = (tab: TabsPaneContext, event: Event) => {
console.log(tab, event)
}
const showSchoolInfo = (schoolCode: string) => {
window.open(schoolCode, '_blank')
}
</script>
<template>
<div class="main-container wrap main-fullScreen main-div" style="height: unset;">
<el-row :gutter="20">
<!-- 左侧 院校列表-->
<el-col :xs="17" :sm="17">
<el-card class="box-card">
<el-tabs v-model="activeTabsName" class="demo-tabs" @tab-click="handleTabsClick">
<el-tab-pane label="院校库" name="yxk">
<el-form :inline="true" :model="selectForm" class="demo-form-inline">
<el-form-item :inline="true">
<el-input style="width: 70%" :input-style="{background:'none !important'}"
v-model="selectForm.schoolName" class="w-50 m-2 input-border-style"
size="large" placeholder="输入院校名称"/>
<el-button size="large" type="primary" style="margin-left: 5px" plain @click="schoolList">搜索
</el-button>
</el-form-item>
<el-form-item label="院校所属">
<el-checkbox-group v-model="selectForm.addressList" @change="schoolList">
<el-checkbox v-for="item in StaticConstant.addressList" :label="item.code" name="address">
{{ item.name }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="院校类型">
<el-radio-group v-model="selectForm.institutionType" @change="schoolList">
<el-radio label="" name="address">不限</el-radio>
<el-radio v-for="item in StaticConstant.institutionTypeList" :label="item.code" name="institutionType">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="办学类型">
<el-radio-group v-model="selectForm.schoolType" @change="schoolList">
<el-radio label="" name="schoolType">不限</el-radio>
<el-radio v-for="item in StaticConstant.schoolTypeList" :label="item.code" name="schoolType">
{{ item.name }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="院校特色">
<el-checkbox-group v-model="selectForm.tagsList" @change="schoolList">
<el-checkbox v-for="item in StaticConstant.tagsList" :label="item.code" name="tags">{{ item.name }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-form>
<el-divider />
<!--clearable-->
<div class="schoolList">
<div class="schoolItem" v-for="item in state.schoolList" @click="showSchoolInfo(item.schoolCode)">
<div class="schoolLogo">
<img :src="item.schoolIcon" v-if="item.schoolIcon!=null && item.schoolIcon!=undefined"/>
<img v-else src="@/assets/images/school/school_default.png">
</div>
<div class="schoolInfo">
<div class="schoolTitle">
<h3 class="schoolName">
{{ item.schoolName }}
<span class="province"
v-if="item.province">{{ item.province }}{{ item.city }}{{ item.area }}</span>
</h3>
</div>
<div class="schoolTags">
<span v-for="tag in item.tagsList">{{ tag }}</span>
</div>
</div>
</div>
</div>
<el-skeleton :loading="state.loading" style="padding-top: 25px;"></el-skeleton>
<div class="page">
<el-pagination background @current-change="handlePage" :current-page="state.current"
:page-size="state.size" :total="state.total"
layout="total, prev, pager, next,jumper"/>
</div>
</el-tab-pane>
<!-- <el-tab-pane label="分数榜" name="fsb">Config</el-tab-pane>-->
</el-tabs>
</el-card>
</el-col>
<!-- 右侧 功能广告-->
<el-col :xs="7" :sm="7">
<div class="page-right" style="width: 300px">
<a><!--@click="router.push({path: '/school/search'})"-->
<img src="@/assets/images/pyxz.png" height="130" width="300">
</a>
<Mngk/>
</div>
</el-col>
</el-row>
</div>
</template>
<style scoped lang="scss">
//
.demo-tabs > .el-tabs__content {
padding: 32px;
color: #6b778c;
font-size: 32px;
font-weight: 600;
}
//
/** 默认样式 */
.input-border-style {
border: 1px solid #eee !important;
border-radius: 6px !important;
}
:deep(.el-input__wrapper) {
background: none !important;
}
</style>
<!--学校列表-->
<style scoped lang="scss">
.schoolList {
.schoolItem:hover {
color: #3491FA
}
.schoolItem:last-child {
border-bottom: none;
}
.schoolItem {
display: flex;
justify-content: flex-start;
align-items: center;
padding: 20px;
cursor: pointer;
border-bottom: 1px solid #eee;
position: relative;
.schoolLogo {
margin-right: 20px;
img {
width: 60px;
height: 60px;
}
}
.schoolInfo {
.schoolTitle {
margin-bottom: 18px;
.schoolName {
color: #333;
font-size: 18px;
height: 25px;
line-height: 25px;
margin: 0 20px 0 0;
transition: all .3s;
display: flex;
align-items: center;
.province {
height: 26px;
line-height: 24px;
font-size: 12px;
border: 1px solid #eee;
color: #555;
display: inline-block;
padding: 0 10px;
margin: 0 20px 0 15px;
}
}
.schoolName:hover {
color: #3491FA
}
}
.schoolTags {
span {
display: inline-block;
color: #555;
padding-right: 10px;
margin-right: 10px;
border-right: 1px solid #c5c5c5;
line-height: 15px;
}
span:last-child {
border: none;
}
}
}
}
}
.page-right {
.box-card {
border-radius: 12px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
color: red;
}
:deep(.el-card__header) {
padding: 6px 12px 12px 12px;
background-color: #4cc8ff;
height: 30px;
span {
width: 100px;
height: 16px;
background-size: cover;
background-image: url(data:image/png;base64,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);
}
}
.item {
border-radius: 12px;
}
:deep(.el-card__body) {
padding: 0;
}
}
</style>

25
tsconfig.json Normal file
View File

@ -0,0 +1,25 @@
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"skipLibCheck": true,
//TypeScriptimport
"baseUrl": "./",
"paths": {
"@/*": ["./src/*"],
//"@components/*": ["./src/components/*"],
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "src/utils/markdownPlugin/remark-directive.ts", "src/utils/markdownPlugin/mdast-util-directive.js"],
"references": [{ "path": "./tsconfig.node.json" }]
}

11
tsconfig.node.json Normal file
View File

@ -0,0 +1,11 @@
{
"compilerOptions": {
"composite": true,
"module": "esnext",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true // ""path"" 使 "allowSyntheticDefaultImports"
},
"include": ["vite.config.ts",
"vite.config"
]
}

35
vite.config.ts Normal file
View File

@ -0,0 +1,35 @@
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
import path from 'path'
export default defineConfig({
plugins: [
vue(),
// 自动导入Element Plus
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
server: {
host: "0.0.0.0", // 监听所有地址(局域网和公网)
port: 5000, // 自定义端口号
},
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
},
css: {
preprocessorOptions: {
scss: {
additionalData: `@use "@/assets/css/base.css" as *;@use "@/assets/css/global.scss" as *;` //加载各模块样式
},
}
},
});

5
xxx.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
declare module "*.vue" {
import { DefineComponent } from "vue"
const component: DefineComponent<{}, {}, any>
export default component
}