Browse Source

add news

master
panda 9 months ago
parent
commit
a50369ae80
  1. 7
      src/App.vue
  2. 91
      src/components/admin/MainWrapper.vue
  3. 20
      src/components/admin/SignIn.vue
  4. 263
      src/components/blogs/HomePage.vue
  5. 5
      src/components/blogs/ceshi.vue
  6. 4
      src/main.ts

7
src/App.vue

@ -1,15 +1,16 @@
<template> <template>
<RouterView/> <RouterView/>
<!-- </Simplebar> -->
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Simplebar from 'simplebar-vue';
import 'simplebar-vue/dist/simplebar.min.css';
</script> </script>
<style> <style>
html{ html{
overflow: hidden; overflow: hidden;
} }
#app>*{
height: 100vh;
overflow: auto;
}
</style> </style>

91
src/components/admin/MainWrapper.vue

@ -1,25 +1,27 @@
<template> <template>
<a-flex>
<div class="menu" :style="{ width: state.menuWidth }">
<div class="menu_header">
<Simplebar >
<div id="container">
<div class="leftSidebar" :style="{ width: state.menuWidth }">
<a-flex justify="center" align="center" style="height: 48px;">
<TitleOutLined :class="collapsed ? 'small' : 'large'" /> <TitleOutLined :class="collapsed ? 'small' : 'large'" />
<span v-if="!collapsed">{{ state.name }}</span> <span v-if="!collapsed">{{ state.name }}</span>
</div>
<a-menu class="menu_navigate" v-model:openKeys="state.openKeys" v-model:selectedKeys="state.selectedKeys"
mode="inline" theme="light" :inline-collapsed="state.collapsed" :items="items" style="border-inline-end: none;"
@click="menuItemclick">
</a-flex>
<a-menu v-model:openKeys="state.openKeys" v-model:selectedKeys="state.selectedKeys" mode="inline" theme="light"
:inline-collapsed="state.collapsed" :items="items" style="border-inline-end: none;" @click="menuItemclick">
</a-menu> </a-menu>
</div> </div>
<div class="main" style="flex: 1;">
<div class="main_header">
<a-space>
<a-button @click="toggleCollapsed">
<MenuUnfoldOutlined v-if="state.collapsed" />
<MenuFoldOutlined v-else />
</a-button>
<a-button type="text" @click="jumpdashboard">首页</a-button>
</a-space>
<div class="user">
<div class="contentArea">
<div>
<a-flex>
<a-space>
<a-button @click="toggleCollapsed">
<MenuUnfoldOutlined v-if="state.collapsed" />
<MenuFoldOutlined v-else />
</a-button>
<a-button type="text" @click="jumpdashboard">首页</a-button>
</a-space>
</a-flex>
<a-flex align="center" gap="middle">
<span>{{ username }}</span> <span>{{ username }}</span>
<div> <div>
<a-button type="primary" @click="showModal" danger> <a-button type="primary" @click="showModal" danger>
@ -29,12 +31,12 @@
<p>确定要注销吗</p> <p>确定要注销吗</p>
</a-modal> </a-modal>
</div> </div>
</div>
</a-flex>
</div> </div>
<RouterView /> <RouterView />
</div> </div>
</a-flex>
</div>
</Simplebar>
</template> </template>
<script setup lang='ts'> <script setup lang='ts'>
@ -139,13 +141,10 @@ onMounted(async () => {
) )
username.value = userinfo.data.username username.value = userinfo.data.username
}); });
const open = ref<boolean>(false); const open = ref<boolean>(false);
const showModal = () => { const showModal = () => {
open.value = true; open.value = true;
}; };
const handleOk = (e: MouseEvent) => { const handleOk = (e: MouseEvent) => {
console.log(e); console.log(e);
authStore.removeToken() authStore.removeToken()
@ -155,30 +154,38 @@ const handleOk = (e: MouseEvent) => {
}, 2000); }, 2000);
open.value = false; open.value = false;
}; };
const handleCancel = (e: MouseEvent) => { const handleCancel = (e: MouseEvent) => {
message.warn('取消注销'); message.warn('取消注销');
} }
</script> </script>
<style scoped> <style scoped>
.menu {
#container {
display: flex;
}
.leftSidebar {
border-right: 1px solid rgba(5, 5, 5, 0.06); border-right: 1px solid rgba(5, 5, 5, 0.06);
font-size: 20px;
} }
.main_header {
display: flex;
margin: 24px;
justify-content: space-between;
.leftSidebar>* {
margin: 12px 0;
} }
.menu_header {
.leftSidebar>:first-child {
font-size: 20px;
}
.contentArea {
flex: 1;
}
.contentArea>:first-child{
margin: 24px;
display: flex; display: flex;
justify-content: center;
flex-direction: row;
justify-content: space-between;
align-items: center; align-items: center;
height: 98px;
font-size: 20px;
} }
.small { .small {
@ -190,20 +197,4 @@ const handleCancel = (e: MouseEvent) => {
font-size: 50px; font-size: 50px;
margin: 0 10px 0 10px; margin: 0 10px 0 10px;
} }
.navigate_button {
justify-content: space-between;
align-items: center;
border-block-end: 1px solid rgba(5, 5, 5, 0.06);
}
.user {
display: flex;
align-items: center;
}
.user>* {
padding: 0 5px;
}
</style> </style>

20
src/components/admin/SignIn.vue

@ -2,7 +2,7 @@
<context-holder /> <context-holder />
<div id="container"> <div id="container">
<a-spin v-if="loading" tip="Loading..."></a-spin> <a-spin v-if="loading" tip="Loading..."></a-spin>
<a-form v-else :model="formState" name="normal_login" class="login-form" @submit.prevent="login">
<a-form v-else :model="formState" @submit.prevent="login">
<h2>博客管理系统</h2> <h2>博客管理系统</h2>
<a-form-item label="用户名" name="username" :rules="[{ required: true, validator: verifyName }]"> <a-form-item label="用户名" name="username" :rules="[{ required: true, validator: verifyName }]">
<a-input v-model:value="formState.username" placeholder="请输入用户名"> <a-input v-model:value="formState.username" placeholder="请输入用户名">
@ -11,12 +11,11 @@
</template> </template>
</a-input> </a-input>
</a-form-item> </a-form-item>
<a-form-item label="密&nbsp;&nbsp;&nbsp;&nbsp;码" name="password" <a-form-item label="密&nbsp;&nbsp;&nbsp;&nbsp;码" name="password"
:rules="[{ required: true, validator: verifyPassword }]"> :rules="[{ required: true, validator: verifyPassword }]">
<a-input-password v-model:value="formState.password" placeholder="请输入密码"> <a-input-password v-model:value="formState.password" placeholder="请输入密码">
<template #prefix> <template #prefix>
<LockOutlined class="site-form-item-icon" />
<LockOutlined />
</template> </template>
</a-input-password> </a-input-password>
</a-form-item> </a-form-item>
@ -26,9 +25,8 @@
</a-form-item> </a-form-item>
<a class="login-form-forgot" href="">忘记密码</a> <a class="login-form-forgot" href="">忘记密码</a>
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<a-button type="primary" html-type="submit" class="login-form-button" :disabled="disabled">
<a-button type="primary" html-type="submit" :disabled="disabled">
</a-button> </a-button>
Or Or
@ -140,16 +138,4 @@ h2 {
text-align: center; text-align: center;
color: rgba(41, 39, 51, 0.88); color: rgba(41, 39, 51, 0.88);
} }
#components-form-demo-normal-login .login-form {
max-width: 300px;
}
#components-form-demo-normal-login .login-form-forgot {
float: right;
}
#components-form-demo-normal-login .login-form-button {
width: 100%;
}
</style> </style>

