feat(dashboard): 添加首页控制台页面

This commit is contained in:
郝先瑞
2022-01-12 00:25:20 +08:00
parent aa89c386c5
commit a5746c7750
5 changed files with 1187 additions and 7 deletions

View File

@@ -0,0 +1,81 @@
<template>
<li :class="{ completed: todo.done, editing: editing }" class="todo">
<div class="view">
<input
:checked="todo.done"
class="toggle"
type="checkbox"
@change="toggleTodo( todo)"
>
<label @dblclick="editing = true" v-text="todo.text" />
<button class="destroy" @click="deleteTodo( todo )" />
</div>
<input
v-show="editing"
v-focus="editing"
:value="todo.text"
class="edit"
@keyup.enter="doneEdit"
@keyup.esc="cancelEdit"
@blur="doneEdit"
>
</li>
</template>
<script>
export default {
name: 'Todo',
directives: {
focus(el, { value }, { context }) {
if (value) {
context.$nextTick(() => {
el.focus()
})
}
}
},
props: {
todo: {
type: Object,
default: function() {
return {}
}
}
},
data() {
return {
editing: false
}
},
methods: {
deleteTodo(todo) {
this.$emit('deleteTodo', todo)
},
editTodo({ todo, value }) {
this.$emit('editTodo', { todo, value })
},
toggleTodo(todo) {
this.$emit('toggleTodo', todo)
},
doneEdit(e) {
const value = e.target.value.trim()
const { todo } = this
if (!value) {
this.deleteTodo({
todo
})
} else if (this.editing) {
this.editTodo({
todo,
value
})
this.editing = false
}
},
cancelEdit(e) {
e.target.value = this.todo.text
this.editing = false
}
}
}
</script>

View File

