mirror of
				https://github.com/continew-org/continew-admin-ui.git
				synced 2025-10-31 00:57:11 +08:00 
			
		
		
		
	refactor: 重构工作台
This commit is contained in:
		| @@ -1,5 +1,5 @@ | ||||
| <template> | ||||
|   <a-layout class="layout layout-default"> | ||||
|   <a-layout class="layout layout-default" :class="{ mobile: isMobile }"> | ||||
|     <Asider></Asider> | ||||
|     <a-layout class="layout-default-right"> | ||||
|       <Header></Header> | ||||
| @@ -17,9 +17,11 @@ import Main from './components/Main.vue' | ||||
| import Tabs from './components/Tabs/index.vue' | ||||
| import GiFooter from '@/components/GiFooter/index.vue' | ||||
| import { useAppStore } from '@/stores' | ||||
| import { useDevice } from '@/hooks' | ||||
|  | ||||
| defineOptions({ name: 'LayoutDefault' }) | ||||
| const appStore = useAppStore() | ||||
| const { isMobile } = useDevice() | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
|   | ||||
| @@ -1,219 +0,0 @@ | ||||
| <template> | ||||
|   <a-spin :loading="loading" style="width: 100%"> | ||||
|     <a-card title="访问趋势" :bordered="false" class="gi_card_title"> | ||||
|       <template #extra> | ||||
|         <a-radio-group v-model:model-value="dateRange" type="button" size="small" @change="onChange"> | ||||
|           <a-radio :value="7">近7天</a-radio> | ||||
|           <a-radio :value="30">近30天</a-radio> | ||||
|         </a-radio-group> | ||||
|       </template> | ||||
|       <VCharts :option="chartOption" autoresize :style="{ height: '326px' }"></VCharts> | ||||
|     </a-card> | ||||
|   </a-spin> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import VCharts from 'vue-echarts' | ||||
| import { graphic } from 'echarts' | ||||
| import { type DashboardAccessTrendResp, getDashboardAccessTrend as getData } from '@/apis' | ||||
| import { useChart } from '@/hooks' | ||||
|  | ||||
| // 提示框 | ||||
| const tooltipItemsHtmlString = (items) => { | ||||
|   return items | ||||
|     .map( | ||||
|       (el) => `<div class="content-panel"> | ||||
|         <p> | ||||
|           <span style="background-color: ${el.color}" class="tooltip-item-icon"></span> | ||||
|           <span>${el.seriesName}</span> | ||||
|         </p> | ||||
|         <span class="tooltip-value"> | ||||
|         ${el.value} | ||||
|         </span> | ||||
|       </div>` | ||||
|     ) | ||||
|     .join('') | ||||
| } | ||||
|  | ||||
| const xData = ref<string[]>([]) | ||||
| const pvStatisticsData = ref<number[]>([]) | ||||
| const ipStatisticsData = ref<number[]>([]) | ||||
| const { chartOption } = useChart((isDark) => { | ||||
|   return { | ||||
|     grid: { | ||||
|       left: '38', | ||||
|       right: '0', | ||||
|       top: '10', | ||||
|       bottom: '50' | ||||
|     }, | ||||
|     legend: { | ||||
|       bottom: -3, | ||||
|       icon: 'circle', | ||||
|       textStyle: { | ||||
|         color: '#4E5969' | ||||
|       } | ||||
|     }, | ||||
|     xAxis: { | ||||
|       type: 'category', | ||||
|       offset: 2, | ||||
|       data: xData.value, | ||||
|       boundaryGap: false, | ||||
|       axisLabel: { | ||||
|         color: '#4E5969', | ||||
|         formatter(value: number, idx: number) { | ||||
|           if (idx === 0) return '' | ||||
|           if (idx === xData.value.length - 1) return '' | ||||
|           return `${value}` | ||||
|         } | ||||
|       }, | ||||
|       axisLine: { | ||||
|         show: false | ||||
|       }, | ||||
|       axisTick: { | ||||
|         show: false | ||||
|       }, | ||||
|       splitLine: { | ||||
|         show: true, | ||||
|         interval: (idx: number) => { | ||||
|           if (idx === 0) return false | ||||
|           return idx !== xData.value.length - 1 | ||||
|         }, | ||||
|         lineStyle: { | ||||
|           color: isDark ? '#3F3F3F' : '#E5E8EF' | ||||
|         } | ||||
|       }, | ||||
|       axisPointer: { | ||||
|         show: true, | ||||
|         lineStyle: { | ||||
|           color: '#23ADFF', | ||||
|           width: 2 | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     yAxis: { | ||||
|       type: 'value', | ||||
|       axisLabel: { | ||||
|         formatter(value: any, idx: number) { | ||||
|           if (idx === 0) return value | ||||
|           if (value >= 1000) { | ||||
|             return `${value / 1000}k` | ||||
|           } | ||||
|           return `${value}` | ||||
|         } | ||||
|       }, | ||||
|       axisLine: { | ||||
|         show: false | ||||
|       }, | ||||
|       splitLine: { | ||||
|         lineStyle: { | ||||
|           type: 'dashed', | ||||
|           color: isDark ? '#3F3F3F' : '#E5E8EF' | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     tooltip: { | ||||
|       show: true, | ||||
|       trigger: 'axis', | ||||
|       formatter(params) { | ||||
|         const [firstElement] = params | ||||
|         return `<div> | ||||
|             <p class="tooltip-title">${firstElement.axisValueLabel}</p> | ||||
|             ${tooltipItemsHtmlString(params)} | ||||
|           </div>` | ||||
|       }, | ||||
|       className: 'echarts-tooltip-diy' | ||||
|     }, | ||||
|     series: [ | ||||
|       { | ||||
|         name: '浏览量(PV)', | ||||
|         data: pvStatisticsData.value, | ||||
|         type: 'line', | ||||
|         smooth: true, | ||||
|         showSymbol: false, | ||||
|         color: '#246EFF', | ||||
|         symbol: 'circle', | ||||
|         symbolSize: 10, | ||||
|         emphasis: { | ||||
|           focus: 'series', | ||||
|           itemStyle: { | ||||
|             borderWidth: 2, | ||||
|             borderColor: '#E0E3FF' | ||||
|           } | ||||
|         }, | ||||
|         areaStyle: { | ||||
|           opacity: 0.8, | ||||
|           color: new graphic.LinearGradient(0, 0, 0, 1, [ | ||||
|             { | ||||
|               offset: 0, | ||||
|               color: 'rgba(17, 126, 255, 0.16)' | ||||
|             }, | ||||
|             { | ||||
|               offset: 1, | ||||
|               color: 'rgba(17, 128, 255, 0)' | ||||
|             } | ||||
|           ]) | ||||
|         } | ||||
|       }, | ||||
|       { | ||||
|         name: 'IP数', | ||||
|         data: ipStatisticsData.value, | ||||
|         type: 'line', | ||||
|         smooth: true, | ||||
|         showSymbol: false, | ||||
|         color: '#00B2FF', | ||||
|         symbol: 'circle', | ||||
|         symbolSize: 10, | ||||
|         emphasis: { | ||||
|           focus: 'series', | ||||
|           itemStyle: { | ||||
|             borderWidth: 2, | ||||
|             borderColor: '#E2F2FF' | ||||
|           } | ||||
|         }, | ||||
|         areaStyle: { | ||||
|           opacity: 0.8, | ||||
|           color: new graphic.LinearGradient(0, 0, 0, 1, [ | ||||
|             { | ||||
|               offset: 0, | ||||
|               color: 'rgba(17, 126, 255, 0.16)' | ||||
|             }, | ||||
|             { | ||||
|               offset: 1, | ||||
|               color: 'rgba(17, 128, 255, 0)' | ||||
|             } | ||||
|           ]) | ||||
|         } | ||||
|       } | ||||
|     ] | ||||
|   } | ||||
| }) | ||||
|  | ||||
| const loading = ref(false) | ||||
| const dateRange = ref(30) | ||||
| // 查询图表数据 | ||||
| const getChartData = async (days: number) => { | ||||
|   try { | ||||
|     loading.value = true | ||||
|     xData.value = [] | ||||
|     pvStatisticsData.value = [] | ||||
|     ipStatisticsData.value = [] | ||||
|     const { data } = await getData(days) | ||||
|     data.forEach((el: DashboardAccessTrendResp) => { | ||||
|       xData.value.push(el.date) | ||||
|       pvStatisticsData.value.push(el.pvCount) | ||||
|       ipStatisticsData.value.push(el.ipCount) | ||||
|     }) | ||||
|   } finally { | ||||
|     loading.value = false | ||||
|   } | ||||
| } | ||||
|  | ||||
| // 切换 | ||||
| const onChange = (days: number) => { | ||||
|   getChartData(days) | ||||
| } | ||||
|  | ||||
| onMounted(() => { | ||||
|   getChartData(30) | ||||
| }) | ||||
| </script> | ||||
							
								
								
									
										33
									
								
								src/views/dashboard/workplace/components/Carousel.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/views/dashboard/workplace/components/Carousel.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| <template> | ||||
|   <a-carousel | ||||
|     indicator-type="slider" | ||||
|     show-arrow="hover" | ||||
|     auto-play | ||||
|     style="width: 100%; height: 150px; border-radius: 4px; overflow: hidden" | ||||
|   > | ||||
|     <a-carousel-item v-for="(image, idx) in images" :key="idx"> | ||||
|       <div> | ||||
|         <a-link | ||||
|           :href="image.url" | ||||
|           target="_blank" | ||||
|           rel="noopener" | ||||
|         > | ||||
|           <img :src="`${image.src}?${new Date().getTime()}`" style="width: 100%" alt="" /> | ||||
|         </a-link> | ||||
|       </div> | ||||
|     </a-carousel-item> | ||||
|   </a-carousel> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| const images = [ | ||||
|   { | ||||
|     src: 'https://continew.top/qrcode-text.png', | ||||
|     url: 'https://continew.top/about/intro.html' | ||||
|   }, | ||||
|   { | ||||
|     src: 'https://continew.top/sponsor.png', | ||||
|     url: 'https://continew.top/sponsor.html' | ||||
|   } | ||||
| ] | ||||
| </script> | ||||
							
								
								
									
										42
									
								
								src/views/dashboard/workplace/components/Docs.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/views/dashboard/workplace/components/Docs.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| <template> | ||||
|   <a-card | ||||
|     class="general-card" | ||||
|     title="帮助文档" | ||||
|     :header-style="{ paddingBottom: 0 }" | ||||
|     :body-style="{ paddingTop: '5px' }" | ||||
|     style="height: 166px" | ||||
|   > | ||||
|     <template #extra> | ||||
|       <a-link href="https://continew.top" target="_blank" rel="noopener">更多</a-link> | ||||
|     </template> | ||||
|     <a-row> | ||||
|       <a-col v-for="link in links" :key="link.text" :span="12"> | ||||
|         <a-link | ||||
|           :href="link.url" | ||||
|           target="_blank" | ||||
|           rel="noopener" | ||||
|         > | ||||
|           {{ link.text }} | ||||
|         </a-link> | ||||
|       </a-col> | ||||
|     </a-row> | ||||
|   </a-card> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| const links = [ | ||||
|   { text: '项目简介', url: 'https://continew.top/admin/intro/what-is.html' }, | ||||
|   { text: '快速开始', url: 'https://continew.top/admin/intro/quick-start.html' }, | ||||
|   { text: '常见问题', url: 'https://continew.top/faq.html' }, | ||||
|   { text: '更新日志', url: 'https://continew.top/admin/other/changelog.html' }, | ||||
|   { text: '贡献指南', url: 'https://continew.top/admin/other/contributing.html' }, | ||||
|   { text: '赞助支持 💖', url: 'https://continew.top/sponsor.html' } | ||||
| ] | ||||
| </script> | ||||
|  | ||||
| <style lang="less" scoped> | ||||
| .arco-card-body .arco-link { | ||||
|   margin: 5px 0; | ||||
|   color: rgb(var(--gray-8)); | ||||
| } | ||||
| </style> | ||||
| @@ -1,77 +0,0 @@ | ||||
| <template> | ||||
|   <a-card title="快捷操作" :bordered="false" size="medium" class="card gi_card_title"> | ||||
|     <a-card-grid v-for="(item, index) in list" :key="item.name" class="card-grid-item" :style="{ width: '33.33%' }"> | ||||
|       <a-card :bordered="false" hoverable> | ||||
|         <a-row justify="center" align="center" :class="`animated-fade-up-${index + 1}`"> | ||||
|           <a-space direction="vertical" align="center" class="wrapper" @click="router.replace({ path: item.path })"> | ||||
|             <component :is="item.icon" :size="30" class="icon"></component> | ||||
|             <a-typography-text class="text">{{ item.name }}</a-typography-text> | ||||
|           </a-space> | ||||
|         </a-row> | ||||
|       </a-card> | ||||
|     </a-card-grid> | ||||
|   </a-card> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| const router = useRouter() | ||||
|  | ||||
| const list = [ | ||||
|   { name: '用户管理', icon: 'icon-user', path: '/system/user' }, | ||||
|   { name: '角色管理', icon: 'icon-user-group', path: '/system/role' }, | ||||
|   { name: '菜单管理', icon: 'icon-menu', path: '/system/menu' }, | ||||
|   { name: '文件管理', icon: 'icon-file', path: '/system/file' }, | ||||
|   { name: '系统配置', icon: 'icon-desktop', path: '/system/config' }, | ||||
|   { name: '系统日志', icon: 'icon-history', path: '/monitor/log' } | ||||
| ] | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .card { | ||||
|   overflow: hidden; | ||||
|   :deep(.arco-card-header) { | ||||
|     border: none; | ||||
|   } | ||||
|   .card-grid-item { | ||||
|     cursor: pointer; | ||||
|   } | ||||
|  | ||||
|   :deep(.text) { | ||||
|     font-size: 12px; | ||||
|     text-align: center; | ||||
|     color: rgb(var(--gray-8)); | ||||
|   } | ||||
|  | ||||
|   :deep(.wrapper) { | ||||
|     margin-bottom: 8px; | ||||
|     text-align: center; | ||||
|     cursor: pointer; | ||||
|  | ||||
|     &:last-child { | ||||
|       .text { | ||||
|         margin-bottom: 0; | ||||
|       } | ||||
|     } | ||||
|     &:hover { | ||||
|       .icon { | ||||
|         color: rgb(var(--arcoblue-6)); | ||||
|       } | ||||
|       .text { | ||||
|         color: rgb(var(--arcoblue-6)); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   :deep(.icon) { | ||||
|     display: inline-block; | ||||
|     width: 32px; | ||||
|     height: 32px; | ||||
|     margin-bottom: 4px; | ||||
|     color: rgb(var(--gray-8)); | ||||
|     line-height: 32px; | ||||
|     font-size: 16px; | ||||
|     text-align: center; | ||||
|     border-radius: 4px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @@ -1,54 +0,0 @@ | ||||
| <template> | ||||
|   <a-card title="公告" :bordered="false" size="medium" class="gi_card_title"> | ||||
|     <template #extra> | ||||
|       <a-link>更多</a-link> | ||||
|     </template> | ||||
|     <a-comment | ||||
|       v-for="(item, index) in list" | ||||
|       :key="index" | ||||
|       align="right" | ||||
|       :class="`animated-fade-up-${index}`" | ||||
|       style="overflow: hidden" | ||||
|     > | ||||
|       <template #content> | ||||
|         <div class="content"> | ||||
|           <a-tag v-if="item.type === 1" color="blue" size="small">通知</a-tag> | ||||
|           <a-tag v-if="item.type === 2" color="orangered" size="small">活动</a-tag> | ||||
|           <a-tag v-if="item.type === 3" color="cyan" size="small">消息</a-tag> | ||||
|           <p>{{ item.content }}</p> | ||||
|         </div> | ||||
|       </template> | ||||
|     </a-comment> | ||||
|   </a-card> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| const list = [ | ||||
|   { type: 1, content: 'v2.4.0 版本发布公告🎉' }, | ||||
|   { type: 1, content: 'v2.3.0 版本发布公告🎉' }, | ||||
|   { type: 1, content: 'v2.2.0 版本发布公告🎉' }, | ||||
|   { type: 2, content: '作者喊你来贡献代码了~' }, | ||||
|   { type: 2, content: '作者喊你来提需求了~' } | ||||
| ] | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| :deep(.arco-comment:not(:first-of-type), .arco-comment-inner-comment) { | ||||
|   margin-top: 10px; | ||||
| } | ||||
| :deep(.arco-comment-content) { | ||||
|   font-size: 14px; | ||||
|   color: var(--color-text-1); | ||||
| } | ||||
| :deep(.arco-comment-datetime) { | ||||
|   color: var(--color-text-4); | ||||
| } | ||||
|  | ||||
| .content { | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   > p { | ||||
|     margin-left: 6px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										89
									
								
								src/views/dashboard/workplace/components/Notice.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/views/dashboard/workplace/components/Notice.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| <template> | ||||
|   <a-card | ||||
|     class="general-card" | ||||
|     title="公告" | ||||
|     :header-style="{ paddingBottom: '0' }" | ||||
|     :body-style="{ padding: '15px 20px 13px 20px' }" | ||||
|   > | ||||
|     <template #extra> | ||||
|       <a-link @click="router.replace({ path: '/system/notice' })">更多</a-link> | ||||
|     </template> | ||||
|     <a-skeleton v-if="loading" :loading="loading" :animation="true"> | ||||
|       <a-skeleton-line :rows="5" /> | ||||
|     </a-skeleton> | ||||
|     <div v-else> | ||||
|       <a-empty v-if="dataList.length === 0">暂无公告</a-empty> | ||||
|       <div v-else> | ||||
|         <div v-for="(item, idx) in dataList" :key="idx" class="item"> | ||||
|           <GiCellTag :value="item.type" :dict="notice_type" /> | ||||
|           <a-link class="item-content" @click="onDetail(item.id)"> | ||||
|             <a-typography-paragraph | ||||
|               :ellipsis="{ | ||||
|                 rows: 1, | ||||
|                 showTooltip: true, | ||||
|                 css: true, | ||||
|               }" | ||||
|             > | ||||
|             {{ item.title }} | ||||
|             </a-typography-paragraph> | ||||
|           </a-link> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   </a-card> | ||||
|  | ||||
|   <NoticeDetailModal ref="NoticeDetailModalRef" /> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import { type DashboardNoticeResp, listDashboardNotice } from '@/apis' | ||||
| import { useDict } from '@/hooks/app' | ||||
| import NoticeDetailModal from '@/views/system/notice/NoticeDetailModal.vue' | ||||
|  | ||||
| const router = useRouter() | ||||
| const { notice_type } = useDict('notice_type') | ||||
|  | ||||
| const dataList = ref<DashboardNoticeResp[]>([]) | ||||
| const loading = ref(false) | ||||
| // 查询列表数据 | ||||
| const getDataList = async () => { | ||||
|   try { | ||||
|     loading.value = true | ||||
|     const res = await listDashboardNotice() | ||||
|     dataList.value = res.data | ||||
|   } finally { | ||||
|     loading.value = false | ||||
|   } | ||||
| } | ||||
|  | ||||
| const NoticeDetailModalRef = ref<InstanceType<typeof NoticeDetailModal>>() | ||||
| // 详情 | ||||
| const onDetail = (id: string) => { | ||||
|   NoticeDetailModalRef.value?.onDetail(id) | ||||
| } | ||||
|  | ||||
| onMounted(() => { | ||||
|   getDataList() | ||||
| }) | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="less"> | ||||
| .item { | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   width: 100%; | ||||
|   height: 24px; | ||||
|   margin-bottom: 4px; | ||||
|   .item-content { | ||||
|     flex: 1; | ||||
|     overflow: hidden; | ||||
|     text-overflow: ellipsis; | ||||
|     white-space: nowrap; | ||||
|     margin-left: 4px; | ||||
|     color: var(--color-text-2); | ||||
|     text-decoration: none; | ||||
|     font-size: 13px; | ||||
|     cursor: pointer; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @@ -1,84 +0,0 @@ | ||||
| <template> | ||||
|   <a-card title="公告" :bordered="false" class="gi_card_title"> | ||||
|     <template #extra> | ||||
|       <a-link href="/system/notice">更多</a-link> | ||||
|     </template> | ||||
|     <a-empty v-if="dataList.length === 0">暂无公告</a-empty> | ||||
|     <a-comment | ||||
|       v-for="(item, index) in dataList" | ||||
|       :key="index" | ||||
|       align="right" | ||||
|       :class="`animated-fade-up-${index}`" | ||||
|       style="overflow: hidden" | ||||
|     > | ||||
|       <template #content> | ||||
|         <a-space> | ||||
|           <GiCellTag :value="item.type" :dict="notice_type" /> | ||||
|           <a-link @click="onDetail(item.id)"> | ||||
|             <a-typography-paragraph | ||||
|               :ellipsis="{ | ||||
|                 rows: 1, | ||||
|                 showTooltip: true, | ||||
|                 css: true, | ||||
|               }" | ||||
|             > | ||||
|               {{ item.title }} | ||||
|             </a-typography-paragraph> | ||||
|           </a-link> | ||||
|         </a-space> | ||||
|       </template> | ||||
|     </a-comment> | ||||
|   </a-card> | ||||
|  | ||||
|   <NoticeDetailModal ref="NoticeDetailModalRef" /> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { type DashboardNoticeResp, listDashboardNotice } from '@/apis' | ||||
| import { useDict } from '@/hooks/app' | ||||
| import NoticeDetailModal from '@/views/system/notice/NoticeDetailModal.vue' | ||||
|  | ||||
| const { notice_type } = useDict('notice_type') | ||||
|  | ||||
| const dataList = ref<DashboardNoticeResp[]>([]) | ||||
| // 查询列表数据 | ||||
| const getDataList = async () => { | ||||
|   const res = await listDashboardNotice() | ||||
|   dataList.value = res.data | ||||
| } | ||||
|  | ||||
| const NoticeDetailModalRef = ref<InstanceType<typeof NoticeDetailModal>>() | ||||
| // 详情 | ||||
| const onDetail = (id: string) => { | ||||
|   NoticeDetailModalRef.value?.onDetail(id) | ||||
| } | ||||
|  | ||||
| onMounted(() => { | ||||
|   getDataList() | ||||
| }) | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| :deep(.arco-comment:not(:first-of-type), .arco-comment-inner-comment) { | ||||
|   margin-top: 10px; | ||||
| } | ||||
| :deep(.arco-comment-content) { | ||||
|   font-size: 14px; | ||||
|   color: var(--color-text-1); | ||||
| } | ||||
| :deep(.arco-comment-datetime) { | ||||
|   color: var(--color-text-4); | ||||
| } | ||||
|  | ||||
| .arco-link { | ||||
|   color: rgb(var(--gray-8)); | ||||
| } | ||||
|  | ||||
| .icon { | ||||
|   margin-right: 3px; | ||||
| } | ||||
|  | ||||
| .update-time-row { | ||||
|   text-align: right; | ||||
| } | ||||
| </style> | ||||
| @@ -1,42 +0,0 @@ | ||||
| <template> | ||||
|   <div v-if="time" class="now-time"> | ||||
|     <p class="now-time__time gi_line_1">{{ time }}</p> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import Dayjs from 'dayjs' | ||||
|  | ||||
| defineOptions({ name: 'NowTime' }) | ||||
| const time = ref('') | ||||
|  | ||||
| // 获取现在时间 | ||||
| const getFormatNowTime = () => { | ||||
|   const weekList = ['日', '一', '二', '三', '四', '五', '六'] | ||||
|   return `${Dayjs(new Date()).format('YYYY年MM月DD日 HH:mm:ss')} 星期${weekList[Dayjs(new Date()).day()]}` | ||||
| } | ||||
|  | ||||
| // 初始化时间 | ||||
| const initTime = () => { | ||||
|   time.value = getFormatNowTime() | ||||
|   setInterval(() => { | ||||
|     time.value = getFormatNowTime() | ||||
|   }, 1000) | ||||
| } | ||||
|  | ||||
| initTime() | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| @import url('@/assets/fonts/font.css'); | ||||
| .now-time { | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   font-size: 14px; | ||||
|   font-family: DINPro-Medium; | ||||
|   color: var(--color-text-1); | ||||
|   &__time { | ||||
|     margin-left: 6px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										157
									
								
								src/views/dashboard/workplace/components/Project.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								src/views/dashboard/workplace/components/Project.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,157 @@ | ||||
| <template> | ||||
|   <a-card class="general-card" title="我的项目"> | ||||
|     <template #extra> | ||||
|       <a-link href="https://github.com/charles7c" target="_blank" rel="noopener">更多</a-link> | ||||
|     </template> | ||||
|     <a-row :gutter="16"> | ||||
|       <a-col | ||||
|         v-for="(item, index) in list" | ||||
|         :key="index" | ||||
|         :xs="12" | ||||
|         :sm="12" | ||||
|         :md="12" | ||||
|         :lg="12" | ||||
|         :xl="8" | ||||
|         :xxl="8" | ||||
|         class="my-project-item" | ||||
|       > | ||||
|         <a-card style="min-height: 204px" :bordered="true" hoverable> | ||||
|           <div class="badge badge-right" :style="`background-color: ${item.statusColor}`">{{ item.status }}</div> | ||||
|           <a :href="item.url" target="_blank"> | ||||
|             <a-space direction="vertical"> | ||||
|               <a-space> | ||||
|                 <img :src="item.logo" width="30px" alt="logo" /> | ||||
|                 <a-typography-text bold>{{ item.name }}</a-typography-text> | ||||
|               </a-space> | ||||
|               <a-typography-paragraph | ||||
|                 :ellipsis="{ | ||||
|                   rows: 6, | ||||
|                   showTooltip: true, | ||||
|                   css: true, | ||||
|                 }" | ||||
|               > | ||||
|                 <a-typography-text type="secondary"> | ||||
|                   {{ item.desc }} | ||||
|                 </a-typography-text> | ||||
|               </a-typography-paragraph> | ||||
|             </a-space> | ||||
|           </a> | ||||
|         </a-card> | ||||
|       </a-col> | ||||
|     </a-row> | ||||
|   </a-card> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| const list = [ | ||||
|   { | ||||
|     name: 'ContiNew Admin', | ||||
|     desc: '🔥Almost最佳后端规范🔥持续迭代优化的前后端分离中后台管理系统框架,开箱即用,持续提供舒适的开发体验。当前采用技术栈:Spring Boot3(Java17)、Vue3 & Arco Design、TS、Vite5 、Sa-Token、MyBatisPlus、Redisson、JetCache、Jackson、SpringDoc、Crane4j、Liquibase、Hutool 等。', | ||||
|     logo: 'https://continew.top/logo.svg', | ||||
|     url: 'https://gitee.com/continew/continew-admin', | ||||
|     status: '迭代', | ||||
|     statusColor: 'rgb(var(--primary-6))' | ||||
|   }, | ||||
|   { | ||||
|     name: 'ContiNew Starter', | ||||
|     desc: '🔥高质量Starter🔥包含了一系列经过企业实践优化的依赖包(如 MyBatis-Plus、SaToken),可轻松集成到应用中,为开发人员减少手动引入依赖及配置的麻烦,为 Spring Boot Web 项目的灵活快速构建提供支持。', | ||||
|     logo: 'https://continew.top/logo.svg', | ||||
|     url: 'https://gitee.com/continew/continew-starter', | ||||
|     status: '迭代', | ||||
|     statusColor: 'rgb(var(--primary-6))' | ||||
|   }, | ||||
|   { | ||||
|     name: 'ContiNew Admin UI', | ||||
|     desc: '全新 3.x 版本,基于 Gi Demo 前端模板开发的 ContiNew Admin 前端适配项目。', | ||||
|     logo: 'https://continew.top/logo.svg', | ||||
|     url: 'https://gitee.com/continew/continew-admin-ui', | ||||
|     status: '迭代', | ||||
|     statusColor: 'rgb(var(--primary-6))' | ||||
|   }, | ||||
|   { | ||||
|     name: 'ContiNew Admin UI Arco', | ||||
|     desc: '2.5 版本,基于 Arco Design Pro 前端模板开发的 ContiNew Admin 前端适配项目。', | ||||
|     logo: 'https://continew.top/logo.svg', | ||||
|     url: 'https://gitee.com/continew/continew-admin-ui-arco', | ||||
|     status: '归档', | ||||
|     statusColor: 'rgb(var(--warning-6))' | ||||
|   }, | ||||
|   { | ||||
|     name: 'ContiNew Cloud', | ||||
|     desc: 'ContiNew Admin 微服务版本。', | ||||
|     logo: 'https://continew.top/logo.svg', | ||||
|     url: '#', | ||||
|     status: '孵化', | ||||
|     statusColor: 'rgb(var(--danger-6))' | ||||
|   }, | ||||
|   { | ||||
|     name: 'charles7c.github.io', | ||||
|     desc: '基于 VitePress 构建的个人知识库/博客。扩展 VitePress 默认主题:增加ICP备案号、公安备案号显示,增加文章元数据信息(原创标识、作者、发布时间、分类、标签)显示,增加文末版权声明,增加 Gitalk 评论功能,主页美化、自动生成侧边栏、文章内支持 Mermaid 流程图、MD公式、MD脚注、增加我的标签、我的归档等独立页面,以及浏览器滚条等细节优化。查尔斯的个人技术知识库,记录 & 分享个人碎片化、结构化、体系化的技术知识内容。', | ||||
|     logo: 'https://blog.charles7c.top/logo.png', | ||||
|     url: 'https://github.com/Charles7c/charles7c.github.io', | ||||
|     status: '归档', | ||||
|     statusColor: 'rgb(var(--warning-6))' | ||||
|   } | ||||
| ] | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="less"> | ||||
| :deep(.arco-card-body) { | ||||
|   min-height: 128px; | ||||
|   overflow: hidden; | ||||
|   position: relative; | ||||
|   .badge { | ||||
|     position: absolute; | ||||
|     font-size: 12px; | ||||
|     height: 18px; | ||||
|     line-height: 18px; | ||||
|     text-align: center; | ||||
|     width: 74px; | ||||
|     color: #fff; | ||||
|   } | ||||
|   .badge-left { | ||||
|     -moz-transform: rotate(-45deg); | ||||
|     -ms-transform: rotate(-45deg); | ||||
|     -o-transform: rotate(-45deg); | ||||
|     -webkit-transform: rotate(-45deg); | ||||
|     transform: rotate(-45deg); | ||||
|     left: -18px; | ||||
|     top: 9px; | ||||
|   } | ||||
|   .badge-right { | ||||
|     -moz-transform: rotate(45deg); | ||||
|     -ms-transform: rotate(45deg); | ||||
|     -o-transform: rotate(45deg); | ||||
|     -webkit-transform: rotate(45deg); | ||||
|     transform: rotate(45deg); | ||||
|     right: -18px; | ||||
|     top: 9px; | ||||
|   } | ||||
| } | ||||
| .my-project { | ||||
|   &-header { | ||||
|     display: flex; | ||||
|     align-items: flex-start; | ||||
|     justify-content: space-between; | ||||
|   } | ||||
|  | ||||
|   &-title { | ||||
|     margin-top: 0 !important; | ||||
|     margin-bottom: 18px !important; | ||||
|   } | ||||
|  | ||||
|   &-list { | ||||
|     display: flex; | ||||
|     justify-content: space-between; | ||||
|   } | ||||
|  | ||||
|   &-item { | ||||
|     // padding-right: 16px; | ||||
|     margin-bottom: 16px; | ||||
|  | ||||
|     &:last-child { | ||||
|       padding-right: 0; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @@ -1,111 +0,0 @@ | ||||
| <template> | ||||
|   <a-card title="项目" :bordered="false" size="medium" class="gi_card_title" style="overflow: hidden"> | ||||
|     <a-row align="stretch"> | ||||
|       <a-col v-for="(item, index) in list" :key="item.name" :xs="12" :sm="8" :md="8"> | ||||
|         <a-card-grid class="w-full h-full"> | ||||
|           <a-card :bordered="false" hoverable :class="`animated-fade-up-${index}`"> | ||||
|             <a :href="item.url" target="_blank"> | ||||
|               <section class="item"> | ||||
|                 <div class="item__header"> | ||||
|                   <img :src="item.logo" width="30px" alt="logo" /> | ||||
|                   <span class="item__name gi_line_1">{{ item.name }}</span> | ||||
|                 </div> | ||||
|                 <div class="item__middle"> | ||||
|                   <p class="item__desc gi_line_2">{{ item.desc }}</p> | ||||
|                 </div> | ||||
|               </section> | ||||
|             </a> | ||||
|           </a-card> | ||||
|         </a-card-grid> | ||||
|       </a-col> | ||||
|     </a-row> | ||||
|   </a-card> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| const list = [ | ||||
|   { | ||||
|     name: 'ContiNew Admin', | ||||
|     desc: '持续优化的前后端分离中后台管理框架,开箱即用,持续提供舒适的开发体验。', | ||||
|     logo: 'https://continew.top/logo.svg', | ||||
|     url: 'https://gitee.com/continew/continew-admin' | ||||
|   }, | ||||
|   { | ||||
|     name: 'ContiNew Starter', | ||||
|     desc: '包含了一系列经过企业实践优化的依赖包(如 MyBatis-Plus、SaToken)。', | ||||
|     logo: 'https://continew.top/logo.svg', | ||||
|     url: 'https://gitee.com/continew/continew-starter' | ||||
|   }, | ||||
|   { | ||||
|     name: 'ContiNew Admin UI', | ||||
|     desc: '全新 3.0 版本,基于 Gi Demo 前端模板开发的 ContiNew Admin 前端适配项目。', | ||||
|     logo: 'https://continew.top/logo.svg', | ||||
|     url: 'https://gitee.com/continew/continew-admin-ui' | ||||
|   }, | ||||
|   { | ||||
|     name: 'ContiNew Admin UI Arco', | ||||
|     desc: '2.5 版本,基于 Arco Design Pro 前端模板开发的 ContiNew Admin 前端适配项目。', | ||||
|     logo: 'https://continew.top/logo.svg', | ||||
|     url: 'https://gitee.com/continew/continew-admin-ui-arco' | ||||
|   }, | ||||
|   { | ||||
|     name: 'ContiNew Cloud(孵化中)', | ||||
|     desc: 'ContiNew Admin 微服务版本', | ||||
|     logo: 'https://continew.top/logo.svg', | ||||
|     url: '#' | ||||
|   }, | ||||
|   { | ||||
|     name: 'charles7c.github.io', | ||||
|     desc: '基于 VitePress 构建的个人知识库/博客,扩展 VitePress 默认主题。', | ||||
|     logo: 'https://blog.charles7c.top/logo.png', | ||||
|     url: 'https://github.com/Charles7c/charles7c.github.io' | ||||
|   } | ||||
| ] | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| :deep(.arco-card) { | ||||
|   height: 100%; | ||||
|   .arco-card-body { | ||||
|     height: 100%; | ||||
|     box-sizing: border-box; | ||||
|   } | ||||
| } | ||||
|  | ||||
| :deep(.arco-card-header) { | ||||
|   border: none; | ||||
| } | ||||
|  | ||||
| .item { | ||||
|   height: 100%; | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   &__header { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|   } | ||||
|   &__name { | ||||
|     margin-left: 10px; | ||||
|     font-size: 1.125rem; | ||||
|     line-height: 1.75rem; | ||||
|     color: var(--color-text-1); | ||||
|     &:hover { | ||||
|       color: rgb(var(--arcoblue-6)); | ||||
|     } | ||||
|   } | ||||
|   &__middle { | ||||
|     flex: 1; | ||||
|   } | ||||
|   &__desc { | ||||
|     flex: 1; | ||||
|     margin-top: 10px; | ||||
|     line-height: 1.5; | ||||
|     color: var(--color-text-2); | ||||
|   } | ||||
|   &__footer { | ||||
|     font-size: 12px; | ||||
|     color: var(--color-text-3); | ||||
|     margin-top: 8px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										40
									
								
								src/views/dashboard/workplace/components/QuickOperation.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/views/dashboard/workplace/components/QuickOperation.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <template> | ||||
|   <a-card | ||||
|     class="general-card" | ||||
|     title="快捷操作" | ||||
|     :header-style="{ paddingBottom: '0' }" | ||||
|     :body-style="{ padding: '24px 20px 16px 20px' }" | ||||
|   > | ||||
|     <a-row :gutter="8"> | ||||
|       <a-col | ||||
|         v-for="link in links" | ||||
|         :key="link.text" | ||||
|         :span="8" | ||||
|         class="wrapper" | ||||
|         @click="router.replace({ path: link.path })" | ||||
|       > | ||||
|         <div class="icon"> | ||||
|           <GiSvgIcon :name="link.icon" /> | ||||
|         </div> | ||||
|         <a-typography-paragraph class="text"> | ||||
|           {{ link.text }} | ||||
|         </a-typography-paragraph> | ||||
|       </a-col> | ||||
|     </a-row> | ||||
|   </a-card> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| const router = useRouter() | ||||
|  | ||||
| const links = [ | ||||
|   { text: '用户管理', icon: 'user', path: '/system/user' }, | ||||
|   { text: '角色管理', icon: 'user-group', path: '/system/role' }, | ||||
|   { text: '菜单管理', icon: 'menu', path: '/system/menu' }, | ||||
|   { text: '文件管理', icon: 'file', path: '/system/file' }, | ||||
|   { text: '代码生成', icon: 'code', path: '/tool/generator' }, | ||||
|   { text: '系统日志', icon: 'history', path: '/monitor/log' } | ||||
| ] | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="less"></style> | ||||
| @@ -1,34 +0,0 @@ | ||||
| <template> | ||||
|   <a-card title="特别赞助" :bordered="false" size="medium" class="card gi_card_title"> | ||||
|     <template #extra> | ||||
|       <a-link href="https://continew.top/other/sponsor.html" target="_blank" rel="noopener">>></a-link> | ||||
|     </template> | ||||
|     <a-row :gutter="8"> | ||||
|       <a-carousel | ||||
|         v-if="imageList.length" | ||||
|         indicator-type="slider" | ||||
|         show-arrow="always" | ||||
|         auto-play | ||||
|         style="width: 100%; height: 110px; border-radius: 4px; overflow: hidden" | ||||
|       > | ||||
|         <a-carousel-item v-for="(image, idx) in imageList" :key="idx"> | ||||
|           <a :href="image.link" target="_blank" :title="image.title"> | ||||
|             <img :src="image.src" style="width: 100%; height: 100%" :alt="image.title" /> | ||||
|           </a> | ||||
|         </a-carousel-item> | ||||
|       </a-carousel> | ||||
|       <a-empty v-else /> | ||||
|     </a-row> | ||||
|   </a-card> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| interface ImageType { | ||||
|   src: string | ||||
|   title: string | ||||
|   link: string | ||||
| } | ||||
|  | ||||
| const imageList: ImageType[] = [ | ||||
| ] | ||||
| </script> | ||||
| @@ -1,19 +0,0 @@ | ||||
| <template> | ||||
|   <a-carousel | ||||
|     indicator-type="slider" | ||||
|     show-arrow="hover" | ||||
|     auto-play | ||||
|     style="width: 120px; height: 100px; border-radius: 4px; overflow: hidden" | ||||
|   > | ||||
|     <a-carousel-item v-for="(src, idx) in imageSrc" :key="idx"> | ||||
|       <div style="padding-bottom: 10px; text-align: center"> | ||||
|         <img :src="src" style="width: 80px" alt="QrCode" /> | ||||
|         <div style="text-align: center">备注cnadmin进群</div> | ||||
|       </div> | ||||
|     </a-carousel-item> | ||||
|   </a-carousel> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| const imageSrc = [`https://continew.top/qrcode.jpg?${new Date().getTime()}`] | ||||
| </script> | ||||
							
								
								
									
										43
									
								
								src/views/dashboard/workplace/components/Welcome.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/views/dashboard/workplace/components/Welcome.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| <template> | ||||
|   <a-card class="card" :bordered="false"> | ||||
|     <a-row align="center" wrap :gutter="[{ xs: 0, sm: 14, md: 14, lg: 14, xl: 14, xxl: 14 }, 16]" class="content"> | ||||
|       <a-space size="medium"> | ||||
|         <a-avatar :size="68"> | ||||
|           <img :src="userStore.avatar" alt="avatar" /> | ||||
|         </a-avatar> | ||||
|         <div class="welcome"> | ||||
|           <p class="hello">{{ goodTimeText() }}!{{ userStore.name }}</p> | ||||
|           <p>北海虽赊,扶摇可接;东隅已逝,桑榆非晚。</p> | ||||
|         </div> | ||||
|       </a-space> | ||||
|     </a-row> | ||||
|   </a-card> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import { useUserStore } from '@/stores' | ||||
| import { goodTimeText } from '@/utils' | ||||
|  | ||||
| const userStore = useUserStore() | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| :deep(.arco-statistic-title) { | ||||
|   margin-bottom: 0; | ||||
| } | ||||
|  | ||||
| .card { | ||||
|   .content { | ||||
|     padding: 8px 20px; | ||||
|     .welcome { | ||||
|       margin: 8px 0; | ||||
|       color: $color-text-3; | ||||
|       .hello { | ||||
|         font-size: 1.25rem; | ||||
|         color: $color-text-1; | ||||
|         margin-bottom: 10px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @@ -1,57 +0,0 @@ | ||||
| <template> | ||||
|   <a-card title="工作台" :bordered="false" class="card"> | ||||
|     <template #extra> | ||||
|       <NowTime /> | ||||
|     </template> | ||||
|     <a-row align="center" wrap :gutter="[{ xs: 0, sm: 14, md: 14, lg: 14, xl: 14, xxl: 14 }, 16]" class="content"> | ||||
|       <a-col :xs="24" :sm="24" :md="14" :lg="16" :xl="16" :xxl="18"> | ||||
|         <a-space size="medium"> | ||||
|           <a-avatar :size="68"> | ||||
|             <img :src="userStore.avatar" alt="avatar" /> | ||||
|           </a-avatar> | ||||
|           <div class="welcome"> | ||||
|             <p class="hello">{{ goodTimeText() }}!{{ userStore.name }}</p> | ||||
|             <p>北海虽赊,扶摇可接;东隅已逝,桑榆非晚。</p> | ||||
|           </div> | ||||
|         </a-space> | ||||
|       </a-col> | ||||
|       <a-col :xs="24" :sm="24" :md="10" :lg="8" :xl="8" :xxl="6" style="margin: -8px -7px"> | ||||
|         <a-row justify="end"> | ||||
|           <SupportCard v-if="isDesktop" /> | ||||
|         </a-row> | ||||
|       </a-col> | ||||
|     </a-row> | ||||
|   </a-card> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import NowTime from './NowTime/index.vue' | ||||
| import SupportCard from './SupportCard.vue' | ||||
| import { useDevice } from '@/hooks' | ||||
| import { useUserStore } from '@/stores' | ||||
| import { goodTimeText } from '@/utils' | ||||
|  | ||||
| const { isDesktop } = useDevice() | ||||
| const userStore = useUserStore() | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| :deep(.arco-statistic-title) { | ||||
|   margin-bottom: 0; | ||||
| } | ||||
|  | ||||
| .card { | ||||
|   .content { | ||||
|     padding: 8px 20px; | ||||
|     .welcome { | ||||
|       margin: 8px 0; | ||||
|       color: $color-text-3; | ||||
|       .hello { | ||||
|         font-size: 1.25rem; | ||||
|         color: $color-text-1; | ||||
|         margin-bottom: 10px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @@ -1,63 +1,128 @@ | ||||
| <template> | ||||
|   <div id="home" class="gi_page home"> | ||||
|     <WorkCard /> | ||||
|  | ||||
|     <a-alert> | ||||
|       全新版本 v3.3.0 已发布,重构全局响应处理,点击查看 | ||||
|       <span class="link" @click="open('https://continew.top/admin/other/changelog.html')">更新日志</span>。 | ||||
|     </a-alert> | ||||
|  | ||||
|     <a-row class="home__content"> | ||||
|       <a-col :xs="24" :sm="24" :md="24" :lg="12" :xl="18" :xxl="18"> | ||||
|         <div class="home__item"><ProjectCard /></div> | ||||
|         <div class="home__item"><AccessTrendCard /></div> | ||||
|       </a-col> | ||||
|       <a-col :xs="24" :sm="24" :md="24" :lg="12" :xl="6" :xxl="6"> | ||||
|         <div class="home__item"><FastCard /></div> | ||||
|         <div class="home__item"><SponsorCard /></div> | ||||
|         <div class="home__item"><NoticeCard /></div> | ||||
|       </a-col> | ||||
|     </a-row> | ||||
|  | ||||
|     <a-back-top :visible-height="100" target-container="#home" /> | ||||
|   <div class="gi_page container"> | ||||
|     <div class="left-side"> | ||||
|       <div class="panel"> | ||||
|         <Welcome /> | ||||
|       </div> | ||||
|       <div style="margin-top: 14px"> | ||||
|         <a-grid :cols="24" :col-gap="14" :row-gap="14"> | ||||
|           <a-grid-item :span="24"> | ||||
|             <Project /> | ||||
|           </a-grid-item> | ||||
|         </a-grid> | ||||
|       </div> | ||||
|     </div> | ||||
|     <div class="right-side"> | ||||
|       <a-grid :cols="24" :row-gap="14"> | ||||
|         <a-grid-item :span="24"> | ||||
|           <div class="panel moduler-wrap"> | ||||
|             <QuickOperation /> | ||||
|           </div> | ||||
|         </a-grid-item> | ||||
|         <a-grid-item class="panel" :span="24"> | ||||
|           <Carousel /> | ||||
|         </a-grid-item> | ||||
|         <a-grid-item class="panel" :span="24"> | ||||
|           <Notice /> | ||||
|         </a-grid-item> | ||||
|         <a-grid-item class="panel" :span="24"> | ||||
|           <Docs /> | ||||
|         </a-grid-item> | ||||
|       </a-grid> | ||||
|     </div> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import WorkCard from './components/WorkCard.vue' | ||||
| import ProjectCard from './components/ProjectCard.vue' | ||||
| import AccessTrendCard from './components/AccessTrendCard.vue' | ||||
| import FastCard from './components/FastCard.vue' | ||||
| import NoticeCard from './components/NoticeCard.vue' | ||||
| import SponsorCard from './components/SponsorCard.vue' | ||||
| import Welcome from './components/Welcome.vue' | ||||
| import Project from './components/Project.vue' | ||||
| import QuickOperation from './components/QuickOperation.vue' | ||||
| import Carousel from './components/Carousel.vue' | ||||
| import Notice from './components/Notice.vue' | ||||
| import Docs from './components/Docs.vue' | ||||
|  | ||||
| defineOptions({ name: 'Workplace' }) | ||||
|  | ||||
| const open = (url: string) => { | ||||
|   window.open(url, '_blank') | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped> | ||||
| .home { | ||||
|   padding: 0; | ||||
|   span.link { | ||||
| .container { | ||||
|   display: flex; | ||||
| } | ||||
|  | ||||
| .left-side { | ||||
|   flex: 1; | ||||
| } | ||||
|  | ||||
| .right-side { | ||||
|   width: 280px; | ||||
|   margin-left: 14px; | ||||
| } | ||||
|  | ||||
| .panel { | ||||
|   background-color: var(--color-bg-2); | ||||
|   border-radius: 4px; | ||||
|   overflow: auto; | ||||
| } | ||||
| :deep(.panel-border) { | ||||
|   margin-bottom: 0; | ||||
|   border-bottom: 1px solid rgb(var(--gray-2)); | ||||
| } | ||||
| .moduler-wrap { | ||||
|   border-radius: 4px; | ||||
|   background-color: var(--color-bg-2); | ||||
|   :deep(.text) { | ||||
|     font-size: 12px; | ||||
|     text-align: center; | ||||
|     color: rgb(var(--gray-8)); | ||||
|   } | ||||
|  | ||||
|   :deep(.wrapper) { | ||||
|     margin-bottom: 8px; | ||||
|     text-align: center; | ||||
|     cursor: pointer; | ||||
|     color: rgb(var(--arcoblue-6)); | ||||
|     font-weight: bold; | ||||
|  | ||||
|     &:last-child { | ||||
|       .text { | ||||
|         margin-bottom: 0; | ||||
|       } | ||||
|     } | ||||
|     &:hover { | ||||
|       opacity: 0.7; | ||||
|       .icon { | ||||
|         color: rgb(var(--arcoblue-6)); | ||||
|         background-color: #e8f3ff; | ||||
|       } | ||||
|       .text { | ||||
|         color: rgb(var(--arcoblue-6)); | ||||
|       } | ||||
|     } | ||||
|   &__content { | ||||
|     padding: 6px; | ||||
|   } | ||||
|   &__item { | ||||
|     padding: 6px; | ||||
|     box-sizing: border-box; | ||||
|   } | ||||
|   .backtop-icon { | ||||
|     cursor: pointer; | ||||
|  | ||||
|   :deep(.icon) { | ||||
|     display: inline-block; | ||||
|     width: 32px; | ||||
|     height: 32px; | ||||
|     margin-bottom: 4px; | ||||
|     color: rgb(var(--dark-gray-1)); | ||||
|     line-height: 32px; | ||||
|     font-size: 16px; | ||||
|     text-align: center; | ||||
|     background-color: rgb(var(--gray-1)); | ||||
|     border-radius: 4px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
|  | ||||
| <style lang="less" scoped> | ||||
| // responsive | ||||
| .mobile { | ||||
|   .container { | ||||
|     display: block; | ||||
|   } | ||||
|   .right-side { | ||||
|     // display: none; | ||||
|     width: 100%; | ||||
|     margin-left: 0; | ||||
|     margin-top: 16px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user