Conflicts:
	.env.production
GST002
喻忠伟 2 months ago
commit b31cf9ff02
  1. 2
      .env.development
  2. 2
      .env.production
  3. 83
      src/Layout/footer/index.vue
  4. 339
      src/Layout/tabbar/index.vue
  5. 40
      src/api/person.ts
  6. BIN
      src/assets/images/bl.png
  7. BIN
      src/assets/images/bzbanner.png
  8. BIN
      src/assets/images/hl.png
  9. BIN
      src/assets/images/pk.png
  10. BIN
      src/assets/images/signup-bg.jpg
  11. 22
      src/main.ts
  12. 10
      src/router/module/constRouter/index.ts
  13. 53
      src/store/module/theme.ts
  14. 147
      src/styles/dark.scss
  15. 10
      src/styles/index.scss
  16. 147
      src/styles/light-blue.scss
  17. 147
      src/styles/light-purple.scss
  18. 75
      src/styles/themes.ts
  19. 62
      src/styles/variables.scss
  20. 10
      src/utils/requset.ts
  21. 983
      src/views/home/index.vue
  22. 84
      src/views/news/hostNews.vue
  23. 43
      src/views/news/index.vue
  24. 2
      src/views/projectName/index.vue
  25. 70
      src/views/raceInfo/index.vue
  26. 16
      src/views/registrationGroup/components/stuDialog.vue
  27. 107
      src/views/registrationGroup/components/stuList.vue
  28. 13
      src/views/registrationGroup/components/teaDialog.vue
  29. 35
      src/views/registrationGroup/components/teaList.vue
  30. 113
      src/views/registrationGroup/index.vue
  31. 83
      src/views/registrationPersonage/index.vue
  32. 88
      src/views/userInfo/index.vue

@ -4,3 +4,5 @@ VITE_APP_TITLE = '教学一体化平台'
VITE_APP_BASE_API = http://localhost:18085/jeecg-boot
# VITE_APP_BASE_API = 'http://127.0.0.1:8080'
VITE_APP_BASE_API_JEECG = '/student'
VITE_APP_PC_URL = http://localhost:18085/jeecg-boot
VITE_APP_MOBILE_URL = http://localhost:18085/jeecg-boot

@ -3,3 +3,5 @@ NODE_ENV = 'development'
VITE_APP_TITLE = '高赛通单项目'
VITE_APP_BASE_API = http://115.190.99.211:18086/jeecg-boot
# VITE_APP_BASE_API = 'http://127.0.0.1:8080'
VITE_APP_PC_URL = http://localhost:18085/jeecg-boot
VITE_APP_MOBILE_URL = http://localhost:18085/jeecg-boot