@@ -0,0 +1,320 @@
.todoapp {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
color: #4d4d4d;
min-width: 230px;
max-width: 550px;
margin: 0 auto ;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-weight: 300;
background: #fff;
z-index: 1;
position: relative;
button {
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
font-weight: inherit;
color: inherit;
-webkit-appearance: none;
appearance: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
:focus {
outline: 0;
}
.hidden {
display: none;
}
.todoapp {
background: #fff;
margin: 130px 0 40px 0;
position: relative;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
.todoapp input::-webkit-input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp input::-moz-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp input::input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp h1 {
position: absolute;
top: -155px;
width: 100%;
font-size: 100px;
font-weight: 100;
text-align: center;
color: rgba(175, 47, 47, 0.15);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
.new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 18px;
font-family: inherit;
font-weight: inherit;
line-height: 1.4em;
border: 0;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.new-todo {
padding: 10px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.003);
box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);
}
.main {
position: relative;
z-index: 2;
border-top: 1px solid #e6e6e6;
}
.toggle-all {
text-align: center;
border: none;
/* Mobile Safari */
opacity: 0;
position: absolute;
}
.toggle-all+label {
width: 60px;
height: 34px;
font-size: 0;
position: absolute;
top: -52px;
left: -13px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.toggle-all+label:before {
content: '';
font-size: 22px;
color: #e6e6e6;
padding: 10px 27px 10px 27px;
}
.toggle-all:checked+label:before {
color: #737373;
}
.todo-list {
margin: 0;
padding: 0;
list-style: none;
}
.todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px solid #ededed;
}
.todo-list li:last-child {
border-bottom: none;
}
.todo-list li.editing {
border-bottom: none;
padding: 0;
}
.todo-list li.editing .edit {
display: block;
width: 506px;
padding: 12px 16px;
margin: 0 0 0 43px;
}
.todo-list li.editing .view {
display: none;
}
.todo-list li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none;
/* Mobile Safari */
-webkit-appearance: none;
appearance: none;
}
.todo-list li .toggle {
opacity: 0;
}
.todo-list li .toggle+label {
/*
Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
*/
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
background-repeat: no-repeat;
background-position: center left;
background-size: 36px;
}
.todo-list li .toggle:checked+label {
background-size: 36px;
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
}
.todo-list li label {
word-break: break-all;
padding: 15px 15px 15px 50px;
display: block;
line-height: 1.0;
font-size: 14px;
transition: color 0.4s;
}
.todo-list li.completed label {
color: #d9d9d9;
text-decoration: line-through;
}
.todo-list li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 30px;
color: #cc9a9a;
transition: color 0.2s ease-out;
cursor: pointer;
}
.todo-list li .destroy:hover {
color: #af5b5e;
}
.todo-list li .destroy:after {
content: '×';
}
.todo-list li:hover .destroy {
display: block;
}
.todo-list li .edit {
display: none;
}
.todo-list li.editing:last-child {
margin-bottom: -1px;
}
.footer {
color: #777;
position: relative;
padding: 10px 15px;
height: 40px;
text-align: center;
border-top: 1px solid #e6e6e6;
}
.footer:before {
content: '';
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 40px;
overflow: hidden;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 8px 0 -3px #f6f6f6, 0 9px 1px -3px rgba(0, 0, 0, 0.2), 0 16px 0 -6px #f6f6f6, 0 17px 2px -6px rgba(0, 0, 0, 0.2);
}
.todo-count {
float: left;
text-align: left;
}
.todo-count strong {
font-weight: 300;
}
.filters {
margin: 0;
padding: 0;
position: relative;
z-index: 1;
list-style: none;
}
.filters li {
display: inline;
}
.filters li a {
color: inherit;
font-size: 12px;
padding: 3px 7px;
text-decoration: none;
border: 1px solid transparent;
border-radius: 3px;
}
.filters li a:hover {
border-color: rgba(175, 47, 47, 0.1);
}
.filters li a.selected {
border-color: rgba(175, 47, 47, 0.2);
}
.clear-completed,
html .clear-completed:active {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
cursor: pointer;
}
.clear-completed:hover {
text-decoration: underline;
}
.info {
margin: 65px auto 0;
color: #bfbfbf;
font-size: 10px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
text-align: center;
}
.info p {
line-height: 1;
}
.info a {
color: inherit;
text-decoration: none;
font-weight: 400;
}
.info a:hover {
text-decoration: underline;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
.toggle-all,
.todo-list li .toggle {
background: none;
}
.todo-list li .toggle {
height: 40px;
}
}
@media (max-width: 430px) {
.footer {
height: 50px;
}
.filters {
bottom: 10px;
}
}
}

View File