263
src/components/blogs/HomePage.vue

@ -1,107 +1,108 @@
<template> <template>
<Simplebar style="height: 100vh;overflow: auto;" @scroll="handleScroll">
<div class="menu" v-if="show_menu">
<Simplebar @scroll="handleScroll">
<!-- 头部导航菜单 -->
<div class="headerMenu" v-if="show_menu">
<a-menu v-model:selectedKeys="current" mode="horizontal" :items="items" style="border-bottom: none;" /> <a-menu v-model:selectedKeys="current" mode="horizontal" :items="items" style="border-bottom: none;" />
<a-input-search v-model:value="value" placeholder="search" style="width: 200px" @search="onSearch" /> <a-input-search v-model:value="value" placeholder="search" style="width: 200px" @search="onSearch" />
</div> </div>
<div class="salon-light-text"></div>
<div class="carouse">
<div class="author"></div>
<!-- 轮播 -->
<div>
<a-carousel autoplay> <a-carousel autoplay>
<div class="img"><img src="/src/assets/images/nav1.png" alt=""></div> <div class="img"><img src="/src/assets/images/nav1.png" alt=""></div>
<div class="img"><img src="/src/assets/images/nav10.png" alt=""></div> <div class="img"><img src="/src/assets/images/nav10.png" alt=""></div>
<div class="img"><img src="/src/assets/images/nav13.png" alt=""></div> <div class="img"><img src="/src/assets/images/nav13.png" alt=""></div>
</a-carousel> </a-carousel>
</div> </div>
<a-button type="link" shape="circle" class="down_button" size="large" @click="downScroll">
<template #icon>
<DownCircleOutlined style="font-size: 35px;color: aliceblue;" spin />
</template>
</a-button>
<a-flex>
<a-flex vertical>
<a-card style="width: 350px;" hoverable>
<template #cover>
<img alt="example" :src="img" style="height: 350px;" />
<!-- 操作按钮滚动 -->
<div class="anchorDown">
<a-button type="link" shape="circle" size="large" @click="downScroll">
<template #icon>
<DownCircleOutlined style="font-size: 35px;color: aliceblue;" spin />
</template>
</a-button>
</div>
<!-- 主要内容区域 -->
<div class="mainContainer">
<a-card hoverable>
<img alt="example" :src="img" />
<a-card-meta title="SunFree" style="min-height: 100px">
<template #description>
<div class="cardtext"></div>
</template> </template>
<a-card-meta title="SunFree" style="height: 100px">
<template #description>
<div class="cardtext"></div>
</template>
</a-card-meta>
<a-space wrap class="button-container">
<a-button shape="circle" size="large">
<GravatarLined />
</a-button>
<a-button shape="circle" size="large">
<QQLined />
</a-button>
<a-button shape="circle" size="large">
<WechatLined />
</a-button>
<a-button shape="circle" size="large">
<MusicLined />
</a-button>
<a-button shape="circle" size="large">
<GitHubLined />
</a-button>
</a-space>
<a-collapse class="custom-collapse" v-model:activeKey="activeKey" :bordered="false"
expandIconPosition="end">
<template #expandIcon="{ isActive }">
<caret-right-outlined :rotate="isActive ? 90 : 0" />
</template>
<a-collapse-panel key="1" header="内容1" :style="customStyle">
<p>{{ text }}</p>
</a-collapse-panel>
<a-collapse-panel key="2" header="内容2" :style="customStyle">
<p>{{ text }}</p>
</a-collapse-panel>
<a-collapse-panel key="3" header="内容3" :style="customStyle">
<p>{{ text }}</p>
</a-collapse-panel>
</a-collapse>
</a-card>
</a-flex>
<a-flex style="height: 500px;width: 60%;background-color: black;border: solid 1px red;">
</a-card-meta>
<a-space wrap>
<a-button shape="circle" size="large" @click="gravatarClick">
<GravatarLined />
</a-button>
<a-button shape="circle" size="large">
<QQLined />
</a-button>
<a-button shape="circle" size="large">
<WechatLined />
</a-button>
<a-button shape="circle" size="large">
<MusicLined />
</a-button>
<a-button shape="circle" size="large">
<GitHubLined />
</a-button>
</a-space>
<a-collapse v-model:activeKey="activeKey" :bordered="false" expandIconPosition="end">
<template #expandIcon="{ isActive }">
<caret-right-outlined :rotate="isActive ? 90 : 0" />
</template>
<a-collapse-panel key="1" header="内容1" :style="customStyle">
<p>{{ text }}</p>
</a-collapse-panel>
<a-collapse-panel key="2" header="内容2" :style="customStyle">
<p>{{ text }}</p>
</a-collapse-panel>
<a-collapse-panel key="3" header="内容3" :style="customStyle">
<p>{{ text }}</p>
</a-collapse-panel>
</a-collapse>
</a-card>
<div class="main">
<div></div> <div></div>
</a-flex>
<a-flex>
<a-card hoverable style="width: 400px">
</div>
<div class="rightBar">
<a-card hoverable style="width: 400px;">
<template #cover> <template #cover>
<div id="aplayer" style="width: 400px"></div>
<div class="heatmap">
<div ref="heat" style="height: 100%;border-right: 1px solid #e9e9e9;"></div>
<div id="aplayer" style="width: 400px;"></div>
<div class="heatmap" style="border-right: rgba(0, 0, 0, 0.5);">
<div ref="heat" style="height: 100%;"></div>
</div> </div>
<div class="statistic"> <div class="statistic">
<a-row> <a-row>
<a-col :span="8"> <a-col :span="8">
<a-statistic title="DAYS" :value="112893" />
<a-statistic title="DAYS" :value="112893" />
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-statistic title="DIARYS" :value="112893" />
<a-statistic title="DIARYS" :value="112893" />
</a-col> </a-col>
<a-col :span="8"> <a-col :span="8">
<a-statistic title="BLOGS" :value="112893" />
<a-statistic title="BLOGS" :value="112893" />
</a-col> </a-col>
</a-row> </a-row>
</div> </div>
</template> </template>
</a-card>
<a-card title="随机文章" :bordered="false" hoverable style="width: 400px;margin: 12px 0;">
sces
</a-card>
<a-card title="标签云" :bordered="false" hoverable style="width: 400px;margin: 12px 0;">
sces
</a-card> </a-card>
</a-flex>
<!-- <a-flex>
<div id="aplayer"></div>
<div>
<div ref="heat" style="height: 200px;width: 500px;"></div>
</div>
</a-flex> -->
</a-flex>
</div>
</div>
</Simplebar> </Simplebar>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import Simplebar from 'simplebar-vue';
import 'simplebar-vue/dist/simplebar.min.css';
import { h, reactive, ref } from 'vue'; import { h, reactive, ref } from 'vue';
import { MenuProps } from 'ant-design-vue/es/menu'; import { MenuProps } from 'ant-design-vue/es/menu';
import { HomeOutlined, HighlightOutlined, ProfileOutlined, CameraOutlined, UsergroupDeleteOutlined, DownCircleOutlined } from '@ant-design/icons-vue'; import { HomeOutlined, HighlightOutlined, ProfileOutlined, CameraOutlined, UsergroupDeleteOutlined, DownCircleOutlined } from '@ant-design/icons-vue';
@ -113,7 +114,8 @@ import 'APlayer/dist/APlayer.min.css';
import APlayer from 'APlayer'; import APlayer from 'APlayer';
import { createEcharts } from "@/hooks/intex" import { createEcharts } from "@/hooks/intex"
import { SettingOutlined, EditOutlined, EllipsisOutlined } from '@ant-design/icons-vue'; import { SettingOutlined, EditOutlined, EllipsisOutlined } from '@ant-design/icons-vue';
import { useRouter } from 'vue-router'
const router = useRouter()
const heat = ref(null); const heat = ref(null);
const activeKey = ref(['']); const activeKey = ref(['']);
const text = `A dog is a type of domesticated animal.Known for its loyalty and faithfulness,it can be found as a welcome guest in many households across the world.`; const text = `A dog is a type of domesticated animal.Known for its loyalty and faithfulness,it can be found as a welcome guest in many households across the world.`;
@ -121,7 +123,7 @@ const customStyle =
'background: #f7f7f7;border-radius: 4px;margin-bottom: 12px;border: 0;overflow: hidden'; 'background: #f7f7f7;border-radius: 4px;margin-bottom: 12px;border: 0;overflow: hidden';
onMounted(() => { onMounted(() => {
// home // home
new Typed('.salon-light-text', {
new Typed('.author', {
strings: ['SunFree.'], strings: ['SunFree.'],
typeSpeed: 200, typeSpeed: 200,
backSpeed: 150, backSpeed: 150,
@ -175,28 +177,35 @@ onMounted(() => {
const currentDate = new Date(); const currentDate = new Date();
for (let i = 0; i < numDays; i++) { for (let i = 0; i < numDays; i++) {
const date = new Date(currentDate); const date = new Date(currentDate);
date.setDate(currentDate.getDate() + i);
date.setDate(currentDate.getDate() - i);
dates.push( dates.push(
{ date: date.toISOString().split('T')[0], blogCount: 0 } { date: date.toISOString().split('T')[0], blogCount: 0 }
); // ); //
} }
return dates; return dates;
} }
// 60 // 60
const data = generateDates(60); const data = generateDates(60);
console.log(`output->`, data)
data[3].blogCount = 5; data[3].blogCount = 5;
data[15].blogCount = 10; data[15].blogCount = 10;
data[25].blogCount = 3; data[25].blogCount = 3;
const formattedData = data.map((value, index) => [index % 15, Math.floor(index / 15), value.blogCount]);
//
const newData = [];
for (let i = 0; i < 60; i += 15) {
// 15
const chunk = data.slice(i, i + 15).reverse();
newData.push(...chunk);
}
const formattedData = newData.map((value, index) => [index % 15, Math.floor(index / 15), value.blogCount]);
const heatMapData = { const heatMapData = {
tooltip: { tooltip: {
position: 'top', position: 'top',
formatter: function (params) {
const item = data[params.dataIndex];
formatter: function (params: any) {
const item = newData[params.dataIndex];
if (item.blogCount > 0) { if (item.blogCount > 0) {
return `${item.date}<br/>COMMENTS: ${item.blogCount}`; return `${item.date}<br/>COMMENTS: ${item.blogCount}`;
} else { } else {
@ -243,7 +252,7 @@ onMounted(() => {
type: 'heatmap', type: 'heatmap',
data: formattedData, data: formattedData,
itemStyle: { itemStyle: {
borderColor: 'rgba(0, 0, 0, 0.4)', //
borderColor: 'rgba(0, 0, 0, 0.1)', //
borderWidth: 0.5, // borderWidth: 0.5, //
}, },
label: { label: {
@ -259,7 +268,8 @@ onMounted(() => {
} }
}] }]
}; };
createEcharts(heat, heatMapData)
createEcharts(heat, heatMapData);
}) })
const current = ref<string[]>(['mail']); const current = ref<string[]>(['mail']);
const show_menu = ref(false); const show_menu = ref(false);
@ -346,14 +356,23 @@ const onSearch = (searchValue: string) => {
const img = ref("https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png") const img = ref("https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png")
const gravatarClick = () => {
window.open("https://www.baidu.com")
}
</script> </script>
<style scoped> <style scoped>
.menu {
.simplebar-wrapper {
height: 100vh;
overflow: auto;
}
.headerMenu {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
padding: 10px 0; padding: 10px 0;
width: 100%; width: 100%;
padding: 0 24px;
border-bottom: 1px solid rgba(5, 5, 5, 0.06); border-bottom: 1px solid rgba(5, 5, 5, 0.06);
position: fixed; position: fixed;
background-color: white; background-color: white;
@ -363,36 +382,12 @@ const img = ref("https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png")
z-index: 999; z-index: 999;
} }
.menu>* {
.headerMenu>* {
margin: 0 24px; margin: 0 24px;
} }
:deep(.slick-slide) {
text-align: center;
height: 100vh;
line-height: 160px;
background: #364d79;
overflow: hidden;
}
:deep(.slick-slide h3) {
color: #fff;
}
.down_button {
position: absolute;
bottom: 100px;
left: 50%;
border-style: hidden;
transform: translateX(-50%);
}
.Typewriter__wrapper {
font-size: 100px;
font-family: 'Courier New', Courier, monospace
}
.salon-light-text {
/* 作者名称 */
.author {
position: absolute; position: absolute;
display: inline-block; display: inline-block;
font-size: 100px; font-size: 100px;
@ -423,6 +418,45 @@ const img = ref("https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png")
} }
} }
.anchorDown {
position: absolute;
bottom: 100px;
left: 50%;
border-style: hidden;
transform: translateX(-50%);
}
.mainContainer {
display: flex;
justify-content: center;
padding-top: 60px;
background-color: rgba(5, 5, 5, 0.08);
}
.mainContainer>:first-child {
width: 15%;
}
.mainContainer img{
width: 100%;
/* 图片宽度占满容器 */
aspect-ratio: 1/1;
/* 图片自适应容器并保持宽高比例 */
}
.main {
height: 500px;
width: 45%;
margin: 0 24px;
background-color: black;
border: solid 1px red;
}
.rightBar {
width: 20%;
}
.button-container button { .button-container button {
margin: 24px 6px; margin: 24px 6px;
} }
@ -439,7 +473,12 @@ const img = ref("https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png")
.heatmap { .heatmap {
margin: 24px 0; margin: 24px 0;
} }
.statistic{
.statistic {
text-align: center; text-align: center;
} }
.sitebar {
width: 400px;
}
</style> </style>

5
src/components/blogs/ceshi.vue

@ -16,17 +16,18 @@ onMounted(() => {
const currentDate = new Date(); const currentDate = new Date();
for (let i = 0; i < numDays; i++) { for (let i = 0; i < numDays; i++) {
const date = new Date(currentDate); const date = new Date(currentDate);
date.setDate(currentDate.getDate() + i);
date.setDate(currentDate.getDate() - i);
dates.push( dates.push(
{ date: date.toISOString().split('T')[0], blogCount: 0 } { date: date.toISOString().split('T')[0], blogCount: 0 }
); // ); //
} }
return dates;
return dates.reverse();
} }
// 60 // 60
const data = generateDates(60); const data = generateDates(60);
console.log(data)
data[3].blogCount = 5; data[3].blogCount = 5;
data[15].blogCount = 10; data[15].blogCount = 10;
data[25].blogCount = 3; data[25].blogCount = 3;

4
src/main.ts

@ -4,9 +4,11 @@ import "normalize.css"
import App from './App.vue' import App from './App.vue'
import router from './router' import router from './router'
import Antd from 'ant-design-vue'; import Antd from 'ant-design-vue';
import Simplebar from 'simplebar-vue';
import 'simplebar-vue/dist/simplebar.min.css';
const app = createApp(App) const app = createApp(App)
app.component('Simplebar', Simplebar);
app.use(createPinia()) app.use(createPinia())
app.use(router) app.use(router)
app.use(Antd) app.use(Antd)
app.mount('#app') app.mount('#app')
Loading…
Cancel
Save