@ -1,10 +1,10 @@
<template>
<div class="footer">
<div class="footer" :class="{ 'dark-layout': useThemeStore.isDark }">
<div class="footer-nav">
<div v-for="item in NewList" :key="item.id" @click="toNewsDetail(item.id)">
<div class="item">
{{ item.title }}
</div>
{{ item.title }}
</div>
</div>
</div>
<div class="copyright">源码自然版权所有@2023 湘豫CP备 19005950-1</div>
@ -18,7 +18,9 @@
import { ref} from 'vue'
import { queryNewListApi } from '@/api/news'
import { useRouter } from 'vue-router'
import themeStore from '@/store/module/theme'
const useThemeStore = themeStore()
const NewList = ref<any>([])
const getNewList = async () =>{
const res:any = await queryNewListApi()
@ -32,25 +34,23 @@ const router = useRouter()
const toNewsDetail = (id: number) => {
router.push({
path: '/detail/' + id,
})
}
</script>
<style lang="scss" scoped>
.footer {
// position: fixed;
// bottom: 0;
height: 300px;
width: 100%;
// background-color: #252527;
height: 300px;
background: url('../../assets//images/footer.png') no-repeat;
background-size: cover;
display: flex;
flex-direction: column;
align-items: center;
// justify-content: center;
color: #333333;
color: var(--text-color);
position: relative;
transition: all 0.3s;
.footer-nav {
display: flex;
margin-top: 120px;
@ -59,6 +59,7 @@ const toNewsDetail = (id: number) => {
text-align: center;
font-size: 18px;
cursor: pointer;
transition: all 0.3s;
}
.item:nth-child(2) {
border-left: 1px solid #333333;
@ -68,11 +69,73 @@ const toNewsDetail = (id: number) => {
color: #0bd7c6;
}
}
.copyright {
margin-top: 80px;
}
.report {
margin-top: 0.1042rem;
}
&.dark-layout {
background: var(--card-bg-color);
border-top: 1px solid var(--border-color);
color: var(--text-color);
// height: auto;
padding: 60px 0;
&::before {
content: '';
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
width: 1420px;
height: 3px;
background: var(--gradient-color);
}
.footer-nav {
position: absolute;
left: calc(50% - 1420px/2 );
top: 60px;
flex-direction: column !important;
gap: 20px;
margin-top: 0;
.item {
width: auto;
padding: 0 20px;
border: none;
opacity: 0.9;
transition: all 0.3s;
color: var(--text-color);
font-weight: 500;
text-align: left;
&:hover {
color: var(--primary-color);
opacity: 1;
}
}
}
.copyright, .report {
position: absolute;
left: calc(50% - 1420px/2 + 20px);
color: var(--text-color);
opacity: 0.8;
font-weight: 500;
}
.copyright {
top: 140px;
}
.report {
top: 160px;
}
}
}
</style>

@ -4,7 +4,7 @@
<div class="left">
<div class="logo-box">
<div class="lesson">
<img :src="logoUrl" alt="" />
<img :src="logoUrl" alt="" v-default-image="logoImage" />
<!-- <img src="../../assets/images/LOGO.png" alt=""> -->
</div>
</div>
@ -26,6 +26,35 @@
</div>
</div>
<div class="right" v-if="!useUserStore.token">
<div class="theme-switch">
<el-popover
v-model:visible="showThemePopover"
placement="bottom"
:width="200"
trigger="manual"
>
<template #reference>
<el-icon class="theme-icon" @click="showThemePopover = !showThemePopover">
<Setting />
</el-icon>
</template>
<div class="theme-popover">
<div class="theme-title">主题设置</div>
<div class="theme-list">
<div
v-for="theme in useThemeStore.themes"
:key="theme.name"
class="theme-item"
:class="{ active: currentThemeName === theme.name }"
@click="handleThemeChange(theme.name)"
>
<div class="theme-color" :style="{ backgroundColor: theme.primaryColor }"></div>
<span class="theme-name">{{ theme.name }}</span>
</div>
</div>
</div>
</el-popover>
</div>
<div
class="registered gradient"
@click="$router.push('/login?registered=true')"
@ -35,6 +64,35 @@
<div class="login" @click="$router.push('/login')">登录</div>
</div>
<div class="right" v-else>
<div class="theme-switch">
<el-popover
v-model:visible="showThemePopover"
placement="bottom"
:width="200"
trigger="manual"
>
<template #reference>
<el-icon class="theme-icon" @click="showThemePopover = !showThemePopover">
<Setting />
</el-icon>
</template>
<div class="theme-popover">
<div class="theme-title">主题设置</div>
<div class="theme-list">
<div
v-for="theme in useThemeStore.themes"
:key="theme.name"
class="theme-item"
:class="{ active: currentThemeName === theme.name }"
@click="handleThemeChange(theme.name)"
>
<div class="theme-color" :style="{ backgroundColor: theme.primaryColor }"></div>
<span class="theme-name">{{ theme.name }}</span>
</div>
</div>
</div>
</el-popover>
</div>
<div class="avater">
<img
:src="setImageUrl(useUserStore.userInfo.avatar)"
@ -69,13 +127,28 @@ import { useRouter, useRoute } from 'vue-router'
import { onMounted, ref, watch } from 'vue'
import userStore from '@/store/module/user'
import settingStore from '@/store/module/setting'
import themeStore from '@/store/module/theme'
import Item from './components/item.vue'
import defaultUserAvater from '@/assets/images/default.png'
import { Setting } from '@element-plus/icons-vue'
import logoImage from '@/assets/images/LOGO.png'
const useUserStore = userStore()
const useSettingStore = settingStore()
const useThemeStore = themeStore()
const $router = useRouter()
const $route = useRoute()
const flog = ref(false)
//
const currentThemeName = ref(useThemeStore.currentTheme.name)
const handleThemeChange = (themeName: string) => {
const selectedTheme = useThemeStore.themes.find(t => t.name === themeName)
if (selectedTheme) {
useThemeStore.setTheme(selectedTheme)
}
}
onMounted(() => {
window.addEventListener('scroll', () => {
if (window.scrollY >= 50) {
@ -108,6 +181,8 @@ watch(
},
)
// getLogoSetting()
const showThemePopover = ref(false)
</script>
<style lang="scss" scoped>
@ -138,12 +213,86 @@ watch(
.tabbar {
position: fixed;
top: 0;
z-index: 1;
height: 80px;
left: 0;
width: 100%;
background-color: transparent;
animation-duration: 0.3s;
animation-name: tabber-to;
z-index: 999;
transition: all 0.3s;
// background-color: var(--background-color);
border-bottom: 1px solid var(--border-color);
.container {
width: $base-container-width;
height: 80px;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
.left {
display: flex;
align-items: center;
.logo {
width: 200px;
height: 80px;
display: flex;
align-items: center;
img {
width: 100%;
height: 100%;
}
}
.menu {
margin-left: 40px;
:deep(.el-menu) {
background-color: transparent;
border: none;
.el-menu-item {
color: var(--text-color);
&:hover {
color: var(--primary-color);
background-color: transparent !important;
}
&.is-active {
color: var(--primary-color);
background-color: transparent !important;
}
}
}
}
}
.right {
display: flex;
align-items: center;
.theme-switcher {
margin-right: 20px;
}
.user-info {
display: flex;
align-items: center;
cursor: pointer;
color: var(--text-color);
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 10px;
border: 1px solid var(--border-color);
}
.username {
font-size: 14px;
margin-right: 5px;
}
.el-icon {
font-size: 12px;
transition: transform 0.3s;
}
&:hover {
color: var(--primary-color);
.el-icon {
transform: rotate(180deg);
}
}
}
}
}
}
.tabbar-active {
@ -151,33 +300,56 @@ watch(
top: 0;
height: 80px;
width: 100%;
background-color: #fff;
background-color: var(--card-bg-color);
animation-duration: 0.3s;
animation-name: tabber;
z-index: 999;
box-shadow: 0px 0px 43px rgba(0, 0, 0, 0.2);
box-shadow: 0px 0px 43px rgba(0, 0, 0, 0.1);
border-bottom: 1px solid var(--border-color);
.container {
width: $base-container-width;
height: 80px;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
.menu {
margin-left: 40px;
:deep(.el-menu) {
background-color: transparent;
border: none;
.el-menu-item {
color: var(--text-color);
&:hover {
color: var(--primary-color);
background-color: transparent !important;
}
&.is-active {
color: var(--primary-color);
background-color: transparent !important;
}
}
}
}
}
}
@keyframes tabber {
0% {
// transform: translateY(-80px);
background-color: transparent;
}
100% {
// transform: translateY(0);
background-color: #fff;
background-color: var(--card-bg-color);
}
}
@keyframes tabber-to {
0% {
// transform: translateY(-80px);
background-color: #fff;
background-color: var(--card-bg-color);
}
100% {
// transform: translateY(0);
background-color: transparent;
}
}
@ -208,15 +380,20 @@ watch(
color: #fff;
}
.login {
color: #1d2129;
color: var(--text-color);
margin-left: 20px;
border: 1px solid #e5e6eb;
border: 1px solid var(--border-color);
&:hover {
color: var(--primary-color);
border-color: var(--primary-color);
}
}
.avater {
width: 35px;
height: 35px;
border-radius: 50%;
overflow: hidden;
border: 1px solid var(--border-color);
img {
width: 100%;
height: 100%;
@ -237,7 +414,7 @@ watch(
li {
padding: 12px 20px;
color: #1d2129;
color: var(--text-color);
font-size: 14px;
cursor: pointer;
transition: all 0.2s;
@ -245,7 +422,7 @@ watch(
}
li:hover {
color: #0033f7;
color: var(--primary-color);
transform: translateY(-5px);
}
@ -259,7 +436,7 @@ watch(
width: 5px;
height: 5px;
border-radius: 50%;
background-color: #fff;
background-color: var(--primary-color);
}
}
@ -300,8 +477,132 @@ watch(
:deep(.el-menu-item) {
background-color: transparent;
border-bottom: none;
&:hover {
background-color: transparent !important;
}
&.is-active {
background-color: transparent !important;
}
}
.el-dropdown-link {
white-space: nowrap;
}
.theme-switch {
margin-right: 20px;
.theme-icon {
font-size: 20px;
color: var(--text-color);
cursor: pointer;
transition: all 0.3s;
&:hover {
color: var(--primary-color);
transform: rotate(90deg);
}
}
}
.theme-popover {
.theme-title {
font-size: 16px;
font-weight: 600;
color: var(--text-color);
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid var(--border-color);
}
.theme-list {
display: flex;
flex-direction: column;
gap: 10px;
.theme-item {
display: flex;
align-items: center;
padding: 8px 12px;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s;
&:hover {
background-color: var(--background-color);
}
&.active {
background-color: var(--background-color);
.theme-name {
color: var(--primary-color);
}
}
.theme-color {
width: 20px;
height: 20px;
border-radius: 4px;
margin-right: 10px;
border: 1px solid var(--border-color);
}
.theme-name {
color: var(--text-color);
font-size: 14px;
}
}
}
}
.right {
display: flex;
align-items: center;
div {
width: 108px;
height: 40px;
text-align: center;
line-height: 40px;
border-radius: 5px;
font-size: 14px;
cursor: pointer;
}
.registered {
color: #fff;
background: var(--gradient-color);
border-radius: 20px;
transition: all 0.3s;
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
}
.login {
color: var(--text-color);
margin-left: 20px;
border: 1px solid var(--border-color);
border-radius: 20px;
transition: all 0.3s;
&:hover {
color: var(--primary-color);
border-color: var(--primary-color);
transform: translateY(-2px);
}
}
.avater {
width: 35px;
height: 35px;
border-radius: 50%;
overflow: hidden;
border: 1px solid var(--border-color);
transition: all 0.3s;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
margin-right: 20px;
&:hover {
transform: translateY(-2px);
border-color: var(--primary-color);
}
}
}
</style>

@ -1,42 +1,4 @@
import req1 from '@/utils/requset'
import { AxiosInstance } from 'axios'
function copyRequest(req1: AxiosInstance, instanceConfig = {}) {
let request: AxiosInstance, copyStatus: boolean
try {
// @ts-ignore
const req2 = req1.create(instanceConfig)
function acopyInterceptors(target: any, interceptorManager: any) {
const handlers = interceptorManager.handlers
for (let index = 0; index < handlers?.length; index++) {
const { fulfilled, rejected, runWhen, synchronous } = handlers[index]
let options
if (synchronous !== false || runWhen !== null)
options = { synchronous, runWhen }
target.use(fulfilled, rejected, options)
}
}
acopyInterceptors(req2.interceptors.request, req1.interceptors.request)
acopyInterceptors(req2.interceptors.response, req1.interceptors.response)
request = req2
copyStatus = true
} catch (error) {
console.warn('拷贝失败,私有拦截器可能失效:\n', error)
request = req1
copyStatus = false
}
return { request, copyStatus }
}
const { request, copyStatus } = copyRequest(req1)
// 若拷贝成功,添加自己独有的拦截器
if (copyStatus) {
request.interceptors.response.use((response: any) => {
if (response.code >= 200 && response.code < 300) return response
else return Promise.reject(response)
})
}
import request from '@/utils/requset'
// =============================================================================
enum api {

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

@ -12,16 +12,19 @@ import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import gloablComponent from './components/index'
// 引入全局样式
import '@/styles/index.scss'
import 'element-plus/theme-chalk/dark/css-vars.css' // 引入Element Plus暗黑主题
import './styles/dark.scss' // 引入自定义暗黑主题
import themeStore from './store/module/theme'
// 引入仓库
import pinia from '@/store/index'
import { createPinia } from 'pinia'
// 引入路由
import router from './permissions'
import '@/utils/rem.js'
import defaultImage from '@/directives/defaultImage'
// 创建vue实例
const app = createApp(App)
app.use(pinia)
const pinia = createPinia()
// 注册全局指令
app.directive('default-image', defaultImage)
@ -33,6 +36,7 @@ app.use(ElementPlus, {
// 注册全局组件
app.use(gloablComponent)
app.use(router)
app.use(pinia)
// app.use(G6)
// 挂载点
@ -42,3 +46,17 @@ import * as ElementPlusIconsVue from '@element-plus/icons-vue'
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
// 初始化主题
const useThemeStore = themeStore()
useThemeStore.initTheme()
const ua = navigator.userAgent.toLowerCase()
const isMobile = /iphone|android|ipad|mobile/.test(ua)
if (isMobile) {
console.log('手机端')
// location.href = import.meta.env.VITE_APP_MOBILE_URL
} else if (!isMobile) {
console.log('电脑端')
// location.href = import.meta.env.VITE_APP_PC_URL
}

@ -99,6 +99,16 @@ export const constRouter: any = {
hidden: false,
},
},
{
path: '/hostNews',
name: 'HostNews',
component: () => import('@/views/news/hostNews.vue'),
meta: {
icon: '',
title: '综合新闻',
hidden: false,
},
},
{
path: 'detail/:id',
name: 'newsDetail',

@ -0,0 +1,53 @@
import { defineStore } from 'pinia'
import { themes, type Theme } from '@/styles/themes'
export default defineStore('theme', {
state: () => {
return {
currentTheme: themes[0],
themes: themes,
isDark: false
}
},
actions: {
setTheme(theme: Theme) {
this.currentTheme = theme
// 更新CSS变量
document.documentElement.style.setProperty('--primary-color', theme.primaryColor)
document.documentElement.style.setProperty('--secondary-color', theme.secondaryColor)
document.documentElement.style.setProperty('--background-color', theme.backgroundColor)
document.documentElement.style.setProperty('--text-color', theme.textColor)
document.documentElement.style.setProperty('--gradient-color', theme.gradientColor)
document.documentElement.style.setProperty('--card-bg-color', theme.cardBgColor)
document.documentElement.style.setProperty('--border-color', theme.borderColor)
document.documentElement.style.setProperty('--menu-text-color', theme.menuTextColor)
document.documentElement.style.setProperty('--menu-active-color', theme.menuActiveColor)
// 更新body背景色
document.body.style.backgroundColor = theme.backgroundColor
document.body.style.color = theme.textColor
// 切换暗黑模式
this.isDark = theme.name === '暗夜主题' || theme.name === '暗夜绿主题'
if (this.isDark) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
// 保存主题到本地存储
localStorage.setItem('theme', theme.name)
},
// 初始化主题
initTheme() {
const savedTheme = localStorage.getItem('theme')
if (savedTheme) {
const theme = this.themes.find(t => t.name === savedTheme)
if (theme) {
this.setTheme(theme)
}
}
}
}
})

@ -0,0 +1,147 @@
// Element Plus 暗黑主题变量覆盖
html.dark {
// 常用颜色
--el-color-primary: var(--primary-color);
--el-color-primary-light-3: var(--primary-color);
--el-color-primary-light-5: var(--primary-color);
--el-color-primary-light-7: var(--primary-color);
--el-color-primary-light-8: var(--primary-color);
--el-color-primary-light-9: var(--primary-color);
--el-color-primary-dark-2: var(--primary-color);
// 文字颜色
--el-text-color-primary: var(--text-color);
--el-text-color-regular: var(--text-color);
--el-text-color-secondary: rgba(255, 255, 255, 0.7);
--el-text-color-placeholder: rgba(255, 255, 255, 0.3);
--el-text-color-disabled: rgba(255, 255, 255, 0.3);
// 边框颜色
--el-border-color: var(--border-color);
--el-border-color-light: var(--border-color);
--el-border-color-lighter: var(--border-color);
--el-border-color-extra-light: var(--border-color);
// 填充颜色
--el-fill-color: var(--card-bg-color);
--el-fill-color-light: var(--card-bg-color);
--el-fill-color-lighter: var(--card-bg-color);
--el-fill-color-extra-light: var(--card-bg-color);
--el-fill-color-dark: var(--card-bg-color);
--el-fill-color-darker: var(--card-bg-color);
// 背景颜色
--el-bg-color: var(--background-color);
--el-bg-color-overlay: var(--card-bg-color);
// 遮罩颜色
--el-mask-color: rgba(0, 0, 0, 0.8);
// 组件深色背景
--el-bg-color-page: var(--background-color);
// 弹窗背景
--el-popup-bg-color: var(--card-bg-color);
// 禁用状态
--el-disabled-bg-color: var(--card-bg-color);
--el-disabled-text-color: rgba(255, 255, 255, 0.3);
--el-disabled-border-color: var(--border-color);
}
// 全局组件暗黑适配
html.dark {
// 表格
.el-table {
--el-table-bg-color: var(--card-bg-color);
--el-table-tr-bg-color: var(--card-bg-color);
--el-table-header-bg-color: var(--background-color);
--el-table-border-color: var(--border-color);
th.el-table__cell {
background-color: var(--background-color);
}
}
// 分页
.el-pagination {
--el-pagination-button-bg-color: var(--card-bg-color);
--el-pagination-hover-color: var(--primary-color);
}
// 表单
.el-form {
.el-form-item__label {
color: var(--text-color);
}
}
// 输入框
.el-input {
--el-input-bg-color: var(--card-bg-color);
--el-input-border-color: var(--border-color);
--el-input-hover-border-color: var(--primary-color);
--el-input-focus-border-color: var(--primary-color);
}
// 选择器
.el-select {
.el-input {
--el-select-input-focus-border-color: var(--primary-color);
}
}
// 下拉菜单
.el-dropdown-menu {
--el-dropdown-menuItem-hover-fill: var(--card-bg-color);
--el-dropdown-menuItem-hover-color: var(--primary-color);
}
// 对话框
.el-dialog {
--el-dialog-bg-color: var(--card-bg-color);
--el-dialog-border-color: var(--border-color);
.el-dialog__header {
border-bottom: 1px solid var(--border-color);
}
}
// 卡片
.el-card {
--el-card-bg-color: var(--card-bg-color);
border-color: var(--border-color);
.el-card__header {
border-bottom: 1px solid var(--border-color);
}
}
// 标签
.el-tag {
--el-tag-bg-color: transparent;
--el-tag-border-color: var(--border-color);
&.el-tag--primary {
--el-tag-bg-color: transparent;
--el-tag-border-color: var(--primary-color);
}
}
// 按钮
.el-button {
&.el-button--primary {
--el-button-bg-color: var(--primary-color) !important;
--el-button-border-color: var(--primary-color) !important;
}
&.el-button--default {
--el-button-bg-color: var(--card-bg-color) !important;
--el-button-border-color: var(--border-color) !important;
--el-button-hover-bg-color: var(--primary-color) !important;
--el-button-hover-border-color: var(--primary-color) !important;
--el-button-active-bg-color: var(--primary-color) !important;
--el-button-active-border-color: var(--primary-color) !important;
}
}
}

@ -1,5 +1,10 @@
// 引入清除浏览器默认样式文件
@import './reset.scss';
@import './variables.scss';
@import './dark.scss';
@import './light-blue.scss';
@import './light-purple.scss';
:root {
--el-color-primary: #0BD7C6;
}
@ -8,6 +13,11 @@
margin: 0 auto;
// background-color: #c2acac;
}
.container-100{
width: 100%;
margin: 0 auto;
// background-color: #c2acac;
}
.gradient{
background: linear-gradient(90deg, rgba(66,217,172,1) 0%, rgba(0,208,208,1) 100%);
}

@ -0,0 +1,147 @@
// Element Plus 白蓝主题变量覆盖
html.light-blue {
// 常用颜色
--el-color-primary: #1890ff;
--el-color-primary-light-3: #40a9ff;
--el-color-primary-light-5: #69c0ff;
--el-color-primary-light-7: #91d5ff;
--el-color-primary-light-8: #bae7ff;
--el-color-primary-light-9: #e6f7ff;
--el-color-primary-dark-2: #096dd9;
// 文字颜色
--el-text-color-primary: #ffffff;
--el-text-color-regular: #ffffff;
--el-text-color-secondary: rgba(255, 255, 255, 0.7);
--el-text-color-placeholder: rgba(255, 255, 255, 0.3);
--el-text-color-disabled: rgba(255, 255, 255, 0.3);
// 边框颜色
--el-border-color: rgba(255, 255, 255, 0.1);
--el-border-color-light: rgba(255, 255, 255, 0.1);
--el-border-color-lighter: rgba(255, 255, 255, 0.1);
--el-border-color-extra-light: rgba(255, 255, 255, 0.1);
// 填充颜色
--el-fill-color: #1d1e1f;
--el-fill-color-light: #1d1e1f;
--el-fill-color-lighter: #1d1e1f;
--el-fill-color-extra-light: #1d1e1f;
--el-fill-color-dark: #1d1e1f;
--el-fill-color-darker: #1d1e1f;
// 背景颜色
--el-bg-color: #141414;
--el-bg-color-overlay: #1d1e1f;
// 遮罩颜色
--el-mask-color: rgba(0, 0, 0, 0.8);
// 组件深色背景
--el-bg-color-page: #141414;
// 弹窗背景
--el-popup-bg-color: #1d1e1f;
// 禁用状态
--el-disabled-bg-color: #1d1e1f;
--el-disabled-text-color: rgba(255, 255, 255, 0.3);
--el-disabled-border-color: rgba(255, 255, 255, 0.1);
}
// 全局组件白蓝主题适配
html.light-blue {
// 表格
.el-table {
--el-table-bg-color: #1d1e1f;
--el-table-tr-bg-color: #1d1e1f;
--el-table-header-bg-color: #141414;
--el-table-border-color: rgba(255, 255, 255, 0.1);
th.el-table__cell {
background-color: #141414;
}
}
// 分页
.el-pagination {
--el-pagination-button-bg-color: #1d1e1f;
--el-pagination-hover-color: #1890ff;
}
// 表单
.el-form {
.el-form-item__label {
color: #ffffff;
}
}
// 输入框
.el-input {
--el-input-bg-color: #1d1e1f;
--el-input-border-color: rgba(255, 255, 255, 0.1);
--el-input-hover-border-color: #1890ff;
--el-input-focus-border-color: #1890ff;
}
// 选择器
.el-select {
.el-input {
--el-select-input-focus-border-color: #1890ff;
}
}
// 下拉菜单
.el-dropdown-menu {
--el-dropdown-menuItem-hover-fill: #1d1e1f;
--el-dropdown-menuItem-hover-color: #1890ff;
}
// 对话框
.el-dialog {
--el-dialog-bg-color: #1d1e1f;
--el-dialog-border-color: rgba(255, 255, 255, 0.1);
.el-dialog__header {
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
}
// 卡片
.el-card {
--el-card-bg-color: #1d1e1f;
border-color: rgba(255, 255, 255, 0.1);
.el-card__header {
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
}
// 标签
.el-tag {
--el-tag-bg-color: #1d1e1f;
--el-tag-border-color: rgba(255, 255, 255, 0.1);
&.el-tag--primary {
--el-tag-bg-color: #1890ff;
--el-tag-border-color: #1890ff;
}
}
// 按钮
.el-button {
&.el-button--primary {
--el-button-bg-color: #1890ff !important;
--el-button-border-color: #1890ff !important;
}
&.el-button--default {
--el-button-bg-color: #1d1e1f !important;
--el-button-border-color: rgba(255, 255, 255, 0.1) !important;
--el-button-hover-bg-color: #1890ff !important;
--el-button-hover-border-color: #1890ff !important;
--el-button-active-bg-color: #1890ff !important;
--el-button-active-border-color: #1890ff !important;
}
}
}

@ -0,0 +1,147 @@
// Element Plus 白紫主题变量覆盖
html.light-purple {
// 常用颜色
--el-color-primary: #B46EFD;
--el-color-primary-light-3: #C08EFD;
--el-color-primary-light-5: #CCADFE;
--el-color-primary-light-7: #D8CBFE;
--el-color-primary-light-8: #E1DAFE;
--el-color-primary-light-9: #F5F0FF;
--el-color-primary-dark-2: #684FFF;
// 文字颜色
--el-text-color-primary: #ffffff;
--el-text-color-regular: #ffffff;
--el-text-color-secondary: rgba(255, 255, 255, 0.7);
--el-text-color-placeholder: rgba(255, 255, 255, 0.3);
--el-text-color-disabled: rgba(255, 255, 255, 0.3);
// 边框颜色
--el-border-color: rgba(255, 255, 255, 0.1);
--el-border-color-light: rgba(255, 255, 255, 0.1);
--el-border-color-lighter: rgba(255, 255, 255, 0.1);
--el-border-color-extra-light: rgba(255, 255, 255, 0.1);
// 填充颜色
--el-fill-color: #1d1e1f;
--el-fill-color-light: #1d1e1f;
--el-fill-color-lighter: #1d1e1f;
--el-fill-color-extra-light: #1d1e1f;
--el-fill-color-dark: #1d1e1f;
--el-fill-color-darker: #1d1e1f;
// 背景颜色
--el-bg-color: #141414;
--el-bg-color-overlay: #1d1e1f;
// 遮罩颜色
--el-mask-color: rgba(0, 0, 0, 0.8);
// 组件深色背景
--el-bg-color-page: #141414;
// 弹窗背景
--el-popup-bg-color: #1d1e1f;
// 禁用状态
--el-disabled-bg-color: #1d1e1f;
--el-disabled-text-color: rgba(255, 255, 255, 0.3);
--el-disabled-border-color: rgba(255, 255, 255, 0.1);
}
// 全局组件白紫主题适配
html.light-purple {
// 表格
.el-table {
--el-table-bg-color: #1d1e1f;
--el-table-tr-bg-color: #1d1e1f;
--el-table-header-bg-color: #141414;
--el-table-border-color: rgba(255, 255, 255, 0.1);
th.el-table__cell {
background-color: #141414;
}
}
// 分页
.el-pagination {
--el-pagination-button-bg-color: #1d1e1f;
--el-pagination-hover-color: #B46EFD;
}
// 表单
.el-form {
.el-form-item__label {
color: #ffffff;
}
}
// 输入框
.el-input {
--el-input-bg-color: #1d1e1f;
--el-input-border-color: rgba(255, 255, 255, 0.1);
--el-input-hover-border-color: #B46EFD;
--el-input-focus-border-color: #B46EFD;
}
// 选择器
.el-select {
.el-input {
--el-select-input-focus-border-color: #B46EFD;
}
}
// 下拉菜单
.el-dropdown-menu {
--el-dropdown-menuItem-hover-fill: #1d1e1f;
--el-dropdown-menuItem-hover-color: #B46EFD;
}
// 对话框
.el-dialog {
--el-dialog-bg-color: #1d1e1f;
--el-dialog-border-color: rgba(255, 255, 255, 0.1);
.el-dialog__header {
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
}
// 卡片
.el-card {
--el-card-bg-color: #1d1e1f;
border-color: rgba(255, 255, 255, 0.1);
.el-card__header {
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
}
// 标签
.el-tag {
--el-tag-bg-color: #1d1e1f;
--el-tag-border-color: rgba(255, 255, 255, 0.1);
&.el-tag--primary {
--el-tag-bg-color: #B46EFD;
--el-tag-border-color: #B46EFD;
}
}
// 按钮
.el-button {
&.el-button--primary {
--el-button-bg-color: #B46EFD !important;
--el-button-border-color: #B46EFD !important;
}
&.el-button--default {
--el-button-bg-color: #1d1e1f !important;
--el-button-border-color: rgba(255, 255, 255, 0.1) !important;
--el-button-hover-bg-color: #B46EFD !important;
--el-button-hover-border-color: #B46EFD !important;
--el-button-active-bg-color: #B46EFD !important;
--el-button-active-border-color: #B46EFD !important;
}
}
}

@ -0,0 +1,75 @@
export interface Theme {
name: string;
primaryColor: string;
secondaryColor: string;
backgroundColor: string;
textColor: string;
gradientColor: string;
cardBgColor: string;
borderColor: string;
menuTextColor: string;
menuActiveColor: string;
}
export const themes: Theme[] = [
{
name: '默认主题',
primaryColor: '#0bd7c6',
secondaryColor: '#0033f7',
backgroundColor: '#ffffff',
textColor: '#333333',
gradientColor: 'linear-gradient(to right, #0bd7c6, #0033f7)',
cardBgColor: '#ffffff',
borderColor: '#e5e6eb',
menuTextColor: '#1d2129',
menuActiveColor: '#0033f7'
},
{
name: '白蓝主题',
primaryColor: '#1890ff',
secondaryColor: '#096dd9',
backgroundColor: '#ffffff',
textColor: '#1d2129',
gradientColor: 'linear-gradient(to right, #1890ff, #096dd9)',
cardBgColor: '#ffffff',
borderColor: '#e5e6eb',
menuTextColor: '#1d2129',
menuActiveColor: '#1890ff'
},
{
name: '白紫主题',
primaryColor: '#B46EFD',
secondaryColor: '#684FFF',
backgroundColor: '#ffffff',
textColor: '#1d2129',
gradientColor: 'linear-gradient(to right, #B46EFD, #684FFF)',
cardBgColor: '#ffffff',
borderColor: '#e5e6eb',
menuTextColor: '#1d2129',
menuActiveColor: '#B46EFD'
},
{
name: '暗夜主题',
primaryColor: '#1055fc',
secondaryColor: '#e03d12',
backgroundColor: '#141414',
textColor: '#ffffff',
gradientColor: 'linear-gradient(to right, #1055fc, #e03d12)',
cardBgColor: '#1f1f1f',
borderColor: '#434343',
menuTextColor: 'rgba(255, 255, 255, 0.85)',
menuActiveColor: '#1055fc'
},
{
name: '暗夜绿主题',
primaryColor: '#61F7EE',
secondaryColor: '#2370E6',
backgroundColor: '#141414',
textColor: '#ffffff',
gradientColor: 'linear-gradient(to right, #61F7EE, #2CE2AF, #2370E6)',
cardBgColor: '#1f1f1f',
borderColor: '#434343',
menuTextColor: 'rgba(255, 255, 255, 0.85)',
menuActiveColor: '#61F7EE'
}
];

@ -0,0 +1,62 @@
:root {
--primary-color: #0bd7c6;
--secondary-color: #0033f7;
--background-color: transparent;
--text-color: #333333;
--gradient-color: linear-gradient(to right, #0bd7c6, #0033f7);
--card-bg-color: #ffffff;
--border-color: #e5e6eb;
--menu-text-color: #1d2129;
--menu-active-color: #0033f7;
}
$el-button-bg-color: #0bd7c6;
$base-container-width: 1420px;
// 使用CSS变量
.gradient {
background: var(--gradient-color);
}
.text-primary {
color: var(--primary-color);
}
.text-secondary {
color: var(--secondary-color);
}
.bg-primary {
background-color: var(--primary-color);
}
.bg-secondary {
background-color: var(--secondary-color);
}
// 暗黑主题适配
body {
background-color: var(--background-color);
color: var(--text-color);
transition: all 0.3s;
}
.el-menu {
--el-menu-bg-color: var(--card-bg-color) !important;
--el-menu-text-color: var(--menu-text-color) !important;
--el-menu-hover-text-color: var(--menu-active-color) !important;
--el-menu-active-color: var(--menu-active-color) !important;
border-color: var(--border-color) !important;
}
.el-card {
--el-card-bg-color: var(--card-bg-color) !important;
--el-card-border-color: var(--border-color) !important;
}
.el-button {
--el-button-bg-color: var($el-button-bg-color) !important;
--el-button-border-color: var(--border-color) !important;
--el-button-hover-border-color: var(--primary-color) !important;
--el-button-hover-bg-color: var(--primary-color) !important;
}

@ -3,6 +3,7 @@ import axios from 'axios'
import pinia from '@/store'
import userStore from '@/store/module/user'
import router from '@/router/index'
// 创建axios实例
const server = axios.create({
baseURL: import.meta.env.VITE_APP_BASE_API,
@ -12,6 +13,7 @@ const server = axios.create({
server.interceptors.request.use((config) => {
const useuserStore = userStore(pinia)
console.log(useuserStore.token,'1212');
config.headers.Authorization = useuserStore.token
config.headers['x-access-token'] = useuserStore.token
@ -23,6 +25,14 @@ server.interceptors.response.use((response) => {
return Promise.reject(response)
}
return response.data
}, (error) => {
console.log(error.request.status,'error');
if(error.request.status === 401){
const useuserStore = userStore(pinia)
useuserStore.layOut()
router.push('/login')
}
return Promise.reject(error)
})
// 暴露axios实例

File diff suppressed because it is too large Load Diff

@ -0,0 +1,84 @@
<template>
<div class="container">
<div class="item" v-for="item in 10">
<div class="new-iamge">
<img src="../../assets/images/news.png" alt="" v-default-image />
</div>
<div class="new-title">上海一患者在医院停房车维权称车祸花近百万屁股整形遇假专家</div>
<div class="new-time">
<div>2023-08-01</div>
<div>新闻</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, nextTick, watch, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
const total = ref(0)
</script>
<style scoped lang="scss">
.container {
width: 1420px;
margin: 0 auto;
padding-top: 100px;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(2, 1fr);
gap: 20px;
.item {
width: 320px;
height: 260px;
background-color: var(--card-bg-color);
margin-right: 20px;
margin-bottom: 20px;
cursor: pointer;
transition: all 0.3s;
border-radius: 5px;
box-shadow: 1px 1px 10px rgba(0, 0, 0, 0.2);
overflow: hidden;
&:hover {
transform: translateY(-5px);
}
.new-iamge{
width: 100%;
height: 175px;
img{
width: 100%;
height: 100%;
}
}
.new-title{
width: 100%;
height: 50px;
padding: 0 10px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
font-size: 16px;
font-weight: 700;
margin-top: 5px;
line-height: 25px;
}
.new-time{
width: 100%;
height: 25px;
padding: 0 10px;
display: flex;
justify-content: space-between;
font-size: 14px;
margin-top: 5px;
font-size: 12px;
color: #999;
}
}
}
</style>

@ -67,38 +67,41 @@ const setImageUrl = (url: string) => {
margin-top: 100px;
.news-list {
width: 100%;
// height: 900px;
// background-color: #f2f3f5;
padding: 15px;
border: 1px solid #f2f3f5;
border: 1px solid var(--border-color);
background-color: var(--card-bg-color);
border-radius: 5px;
.item {
.news-title {
font-size: 24px;
font-weight: 700;
color: var(--text-color);
}
.children {
margin: 20px 0;
.son-item {
width: 100%;
height: 100px;
background-color: #fff;
background-color: var(--card-bg-color);
padding: 15px;
display: flex;
border-bottom: 1px solid rgba(228, 230, 235, 0.5);
border-bottom: 1px solid var(--border-color);
justify-content: space-between;
cursor: pointer;
transition: all 0.3s;
.left {
width: 1000px;
.title {
font-size: 18px;
font-weight: 700;
color: #4f5153;
color: var(--text-color);
transition: color 0.3s;
}
.content {
margin-top: 8px;
font-size: 13px;
color: #8a919f;
color: var(--text-color);
opacity: 0.65;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
@ -107,7 +110,8 @@ const setImageUrl = (url: string) => {
.time {
margin-top: 8px;
font-size: 12px;
color: #8a919f;
color: var(--text-color);
opacity: 0.45;
display: flex;
}
}
@ -119,10 +123,15 @@ const setImageUrl = (url: string) => {
img {
width: 100%;
height: 100%;
border-radius: 4px;
border: 1px solid var(--border-color);
}
}
&:hover {
background-color: #f7f8fa;
background-color: var(--background-color);
.title {
color: var(--primary-color);
}
}
}
}
@ -135,27 +144,29 @@ const setImageUrl = (url: string) => {
top: 100px;
z-index: 999;
width: 150px;
// height: 300px;
background-color: #f2f3f5;
background-color: var(--card-bg-color);
border: 1px solid var(--border-color);
padding: 10px;
border-radius: 5px;
.item {
height: 45px;
// text-align: center;
line-height: 22px;
font-size: 16px;
padding: 10px;
border-radius: 5px;
cursor: pointer;
margin: 5px 0;
color: var(--text-color);
transition: all 0.3s;
&:hover {
background-color: #0bd7c628;
color: #0bd7c6;
background-color: var(--primary-color);
color: #ffffff;
opacity: 0.8;
}
}
.active {
background-color: #0bd7c628;
color: #0bd7c6;
background-color: var(--primary-color);
color: #ffffff;
}
}
</style>

@ -86,7 +86,7 @@ const checked = ref(false)
function handleSub() {
if (!checked.value) {
ElMessage({
message: '请先同意',
message: '请确认您已阅读并同意比赛规则。',
type: 'warning',
})
return

@ -308,9 +308,9 @@ const scrollToPosition = () => {
.top-image {
width: 100%;
height: 300px;
background-color: skyblue;
background: var(--background-color);
text-align: center;
color: #fff;
color: var(--text-color);
font-size: 32px;
font-weight: 700;
line-height: 300px;
@ -319,16 +319,14 @@ const scrollToPosition = () => {
width: 100%;
display: grid;
grid-template-columns: repeat(4, 1fr);
// grid-template-rows: repeat(2, 1fr);
// gap: 10px;
// margin-top: 10px;
.item {
width: 340px;
height: 360px;
// background-color: pink;
background-color: var(--card-bg-color);
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.06);
cursor: pointer;
border-radius: 10px;
border: 1px solid var(--border-color);
transition: all 0.2s;
.image {
width: 100%;
@ -336,19 +334,21 @@ const scrollToPosition = () => {
img {
width: 100%;
height: 100%;
border-radius: 4px;
}
}
.reac-info {
padding: 0 8px;
.reac-title {
margin-top: 19px;
color: #c9c9c9;
color: var(--text-color);
opacity: 0.65;
font-size: 12px;
}
.reac-project {
font-size: 16px;
font-weight: 600;
color: #333333;
color: var(--text-color);
margin-top: 10px;
line-height: 20px;
height: 60px;
@ -359,11 +359,12 @@ const scrollToPosition = () => {
}
.time {
font-size: 14px;
color: #8c8b8b;
color: var(--text-color);
opacity: 0.65;
margin-top: 30px;
}
.niandu {
color: #1e2033;
color: var(--text-color);
font-size: 18px;
margin-top: 20px;
font-weight: 600;
@ -375,6 +376,7 @@ const scrollToPosition = () => {
}
.item:hover {
transform: translateY(-5px);
border-color: var(--primary-color);
}
.item:nth-child(n) {
margin-top: 20px;
@ -391,12 +393,13 @@ const scrollToPosition = () => {
width: 300px;
margin-left: 40px;
.title {
color: #1e2033;
color: var(--text-color);
font-size: 28px;
font-weight: 600;
}
.description {
color: #1e2033;
color: var(--text-color);
opacity: 0.65;
font-size: 14px;
margin-top: 15px;
}
@ -406,8 +409,7 @@ const scrollToPosition = () => {
position: relative;
width: 100%;
height: 140px;
// background-color: pink;
color: #333333;
color: var(--text-color);
padding: 15px;
display: flex;
flex-direction: column;
@ -415,8 +417,13 @@ const scrollToPosition = () => {
box-shadow: 0rem 0rem 0.05208rem rgba(0, 0, 0, 0.06);
margin-top: 10px;
cursor: pointer;
background: var(--card-bg-color);
border: 1px solid var(--border-color);
border-radius: 4px;
transition: all 0.3s;
.year {
font-size: 12px;
opacity: 0.65;
}
.name {
width: 130px;
@ -426,6 +433,7 @@ const scrollToPosition = () => {
}
.time {
font-size: 12px;
opacity: 0.45;
}
.go-to {
position: absolute;
@ -436,9 +444,9 @@ const scrollToPosition = () => {
line-height: 28px;
text-align: center;
font-size: 14px;
color: #f6f5fb;
background: url('../../assets/images/left-top.png') no-repeat;
background-size: contain;
color: #ffffff;
background: var(--primary-color);
border-radius: 0 4px 0 4px;
}
.icon {
position: absolute;
@ -450,6 +458,14 @@ const scrollToPosition = () => {
img {
width: 100%;
height: 100%;
opacity: 0.8;
}
}
&:hover {
transform: translateY(-2px);
border-color: var(--primary-color);
.name {
color: var(--primary-color);
}
}
}
@ -474,12 +490,14 @@ const scrollToPosition = () => {
display: flex;
.label {
font-size: 16px;
color: #aaa;
color: var(--text-color);
opacity: 0.45;
width: 100px;
}
.text {
font-size: 16px;
font-weight: 600;
color: var(--text-color);
}
}
li:first-child {
@ -499,7 +517,8 @@ const scrollToPosition = () => {
margin-top: 25px;
.label {
font-size: 16px;
color: #aaa;
color: var(--text-color);
opacity: 0.45;
}
.deaceiption {
font-size: 16px;
@ -507,6 +526,7 @@ const scrollToPosition = () => {
line-height: 26px;
margin-top: 15px;
height: 300px;
color: var(--text-color);
}
.file {
margin-top: 25px;
@ -519,12 +539,16 @@ const scrollToPosition = () => {
width: 100%;
font-size: 14px;
line-height: 22px;
border: 1px solid #ccc;
border: 1px solid var(--border-color);
background-color: var(--card-bg-color);
padding: 20px;
margin-top: 20px;
color: var(--text-color);
p {
img {
width: 100%;
border-radius: 4px;
border: 1px solid var(--border-color);
}
}
}
@ -532,6 +556,12 @@ const scrollToPosition = () => {
:deep(.el-card) {
width: 100%;
height: 100%;
background-color: var(--card-bg-color);
border-color: var(--border-color);
color: var(--text-color);
.el-card__header {
border-bottom: 1px solid var(--border-color);
}
}
img {
width: 100%;

@ -8,6 +8,8 @@
width="800"
draggable
overflow
:close-on-click-modal="false"
:before-close="closeDialog"
>
<div class="table-box">
<div class="search">
@ -56,7 +58,10 @@
/>
</div>
<div class="dialog-footer">
<el-button @click="$emit('update:modelValue', false)">关闭</el-button>
<!-- <el-button @click="$emit('update:modelValue', false)">关闭</el-button> -->
<el-button
@click="closeDialog"
>关闭</el-button>
<el-button
type="primary"
@click="
@ -64,8 +69,9 @@
$emit('update:modelValue', false)
$emit(
'selected',
tableData.find((o) => o.id === selectedRowId) || {},
tableData.find((o) => o.id === selectedRowId),
)
selectedRowId = null
}
"
>
@ -95,6 +101,12 @@ watch(
const tableData = reactive<any[]>([])
const selectedRowId = ref()
//
const closeDialog = ()=>{
$emit('update:modelValue', false)
$emit('selected', {});
selectedRowId.value = null
}
//
const total = ref(0)

@ -1,32 +1,14 @@
<template>
<div>
<el-button
type="primary"
icon="Plus"
@click="add"
class="btn"
:disabled="isDisable"
>
<el-button type="primary" icon="Plus" @click="add" class="btn" :disabled="isDisable">
新增
</el-button>
<el-button
type="danger"
icon="Delete"
@click="del"
class="btn"
:disabled="isDisable"
>
<el-button type="danger" icon="Delete" @click="del" class="btn" :disabled="isDisable">
删除
</el-button>
<div class="table-box">
<el-table
ref="multipleTableRef"
@select="(selection: any[]) => (isSele = !!selection.length)"
border
:data="tableData"
class="table"
height="276px"
>
<el-table ref="multipleTableRef" @select="(selection: any[]) => (isSele = !!selection.length)" border
:data="tableData" class="table" height="276px">
<el-table-column type="selection" width="55" />
<el-table-column label="#" width="55">
<template #default="{ $index }">
@ -41,13 +23,7 @@
<span style="margin-left: 10px">用户</span>
</template>
<template #default="{ row }">
<el-input
:disabled="isDisable"
@click="openDialog(row)"
v-model="row.realname"
placeholder="请选择"
:prefix-icon="ClusterOutlined"
/>
<el-input v-model="row.realname" :disabled="true" />
</template>
</el-table-column>
<el-table-column>
@ -58,12 +34,17 @@
<span style="margin-left: 10px">是否队长</span>
</template>
<template #default="{ row }">
<el-cascader
:modelValue="row.captain"
@update:modelValue="(arr: any[]) => (row.captain = arr[0])"
:options="options"
:disabled="isDisable"
/>
<el-select v-model="row.captain" @update:modelValue="(arr: any[]) => {row.captain = arr[0];console.log(arr);
}"
@change="()=>checkUniqueness(row)"
:options="options">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-table-column>
<el-table-column>
@ -74,7 +55,7 @@
<span style="margin-left: 10px">学号</span>
</template>
<template #default="{ row }">
<el-input v-model="row.workNo" :disabled="isDisable" />
<el-input v-model="row.workNo" :disabled="true" />
</template>
</el-table-column>
<el-table-column>
@ -85,7 +66,7 @@
<span style="margin-left: 10px">手机号</span>
</template>
<template #default="{ row }">
<el-input v-model="row.phone" :disabled="isDisable" />
<el-input v-model="row.phone" :disabled="true" />
</template>
</el-table-column>
<el-table-column>
@ -96,7 +77,7 @@
<span style="margin-left: 10px">邮箱</span>
</template>
<template #default="{ row }">
<el-input v-model="row.email" :disabled="isDisable" />
<el-input v-model="row.email" :disabled="true" />
</template>
</el-table-column>
<el-table-column>
@ -107,7 +88,7 @@
<span style="margin-left: 10px">队员序号</span>
</template>
<template #default="{ row }">
<el-input v-model="row.teamSeq" :disabled="isDisable" />
<el-input v-model="row.teamSeq" :disabled="true" />
</template>
</el-table-column>
</el-table>
@ -117,7 +98,7 @@
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted, watch } from 'vue'
import { reactive, ref, onMounted, nextTick } from 'vue'
import stuDialog from './stuDialog.vue'
import { ClusterOutlined } from '@ant-design/icons-vue'
import { ElMessage } from 'element-plus'
@ -126,6 +107,7 @@ import { getTeamList } from '@/api/oldRace'
import { useRoute } from 'vue-router'
const route = useRoute()
const userModel = userStore()
const visible = ref(false)
//
const isDisable = ref(false)
isDisable.value = route.query.info as any
@ -139,7 +121,27 @@ const options = [
label: '否',
},
]
//
const checkUniqueness = (row:any) => {
// console.log(row);
//tableData
const count = tableData.filter(item => item.captain === '1').length
// console.log(count,'count');
//
if(count === 2){
//
ElMessage({
message: '已有队长人选!',
type: 'error',
})
row.captain = '0';
}else if(count === 0){
ElMessage({
message: '请选择队长人选!',
type: 'error',
})
}
}
//
const tableData = reactive<any[]>([])
onMounted(() => {
@ -167,15 +169,7 @@ onMounted(() => {
})
}, 500)
})
// watch(()=>userModel.userInfo,()=>{
// if(tableData.length === 1) return
// tableData.push({
// userId: userModel.userInfo.id,
// realname: userModel.userInfo.realname,
// captain: '1',
// teamSeq: 1,
// })
// })
const add = () => {
const length = tableData.push({
realname: '', //
@ -193,21 +187,24 @@ const add = () => {
const target = ref<any>()
const openDialog = (row: any) => {
// console.log(row,'row');
visible.value = true
target.value = row
}
const visible = ref(false)
//
const handleSelected = (row: any = {}) => {
// tableData
if (Object.keys(row).length === 0) {
if (tableData.length > 0) {
tableData.pop(); //
}
}
if (tableData.some((o) => o.userId === row.id)) {
ElMessage({
message: '用户不能多选!',
message: '已有该用户,不能重复选择用户!',
type: 'error',
})
return
tableData.pop(); //
}
console.log(row, 'aqq')
target.value.workNo = row.work_no

@ -9,6 +9,8 @@
width="1000"
draggable
overflow
:close-on-click-modal="false"
:before-close="closeDialog"
>
<div class="table-box">
@ -53,7 +55,7 @@
<template #footer>
<div class="dialog-footer">
<el-button @click="$emit('update:modelValue', false)">关闭</el-button>
<el-button @click="closeDialog">关闭</el-button>
<el-button
type="primary"
@click="
@ -62,7 +64,8 @@
$emit(
'selected',
tableData.find((o) => o.user_id === selectedRowId) || {},
)
);
selectedRowId = null; // selectedRowId
}
"
>
@ -91,6 +94,12 @@ watch(
//
const tableData = reactive<any[]>([])
const selectedRowId = ref()
//
const closeDialog = ()=>{
$emit('update:modelValue', false)
$emit('selected', {});
selectedRowId.value = null
}
//
const total = ref(0)

@ -50,13 +50,7 @@
<span style="margin-left: 10px">指导老师姓名</span>
</template>
<template #default="{ row }">
<el-input
:disabled="isDisable"
@click="openDialog(row)"
v-model="row.teacherName"
placeholder="请选择"
:prefix-icon="ClusterOutlined"
/>
<el-input v-model="row.teacherName" placeholder="请输入指导老师姓名" :disabled="isDisable"/>
</template>
</el-table-column>
<el-table-column>
@ -103,7 +97,7 @@
<el-input v-model="row.teacherYjfx" placeholder="请输入研究方向" :disabled="isDisable"/>
</template>
</el-table-column>
<el-table-column>
<el-table-column >
<template #header>
<el-icon>
<Edit />
@ -111,7 +105,7 @@
<span style="margin-left: 10px">手机号</span>
</template>
<template #default="{ row }">
<el-input v-model="row.teacherPhone" placeholder="请输入手机号" :disabled="isDisable"/>
<el-input v-model="row.teacherPhone" @blur="validatePhoneInput(row)" placeholder="请输入手机号" :disabled="isDisable"/>
</template>
</el-table-column>
</el-table>
@ -143,6 +137,13 @@ const options = [
},
]
//
const validatePhone = (teacherPhone: string) => {
const pattern = /^1[3-9]\d{9}$/;
return pattern.test(teacherPhone);
};
//
const tableData = reactive<any[]>([])
onMounted(async() => {
@ -187,13 +188,24 @@ const visible = ref(false)
//
const handleSelected = (row: any = {}) => {
console.log(row,'row');
// tableData
if (Object.keys(row).length === 0) {
console.log(Object)
if (tableData.length > 0) {
tableData.pop(); //
}
}
if (tableData.some((o) => o.teacherid === row.user_id)) {
ElMessage({
message: '用户不能多选!',
message: '已有该用户,不能重复选择用户!',
type: 'error',
})
return
tableData.pop(); //
}
console.log(row,'row')
target.value.teacherName = row.realname
target.value.teacherXl = row.exp_title
target.value.teacherZc = row.exp_zc
@ -201,6 +213,7 @@ const handleSelected = (row: any = {}) => {
target.value.teacherYjfx = row.exp_yjfx
target.value.teacherPhone = row.phone
target.value.teacherid = row.user_id
}
//

@ -44,31 +44,6 @@
</div>
</div>
</el-card>
<!-- 项目信息 -->
<el-card class="com">
<div class="title">比赛项目信息</div>
<div class="content track">
<div class="card-annual padding">
<p>{{ ndbsXm.objName }}</p>
</div>
<div class="right">
<div class="info-box">
<div class="name">项目名称</div>
<div class="title">{{ ndbsXm.objName }}</div>
<div class="name">要求人数</div>
<div class="title">{{ ndbsXm.workCount }}</div>
<div class="date-box">
<div class="label">开始报名时间</div>
<div class="date">{{ ndbsXm.starttime?.split(' ')[0] }}</div>
</div>
<div class="date-box">
<div class="label">开始截至时间</div>
<div class="date">{{ ndbsXm.endtime?.split(' ')[0] }}</div>
</div>
</div>
</div>
</div>
</el-card>
</div>
<el-card class="center">
<div class="personage-info">
@ -122,6 +97,16 @@
<el-form-item label="队伍名称" prop="teamName">
<el-input v-model="ruleForm.teamName" maxlength="30" type="text" :disabled="isDisable"/>
</el-form-item>
<!-- <el-form-item label="选择题目" prop="topicid" v-show="false">
<el-select v-model="ruleForm.topicid" placeholder="请选择题目" :disabled="isDisable">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>-->
</el-form>
</div>
@ -140,9 +125,10 @@
</div>
</el-card>
<div class="bottom">
<el-button class="btn" @click="$router.back()">{{ isDisable ? '返回' : isEdit ? '取消修改' : '取消报名' }}</el-button>
<el-button class="btn cyan" @click="submit" :loading="loading" v-if=!isDisable>
{{ isEdit ? '确认修改' : '确认报名' }}
<el-button class="btn" @click="$router.back()">{{ isDisable ? '返回' : isEdit ? '取消修改' : '返回' }}</el-button>
<el-button class="btn temp" @click="submit('2')" v-if="!isDisable">暂存信息</el-button>
<el-button class="btn cyan" :loading="loading" @click="submit('1')" v-if="!isDisable">
{{ isEdit ? '确认修改' : '确认报名' }}
</el-button>
</div>
</div>
@ -157,7 +143,7 @@ import { ElMessage } from 'element-plus'
import { getSignUpApi } from '@/api/person'
import stuList from './components/stuList.vue'
import teaList from './components/teaList.vue'
import { getNdbswxqList, getComppxqList } from '@/api/person'
import { getNdbswxqList } from '@/api/person'
import { getOldRaceList,getOldRaceInfo } from '@/api/oldRace'
import { getTopicList } from '@/api/race'
const user = userStore()
@ -177,9 +163,8 @@ function pasSex(num: number) {
else return '保密'
}
//
//
const ndbs = ref<any>({})
const ndbsXm = ref<any>({})
console.log(route.query.edit, 'route.query.edit')
const options = ref([])
@ -187,11 +172,12 @@ if (route.query.edit) {
const getOldRaceListEvent = async () => {
const res: any = await getOldRaceList({ id: route.query.id})
ndbs.value = res.result.annualComp
ndbsXm.value = res.result.annualCompPoint
}
const getOldRaceInfoEvent = async () => {
const res: any = await getOldRaceInfo({ id: route.query.id})
// ruleForm.annualCompid = route.query.annualCompid
ruleForm.teamName = res.result.teamName
ruleForm.topicid = res.result.topicObj ? res.result.topicObj.id : ''
ruleForm.objName = res.result.annualCompPointName
options.value = res.result.topicList.map((item) => {
return {
@ -209,26 +195,23 @@ if (route.query.edit) {
getNdbswxqList(route.query.bcId as string).then((res: any) => {
if (res.result) ndbs.value = res.result
})
getComppxqList(route.query.id as string).then((res: any) => {
//console.log(res.result, 'xm')
if (res.result) ndbsXm.value = res.result
})
/*const getTopicListApi = async () => {
const res: any = await getTopicList({ annualCompid: route.query.id })
nextTick(() => {
if (res.result.length != 0) {
ruleForm.topicid = res.result[0].id
}
})
options.value = res.result.map((item) => {
return {
value: item.id,
label: item.name,
}
})
}
getTopicListApi()*/
// const getTopicListApi = async () => {
// const res: any = await getTopicList({ annualCompid: route.query.id })
// console.log(res)
// nextTick(() => {
// if (res.result.length != 0) {
// ruleForm.topicid = res.result[0].id
// }
// })
// options.value = res.result.map((item) => {
// return {
// value: item.id,
// label: item.name,
// }
// })
// }
// getTopicListApi()
}
// members: adviser:
@ -253,23 +236,38 @@ const stuRef = ref<any>(null)
const teaRef = ref<any>(null)
const loading = ref(false)
const submit = () => {
const submit = (substa:string) => {
if (!ruleForm.teamName) return ElMessage.warning('请输入队伍名称')
ruleForm.instructorSheetList = [...teaRef.value.submit()]
ruleForm.teamManagementList = [...stuRef.value.submit()]
loading.value = true
console.log(ruleForm.instructorSheetList, 'ruleForm.instructorSheetList');
console.log( ruleForm.teamManagementList,' ruleForm.teamManagementList');
if(ruleForm.teamManagementList.every((member:any) => member.captain == "0")){
ElMessage.warning('请选择队长')
return
}
ruleForm.substa = substa
ruleForm.id = route.query.id
// ruleForm.annualCompid = route.query.id
if(route.query.edit){
ruleForm.enrollCode = route.query.enrollCode
ruleForm.id = route.query.annualCompid
}
// ruleForm.substa = "1"
getSignUpApi(ruleForm)
.then((res: any) => {
if(substa == '1'){
loading.value = true
ElMessage({
message: isEdit.value ? '修改成功' : '报名成功',
type: 'success',
})
}else{
ElMessage({
message: res?.message || '报名成功',
message: '暂存成功',
type: 'success',
})
}
router.push('/user-info')
})
.catch((err) => {
@ -377,7 +375,7 @@ const submit = () => {
height: 300px;
.com {
width: 685px;
width: 100%;
height: 300px;
border-radius: 6px 6px 6px 6px;
padding-top: 22px;
@ -395,7 +393,6 @@ const submit = () => {
margin-bottom: 18px;
}
margin-right: 22px;
.content {
display: flex;
@ -445,7 +442,7 @@ const submit = () => {
.right {
.info-box {
width: 210px;
width: 100%;
.name {
height: 20px;
font-family:

@ -46,31 +46,6 @@
</div>
</div>
</el-card>
<!-- 项目信息 -->
<el-card class="com">
<div class="title">比赛项目信息</div>
<div class="content track">
<div class="card-annual padding">
<p>{{ ndbsXm.objName }}</p>
</div>
<div class="right">
<div class="info-box">
<div class="name">项目名称</div>
<div class="title">{{ ndbsXm.objName }}</div>
<div class="name">要求人数</div>
<div class="title">{{ ndbsXm.workCount }}</div>
<div class="date-box">
<div class="label">开始报名时间</div>
<div class="date">{{ ndbsXm.starttime?.split(' ')[0] }}</div>
</div>
<div class="date-box">
<div class="label">开始截至时间</div>
<div class="date">{{ ndbsXm.endtime?.split(' ')[0] }}</div>
</div>
</div>
</div>
</div>
</el-card>
</div>
<el-card>
<div>
@ -82,7 +57,6 @@
<el-form-item label="参赛形式">
<el-input v-model="ruleForm.entryFormat" type="text" disabled />
</el-form-item>
</el-form>
</div>
</el-card>
@ -153,7 +127,7 @@
<div class="bottom">
<el-button class="btn" @click="() => router.back()">
{{ isDisable ? '返回' : isEdit ? '取消修改' : '取消报名' }}
{{ isDisable ? '返回' : isEdit ? '取消修改' : '返回' }}
</el-button>
<el-button class="btn temp" @click="submit('2')" v-if="!isDisable">暂存信息</el-button>
<el-button class="btn cyan" :loading="subLoading" @click="submit('1')" v-if="!isDisable">
@ -176,7 +150,7 @@
</template>
<template #tip>
<div class="el-upload__tip text-red">作品只允许上传一个,格式为{{ndbsXm.uploadWorksType}}</div>
<div class="el-upload__tip text-red">作品只允许上传一个,格式为{{ndbs.uploadWorksType}}</div>
</template>
</el-upload>
@ -235,8 +209,6 @@ const annualCompid = ref('')
const raceName = ref<any>('')
const uploadZp = (id: any) => {
console.log(id)
annualCompid.value = id
dialogVisible.value = true
}
@ -281,9 +253,8 @@ const submitWork = async () => {
//
//
const ndbs = ref<any>({})
const ndbsXm = ref<any>({})
const subLoading = ref(false)
async function submit(substa:string) {
@ -293,21 +264,21 @@ async function submit(substa:string) {
upData.value.workName = WorkName.value
upData.value.files = fileUrl.value
upData.value.substa = substa
// if (!upData.value.teamName) {
// ElMessage({
// message: '',
// type: 'warning',
// })
// return
// }
try {
subLoading.value = true
const res: any = await getSignUpApi({ ...upData.value })
console.log(res, 999999999)
ElMessage({
message: res?.message || res?.result || '报名成功',
type: 'success',
})
if(substa == '1'){
subLoading.value = true
ElMessage({
message: isEdit.value ? '修改成功' : '报名成功',
type: 'success',
})
}else{
ElMessage({
message: '暂存成功',
type: 'success',
})
}
router.push('/user-info')
} catch (error) {
ElMessage({
@ -337,22 +308,13 @@ if (route.query.edit) {
const getOldRaceListEvent = async () => {
const res: any = await getOldRaceList({ id: route.query.id })
ndbs.value = res.result.annualComp
ndbsXm.value = res.result.annualCompPoint
}
const getOldRaceInfoEvent = async () => {
const res: any = await getOldRaceInfo({ id: route.query.id })
ruleForm.annualCompid = route.query.annualCompid
ruleForm.teamName = res.result.teamName
ruleForm.topicid = res.result.topicObj ? res.result.topicObj.id : ''
ruleForm.objName = res.result.annualCompPointName
ruleForm.requireUploadWorks = res.result.requireUploadWorks
WorkName.value = res.result.uploadFile.topicName
options.value = res.result.topicList.map((item) => {
return {
value: item.id,
label: item.name,
}
})
ruleForm.objName = res.result.annualCompPointName
}
getOldRaceListEvent()
@ -361,14 +323,10 @@ if (route.query.edit) {
getNdbswxqList(route.query.bcId as string).then((res: any) => {
if (res.result) ndbs.value = res.result
})
getComppxqList(route.query.id as string).then((res: any) => {
if (res.result) ndbsXm.value = res.result
})
}
/*const getTopicListApi = async () => {
const res: any = await getTopicList({ annualCompid: route.query.id })
console.log(res)
nextTick(() => {
if (res.result.length != 0) {
ruleForm.topicid = res.result[0].id
@ -459,7 +417,7 @@ getTopicListApi()*/
height: 300px;
.com {
width: 685px;
width: 100%;
height: 300px;
border-radius: 6px 6px 6px 6px;
padding-top: 22px;
@ -477,7 +435,6 @@ getTopicListApi()*/
margin-bottom: 18px;
}
margin-right: 22px;
.content {
display: flex;
@ -528,7 +485,7 @@ getTopicListApi()*/
.right {
.info-box {
width: 210px;
width: 100%;
.name {
height: 20px;

@ -105,7 +105,7 @@
width="35%"
:before-close="handleClose"
>
<el-form :model="form" label-width="80" style="padding-right: 30px">
<el-form :model="form":rules="rules" ref="ruleFormRef" label-width="80" style="padding-right: 30px">
<el-form-item label="头像">
<el-upload
v-model:file-list="fileList"
@ -119,7 +119,7 @@
<el-form-item label="姓名">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="学号">
<el-form-item label="学号" prop="workno">
<el-input v-model="form.workNo" />
</el-form-item>
<!-- <el-form-item label="部门">
@ -143,10 +143,10 @@
<el-radio :value="0" size="large"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="邮箱">
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" />
</el-form-item>
<el-form-item label="手机号">
<el-form-item label="手机号" prop="phone">
<el-input v-model="form.phone" type="number" />
</el-form-item>
</el-form>
@ -161,6 +161,7 @@
<script lang="ts" setup>
import { nextTick, onMounted, reactive, ref, toRefs, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { useRouter } from 'vue-router'
import userStore from '@/store/module/user'
import { getFaculties, uploadFile, editUserInfoApi } from '@/api/race'
@ -172,6 +173,25 @@ console.log(useUserStore.userInfo, 'useUserStore')
userInfo.value = useUserStore.userInfo
const Router = useRouter()
const dialogVisible = ref(false)
const ruleFormRef = ref<any>()
const rules = {
workno: [
// { required: true, message: '/', trigger: 'blur' },
{
pattern: /^[a-zA-Z0-9]{1,20}$/,
message: '工号/学号为1-20位数字或字母',
trigger: 'blur',
},
],
phone: [
// { required: true, message: '', trigger: 'blur' },
{ pattern: /^1[3-9]\d{9}$/, message: '手机号格式不正确', trigger: 'blur' },
],
email: [
// { required: true, message: '', trigger: 'blur' },
{ type: 'email', message: '请输入有效的邮箱地址', trigger: ['blur'] }
],
}
//
const editUserInfo = () => {
form.name = useUserStore.userInfo.realname
@ -215,30 +235,44 @@ const uploadFileEvent = async () => {
}
//
const submit = async () => {
if (fileList.value[0].hasOwnProperty('raw')) {
await uploadFileEvent()
}
const data: any = {
id: userInfo.value.id,
realname: form.name,
birthday: form.birthday,
sex: form.sex,
email: form.email,
facultiesId: form.facultiesId,
phone: form.phone,
avatar: avatar.value,
workNo: form.workNo
}
for (const key in data) {
if (data[key] === '') {
delete data[key]
//
if (!ruleFormRef.value) return
await ruleFormRef.value.validate(async (valid: boolean) => {
if (valid) {
//
if (fileList.value[0].hasOwnProperty('raw')) {
await uploadFileEvent()
}
const data: any = {
id: userInfo.value.id,
realname: form.name,
birthday: form.birthday,
sex: form.sex,
email: form.email,
facultiesId: form.facultiesId,
phone: form.phone,
avatar: avatar.value,
workNo: form.workNo
}
for (const key in data) {
if (data[key] === '') {
delete data[key]
}
}
await editUserInfoApi(data).then((res: any) => {
console.log(res.code);
if(res.code != 200){
return ElMessage.error(res.message)
}
})
useUserStore.getUserInfo()
userInfo.value = useUserStore.userInfo
dialogVisible.value = false
} else {
//
ElMessage.error('表单信息填写有误,请检查后再试')
}
}
await editUserInfoApi(data)
useUserStore.getUserInfo()
userInfo.value = useUserStore.userInfo
dialogVisible.value = false
})
}
onMounted(() => {})
//

Loading…
Cancel
Save