@@ -0,0 +1,135 @@
<template>
<section class="todoapp">
<!-- header -->
<header class="header">
<input class="new-todo" autocomplete="off" placeholder="Todo List" @keyup.enter="addTodo">
</header>
<!-- main section -->
<section v-show="todos.length" class="main">
<input id="toggle-all" :checked="allChecked" class="toggle-all" type="checkbox" @change="toggleAll({ done: !allChecked })">
<label for="toggle-all" />
<ul class="todo-list">
<todo
v-for="(todo, index) in filteredTodos"
:key="index"
:todo="todo"
@toggleTodo="toggleTodo"
@editTodo="editTodo"
@deleteTodo="deleteTodo"
/>
</ul>
</section>
<!-- footer -->
<footer v-show="todos.length" class="footer">
<span class="todo-count">
<strong>{{ remaining }}</strong>
{{ remaining | pluralize('item') }} left
</span>
<ul class="filters">
<li v-for="(val, key) in filters" :key="key">
<a :class="{ selected: visibility === key }" @click.prevent="visibility = key">{{ key | capitalize }}</a>
</li>
</ul>
</footer>
</section>
</template>
<script>
import Todo from './Todo.vue'
const STORAGE_KEY = 'todos'
const filters = {
all: todos => todos,
active: todos => todos.filter(todo => !todo.done),
completed: todos => todos.filter(todo => todo.done)
}
const defaultList = [
{ text: 'Vue2升级Vue3', done: false },
{ text: 'Element-UI升级Element-Plus', done: false },
{ text: '商城应用Android、IOS端适配开发', done: false },
{ text: 'IM即时通讯(Netty/ZooKeeper/Redis)', done: false },
{ text: 'ElasticSearch商品搜索', done: false },
{ text: '分库分表实践', done: false },
{ text: 'Seata-TCC模式', done: false },
{ text: '微服务链路追踪', done: false },
{ text: '多租户', done: false },
{ text: 'ELK日志收集->ELFK日志收集', done: false },
{ text: '微服务流控Sentinel', done: true },
{ text: 'ELK日志搜集', done: true },
{ text: 'RabbitMQ死信队列-订单超时取消', done: true },
{ text: 'Redission分布式锁', done: true },
{ text: 'Seata-AT模式', done: true },
{ text: '微服务基础设施', done: true },
{ text: 'OAuth2 + JWT统一认证鉴权', done: true },
{ text: 'RBAC权限设计', done: true }
]
export default {
components: { Todo },
data() {
return {
visibility: 'all',
filters,
todos: defaultList
}
},
computed: {
allChecked() {
return this.todos.every(todo => todo.done)
},
filteredTodos() {
return filters[this.visibility](this.todos)
},
remaining() {
return this.todos.filter(todo => !todo.done).length
}
},
methods: {
pluralize(n, w){
return n === 1 ? w : w + 's'
},
capitalize(s){
return s.charAt(0).toUpperCase() + s.slice(1)
},
setLocalStorage() {
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(this.todos))
},
addTodo(e) {
const text = e.target.value
if (text.trim()) {
this.todos.push({
text,
done: false
})
this.setLocalStorage()
}
e.target.value = ''
},
toggleTodo(val) {
val.done = !val.done
this.setLocalStorage()
},
deleteTodo(todo) {
this.todos.splice(this.todos.indexOf(todo), 1)
this.setLocalStorage()
},
editTodo({ todo, value }) {
todo.text = value
this.setLocalStorage()
},
clearCompleted() {
this.todos = this.todos.filter(todo => !todo.done)
this.setLocalStorage()
},
toggleAll({ done }) {
this.todos.forEach(todo => {
todo.done = done
this.setLocalStorage()
})
}
}
}
</script>
<style lang="scss">
@import './index.scss';
</style>

View File

@@ -1,13 +1,603 @@
<template>
<div> 这里是控制台</div>
<div class="dashboard-container">
<github-corner class="github-corner"/>
<el-row :gutter="40" class="card-panel-col">
<el-col :xs="12" :span="12" :lg="6">
<div class="card-panel">
<div class="card-panel-icon-wrapper" style="margin-top: -10px">
<el-image style="width:200px; height: 90px"
src="https://gitee.com/haoxr/image/raw/master/20210606213932.png"></el-image>
</div>
<div class="card-panel-description">
<div class="card-panel-text">
{{ nickname }}
</div>
<div class="card-panel-text">
<el-tag size="mini" type="danger">莫得感情</el-tag>
<el-tag size="mini" type="success" style="margin-left: 5px">打工人</el-tag>
</div>
</div>
</div>
</el-col>
<el-col :xs="12" :span="12" :lg="6" class="card-panel-col">
<div class="card-panel">
<div class="card-panel-icon-wrapper icon-people">
<svg-icon icon-class="peoples" class-name="card-panel-icon"/>
</div>
<div class="card-panel-description">
<div class="card-panel-text">
总访问量
</div>
<div class="card-panel-num">123456 </div>
</div>
</div>
</el-col>
<el-col :xs="12" :span="12" :lg="6" class="card-panel-col">
<div class="card-panel">
<div class="card-panel-icon-wrapper icon-money">
<svg-icon icon-class="money" class-name="card-panel-icon"/>
</div>
<div class="card-panel-description">
<div class="card-panel-text">
支付金额
</div>
<div class="card-panel-num">123456 </div>
</div>
</div>
</el-col>
<el-col :xs="12" :span="12" :lg="6" class="card-panel-col">
<div class="card-panel">
<div class="card-panel-icon-wrapper icon-shopping">
<svg-icon icon-class="shopping" class-name="card-panel-icon"/>
</div>
<div class="card-panel-description">
<div class="card-panel-text">
订单数
</div>
<div class="card-panel-num">123456 </div>
</div>
</div>
</el-col>
</el-row>
<el-row :gutter="40">
<el-col :span="12" :xs="24">
<el-card class="project-brief-introduction" style="height: 420px;">
<div slot="header" class="clearfix">
<span>有来项目简介</span>
</div>
<div style="font-size: 14px">
<div class="content">
<el-link target="_blank" style="font-weight: bold" type="primary" href="https://gitee.com/youlaitech/youlai-mall">
youlai-mall
</el-link>
是基于Spring Boot 2.5.0Spring Cloud 2020 &
Alibaba 2021vueelement-uiuni-app快速构建的一套全栈开源商城项目
<el-divider/>
项目采用微服务前后端分离开发模式
<br/>
汇集全栈主流的技术栈
涉及
<el-link target="_blank" type="primary" size="mini" href="https://gitee.com/youlaitech/youlai-mall">后端微服务</el-link>
<el-link target="_blank" type="success" size="mini" href="https://gitee.com/youlaitech/youlai-mall-admin">前端管理</el-link>
<el-link target="_blank" type="warning" size="mini" href="https://gitee.com/youlaitech/youlai-mall-weapp">微信小程序</el-link>
<el-link target="_blank" type="danger" size="mini" href="https://gitee.com/youlaitech/youlai-mall-weapp">APP应用</el-link>
等多端的开发
</div>
<el-divider/>
<el-row :gutter="10">
<el-col :span="8">
<el-badge value="免费开源" style="font-weight: bold">
项目源码地址
</el-badge>
</el-col>
<el-col :span="8">
<el-link target="_blank" type="primary" href="https://github.com/hxrui">github</el-link>
</el-col>
<el-col :span="8">
<el-link target="_blank" type="success" href="https://gitee.com/haoxr">码云</el-link>
</el-col>
</el-row>
<el-divider/>
<el-row :gutter="10">
<el-col :span="8" style="font-weight: bold">
接口文档地址
</el-col>
<el-col :span="8">
<el-link target="_blank" type="primary" href="http://www.youlai.tech:9999/doc.html">线上</el-link>
</el-col>
<el-col :span="8">
<el-link target="_blank" type="success" href="http://localhost:9999/doc.html">本地</el-link>
</el-col>
</el-row>
<el-divider/>
<el-row :gutter="10">
<el-col :span="8" style="font-weight: bold">
后端技术栈
</el-col>
<el-col :span="16">
Spring BootSpring CloudSpring Cloud AlibabaSpring Security OAuth2JWTMybatis-PlusSeataSentinelELKRedis
</el-col>
</el-row>
<el-divider/>
<el-row :gutter="10">
<el-col :span="8" style="font-weight: bold">
前端技术栈
</el-col>
<el-col :span="16">
vueelement-uiuni-appvue-element-admin
</el-col>
</el-row>
</div>
</el-card>
</el-col>
<el-col :span="12" :xs="24">
<el-card class="technology-stack" style="height: 420px;">
<div slot="header" class="clearfix">
<span>联系信息</span>
</div>
<div style="font-size: 14px">
<el-tabs v-model="contactActiveName">
<el-tab-pane label="开发人员" name="1">
<el-row :gutter="5">
<el-col :span="8">
<el-card :body-style="{ padding: '0px' }" align="center">
<el-image
style="width: 60px; height: 60px"
src="https://gitee.com/haoxr/image/raw/master/hxr.jpg"
:preview-src-list="['https://gitee.com/haoxr/image/raw/master/hxr.jpg']">
</el-image>
<div style="padding: 6px;">
<span tyle="font-size: 14px">郝先瑞</span>
<div class="bottom clearfix" style="margin-top: 5px">
<el-tag type="primary" size="mini">后端</el-tag>
<el-tag type="success" style="margin-left: 5px" size="mini">前端</el-tag>
<el-tag type="danger" style="margin-left: 5px" size="mini">运维</el-tag>
</div>
</div>
</el-card>
</el-col>
<el-col :span="8">
<el-card :body-style="{ padding: '0px' }" align="center">
<el-image
style="width: 60px; height: 60px"
src="https://gitee.com/haoxr/image/raw/master/huawei.jpg"
:preview-src-list="['https://gitee.com/haoxr/image/raw/master/huawei.jpg']">
</el-image>
<div style="padding: 6px;">
<span>猴子也能上天</span>
<div class="bottom clearfix" style="margin-top: 5px">
<el-tag type="primary" size="mini">后端</el-tag>
<el-tag type="success" style="margin-left: 5px" size="mini">前端</el-tag>
<el-tag type="danger" style="margin-left: 5px" size="mini">运维</el-tag>
</div>
</div>
</el-card>
</el-col>
<el-col :span="8">
<el-card :body-style="{ padding: '0px' }" align="center">
<el-image
style="width: 60px; height: 60px"
src=" https://gitee.com/haoxr/image/raw/master/DaniR.png"
:preview-src-list="['https://gitee.com/haoxr/image/raw/master/DaniR.png']">
</el-image>
<div style="padding: 6px;">
<span>DaniR</span>
<div class="bottom clearfix" style="margin-top: 5px">
<el-tag type="primary" size="mini">后端</el-tag>
<el-tag type="success" style="margin-left: 5px" size="mini">前端</el-tag>
<el-tag type="danger" style="margin-left: 5px" size="mini">运维</el-tag>
</div>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="5" style="margin-top: 8px">
<el-col :span="8">
<el-card :body-style="{ padding: '0px' }" align="center">
<el-image
style="width: 60px; height: 60px"
src="https://gitee.com/haoxr/image/raw/master/20210606203219.png"
:preview-src-list="['https://gitee.com/haoxr/image/raw/master/20210606203219.png']">
</el-image>
<div style="padding: 6px;">
<span>Mr.</span>
<div class="bottom clearfix" style="margin-top: 5px">
<el-tag type="primary" size="mini">后端</el-tag>
<el-tag type="success" style="margin-left: 5px" size="mini">前端</el-tag>
<el-tag type="danger" style="margin-left: 5px" size="mini">运维</el-tag>
</div>
</div>
</el-card>
</el-col>
<el-col :span="8">
<el-card :body-style="{ padding: '0px' }" align="center">
<el-image
style="width: 60px; height: 60px"
src=" https://gitee.com/haoxr/image/raw/master/20210606203659.png"
:preview-src-list="['https://gitee.com/haoxr/image/raw/master/20210606203659.png']">
</el-image>
<div style="padding: 6px;">
<span>???</span>
<div class="bottom clearfix" style="margin-top: 5px">
<el-tag type="warning" size="mini">??</el-tag>
</div>
</div>
</el-card>
</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="微信群" name="2">
<el-image
style="width: 210px; height: 210px"
src="https://gitee.com/haoxr/image/raw/master/default/%E5%9B%A2%E9%98%9FLOGO_%E5%89%AF%E6%9C%AC.png"
:preview-src-list="['https://gitee.com/haoxr/image/raw/master/default/%E5%9B%A2%E9%98%9FLOGO_%E5%89%AF%E6%9C%AC.png']">
</el-image>
<el-link style="margin-top: 10px" type="danger" :underline="false">群二维码过期请添加开发人员微信备注有来</el-link>
</el-tab-pane>
<el-tab-pane label="微信小程序体验码" name="3">
<el-image
style="width: 210px; height: 210px"
src="https://gitee.com/haoxr/image/raw/master/default/%E5%9B%A2%E9%98%9FLOGO_%E5%89%AF%E6%9C%AC.png"
:preview-src-list="['https://gitee.com/haoxr/image/raw/master/default/%E5%9B%A2%E9%98%9FLOGO_%E5%89%AF%E6%9C%AC.png']">
</el-image>
</el-tab-pane>
</el-tabs>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="40">
<el-col :span="6" :xs="24">
<el-card class="technology-stack">
<div slot="header" class="clearfix">
<span>更新日志</span>
</div>
<div style="font-size: 14px">
<el-collapse v-model="updateLogActiveName" accordion>
<el-collapse-item name="1">
<template slot="title">
v1.0.0 - 2021.06.06
<el-tooltip content="版本重大更新" placement="right">
<i style="margin-left: 5px;color: red" class="header-icon el-icon-star-on"></i>
</el-tooltip>
</template>
<div>1. 权限重构RESTFul URL权限和按钮权限数据归并</div>
<div>2. 新增角色编码逻辑</div>
<div>3. 网关新增本地公钥的方式</div>
<div>4. 认证中心移除MySQL数据源</div>
<div>5. OAuth2客户端官方表oauth_client_details重命名sys_oauth_client</div>
<div>6. 自定义实现ClientDetailsService接口loadClientByClientId方法</div>
<div>7. JWT的权限属性authorities将角色ID调整为角色编码</div>
<div>8. 网关统一鉴权优化设置了权限规则的请求进行拦截鉴权</div>
<div>9. 菜单角色管理界面针对小尺寸屏幕友好优化</div>
<div>10. Spring Boot升级 2.4.4 <i class="el-icon-right"></i> 2.5.0</div>
<div>11. Spring Cloud升级 2020.0.2<i class="el-icon-right"></i>2020.0.3</div>
<div>12. Spring Cloud Alibaba升级 2020.0.RC1<i class="el-icon-right"></i>2021.1</div>
<div>13. Nacos服务升级 2.0.0<i class="el-icon-right"></i>2.0.1</div>
<div>14. 表字段统一调整gmt_create<i class="el-icon-right"></i>create_timegmt_update<i
class="el-icon-right"></i>update-time
</div>
<div>15. 前端管理控制台优化</div>
<div>16. JWT的密钥对修改youlai.jks<i class="el-icon-right"></i>jwt.jks</div>
</el-collapse-item>
</el-collapse>
</div>
</el-card>
</el-col>
<el-col :span="6" :xs="24">
<el-card class="technology-stack">
<div slot="header" class="clearfix">
<span>计划事项</span>
</div>
<div style="font-size: 14px">
<todo-list/>
</div>
</el-card>
</el-col>
<el-col :span="12" :xs="24">
<el-card class="technology-stack">
<div slot="header" class="clearfix">
<span>项目文档</span>
</div>
<div style="font-size: 14px">
<el-tabs v-model="documentActiveName">
<el-tab-pane label="后端文档" name="1">
<el-link target="_blank" type="primary" href="https://www.cnblogs.com/haoxianrui/p/13581881.html">1. Spring Cloud实战 |
第一篇Windows搭建Nacos服务
</el-link>
<el-divider/>
<el-link target="_blank" type="primary" href="https://www.cnblogs.com/haoxianrui/p/13584204.html">2. Spring Cloud实战 |
第二篇Spring Cloud整合Nacos实现注册中心
</el-link>
<el-divider/>
<el-link target="_blank" type="primary" href="https://www.cnblogs.com/haoxianrui/p/13585125.html">3. Spring Cloud实战 |
第三篇Spring Cloud整合Nacos实现配置中心
</el-link>
<el-divider/>
<el-link target="_blank" type="primary" href="https://www.cnblogs.com/haoxianrui/p/13608650.html">4. Spring Cloud实战 |
第四篇Spring Cloud整合Gateway实现API网关
</el-link>
<el-divider/>
<el-link target="_blank" type="primary" href="https://www.cnblogs.com/haoxianrui/p/13615592.html">5. Spring Cloud实战 |
第五篇Spring Cloud整合OpenFeign实现微服务之间的调用
</el-link>
<el-divider/>
<el-badge value="热">
<el-link target="_blank" type="primary" href="https://www.cnblogs.com/haoxianrui/p/13719356.html">6. Spring Cloud实战 |
第六篇Spring Cloud Gateway+Spring Security OAuth2+JWT实现微服务统一认证授权
</el-link>
</el-badge>
<el-divider/>
<el-link target="_blank" type="primary" href="https://www.cnblogs.com/haoxianrui/p/13740264.html">7. Spring Cloud实战
|
最七篇Spring Cloud Gateway+Spring Security OAuth2集成统一认证授权平台下实现注销使JWT失效方案
</el-link>
<el-divider/>
<el-link target="_blank" type="primary" href="https://www.cnblogs.com/haoxianrui/p/14022632.html">8. Spring Cloud实战
|
最八篇Spring Cloud +Spring Security OAuth2+ Vue前后端分离模式下无感知刷新实现JWT续期
</el-link>
<el-divider/>
<el-link target="_blank" type="primary" href="https://www.cnblogs.com/haoxianrui/p/14028366.html">9. Spring Cloud实战
|
最九篇Spring Security OAuth2认证服务器统一认证自定义异常处理
</el-link>
<el-divider/>
<el-link target="_blank" type="primary" href="https://www.cnblogs.com/haoxianrui/p/14280184.html">10. Spring Cloud&
Alibaba 实战 | 第十篇 Spring Cloud + Nacos整合Seata 1.4.1最新版本实现微服务架构中的分布式事务进阶之路必须要迈过的槛
</el-link>
<el-divider/>
<el-link target="_blank" type="primary" href="https://www.cnblogs.com/haoxianrui/p/14396990.html">11. Spring Cloud &
Alibaba 实战 | 第十一篇 Spring Cloud Gateway网关实现对RESTful接口权限和按钮权限细粒度控制
</el-link>
<el-divider/>
<el-link target="_blank" type="primary" href="https://www.cnblogs.com/haoxianrui/p/14720405.html">12. Spring Cloud &
Alibaba 实战 | 第十二篇 Sentinel+Nacos实现流控熔断降级赋能拥有降级功能的Feign新技能熔断做到熔断降级双剑合璧
</el-link>
</el-tab-pane>
<el-tab-pane label="前端文档" name="2">
<el-link target="_blank" type="primary" href="https://www.cnblogs.com/haoxianrui/p/13624548.html">
1. vue-element-admin实战 | 第一篇 移除mock接入微服务接口搭建SpringCloud+Vue前后端分离管理平台
</el-link>
<el-divider/>
<el-link target="_blank" type="primary" href="https://www.cnblogs.com/haoxianrui/p/13676619.html">
2. vue-element-admin实战 | 第二篇 最小改动接入后台实现根据权限动态加载菜单
</el-link>
</el-tab-pane>
<el-tab-pane label="微信小程序文档" name="3">
<el-badge value="荐" style="margin-top: 10px">
<el-link target="_blank" type="primary"
href="https://www.cnblogs.com/haoxianrui/p/13882310.html">
1. vue+uni-app商城实战 | 第一篇从0到1快速开发一个商城微信小程序无缝接入Spring Cloud
OAuth2认证授权登录
</el-link>
</el-badge>
</el-tab-pane>
<el-tab-pane label="应用部署文档" name="4" align="center">
<svg-icon style="width: 200px;height: 200px;" icon-class="await"/>
</el-tab-pane>
<el-tab-pane name="5">
<span slot="label" class="start-doc">
<el-badge value="必读" style="margin-top:8px;">
<div style="margin-top: -10px">项目启动说明</div>
</el-badge>
</span>
<el-link target="_blank" type="primary"
href="https://gitee.com/youlaitech/youlai-mall#1-%E5%90%8E%E5%8F%B0%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%90%AF%E5%8A%A8">1. 后端微服务启动
</el-link>
<el-divider/>
<el-link target="_blank" type="primary"
href="https://gitee.com/youlaitech/youlai-mall#2-%E5%90%8E%E5%8F%B0%E5%89%8D%E7%AB%AF%E5%90%AF%E5%8A%A8">2. 管理前端启动
</el-link>
<el-divider/>
<el-link target="_blank" type="primary"
href="https://gitee.com/youlaitech/youlai-mall#3-%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%90%AF%E5%8A%A8">3. 微信小程序启动
</el-link>
</el-tab-pane>
</el-tabs>
</div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
name: "index"
}
<script setup lang="ts">
import GithubCorner from '@/components/GithubCorner/index.vue'
import TodoList from './components/TodoList/index.vue'
import {computed, reactive, toRefs} from "vue";
import SvgIcon from '@/components/SvgIcon/index.vue'
import {useUserStoreHook} from "@/store/modules/user"
const roles = computed(() => useUserStoreHook().roles);
const avatar = computed(() => useUserStoreHook().avatar);
const nickname = computed(() => useUserStoreHook().nickname);
const state =reactive({
updateLogActiveName: '1',
contactActiveName: '1',
documentActiveName: '1'
})
const {updateLogActiveName,contactActiveName,documentActiveName} = toRefs(state)
</script>
<style scoped>
</style>
<style lang="scss" scoped>
.dashboard-container {
padding: 24px;
background-color: rgb(240, 242, 245);
position: relative;
.project-brief-introduction {
.el-divider--horizontal {
margin: 16px 0;
}
.content {
line-height: 20px;
}
margin-bottom: 24px;
}
.technology-stack {
margin-bottom: 24px;
}
.github-corner {
position: absolute;
top: 0px;
border: 0;
right: 0;
z-index: 99;
}
.box-center {
margin: 0 auto;
display: table;
}
.user-profile {
.user-name {
}
.box-center {
padding-top: 10px;
}
.user-role {
padding-top: 10px;
font-weight: 400;
font-size: 14px;
}
.box-social {
padding-top: 30px;
.el-table {
border-top: 1px solid #dfe6ec;
}
}
.user-follow {
padding-top: 20px;
}
}
.card-panel-col {
margin-bottom: 12px;
}
.card-panel {
height: 108px;
cursor: pointer;
font-size: 12px;
position: relative;
overflow: hidden;
color: #666;
background: #fff;
box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
border-color: rgba(0, 0, 0, .05);
&:hover {
.card-panel-icon-wrapper {
color: #fff;
}
.icon-user {
background: #e77541;
}
.icon-people {
background: #40c9c6;
}
.icon-money {
background: #f4516c;
}
.icon-shopping {
background: #34bfa3
}
}
.icon-people {
color: #40c9c6;
.svg-icon{
width: 3em!important;
height: 3em!important;
}
}
.icon-message {
color: #36a3f7;
.svg-icon{
width: 3em!important;
height: 3em!important;
}
}
.icon-money {
color: #f4516c;
.svg-icon{
width: 3.2em!important;
height: 3.2em!important;
}
}
.icon-shopping {
color: #34bfa3;
.svg-icon{
width: 3em!important;
height: 3em!important;
}
}
.card-panel-icon-wrapper {
float: left;
margin: 14px 0 0 14px;
padding: 16px;
transition: all 0.38s ease-out;
border-radius: 6px;
}
.card-panel-description {
float: right;
font-weight: bold;
margin: 26px;
margin-left: 0px;
.card-panel-text {
line-height: 18px;
color: rgba(0, 0, 0, 0.45);
font-size: 16px;
margin-bottom: 12px;
}
.card-panel-num {
font-size: 20px;
}
}
}
}
</style>