first commit
This commit is contained in:
36
resources/admin/views/dashboard/dependencies.vue
Normal file
36
resources/admin/views/dashboard/dependencies.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<div class="flex flex-col bg-white dark:bg-regal-dark pl-5 pr-5 rounded">
|
||||
<span class="text-lg mt-5">项目依赖</span>
|
||||
<div class="flex mt-3">
|
||||
<el-table :data="dependencies" border width="200">
|
||||
<el-table-column prop="dependency" label="Dependency" />
|
||||
<el-table-column prop="version" label="Version" />
|
||||
</el-table>
|
||||
<el-table :data="devDependencies" border>
|
||||
<el-table-column prop="devDependency" label="DevDependency" />
|
||||
<el-table-column prop="version" label="Version" />
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import packages from '/admin/../package.json'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const dependencies = computed(() => {
|
||||
const _dependencies = []
|
||||
for (const dependency in packages.dependencies) {
|
||||
_dependencies.push(Object.assign({ dependency, version: (packages.dependencies as any)[dependency] }))
|
||||
}
|
||||
|
||||
return _dependencies
|
||||
})
|
||||
const devDependencies = computed(() => {
|
||||
const _devDependencies = []
|
||||
for (const devDependency in packages.devDependencies) {
|
||||
_devDependencies.push(Object.assign({ devDependency, version: (packages.devDependencies as any)[devDependency] }))
|
||||
}
|
||||
|
||||
return _devDependencies
|
||||
})
|
||||
</script>
|
84
resources/admin/views/dashboard/index.vue
Normal file
84
resources/admin/views/dashboard/index.vue
Normal file
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="bg-white dark:bg-regal-dark rounded flex flex-col sm:flex-row justify-between">
|
||||
<div class="w-full sm:w-[40rem] flex flex-row p1-1 sm:pl-3 items-center justify-between min-h-28 border-b pb-2 sm:pb-0 sm:border-b-0 border-gray-400">
|
||||
<img :src="avatar" class="rounded-full w-16 h-16" />
|
||||
<div class="flex flex-col w-[34rem] pl-4 sm:pl-0 pt-2 sm:pt-3">
|
||||
<div class="text-lg text-zinc-800 dark:text-gray-200">很高兴见到你👋 ,{{ nickname }}!{{ itsTimeDo }}</div>
|
||||
<div class="text-sm text-gray-400 break-words pt-0 sm:pt-2">{{ context }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center h-28 w-full sm:w-[23rem] justify-between pl-2 pr-2 sm:pr-3">
|
||||
<div class="flex flex-col text-center">
|
||||
<div class="text-lg text-gray-600 dark:text-gray-400">项目数</div>
|
||||
<div class="text text-gray-400 dark:text-gray-200">1000</div>
|
||||
</div>
|
||||
|
||||
<el-divider direction="vertical" />
|
||||
<div class="flex flex-col text-center">
|
||||
<div class="text-lg text-gray-600 dark:text-gray-400">国内排名</div>
|
||||
<div class="text text-gray-400 dark:text-gray-200">1000</div>
|
||||
</div>
|
||||
<el-divider direction="vertical" border-style="dashed" />
|
||||
<div class="flex flex-col text-center">
|
||||
<div class="text-lg text-gray-600 dark:text-gray-400">团队成员</div>
|
||||
<div class="text text-gray-400 dark:text-gray-200">1000</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col sm:flex-row mt-4 justify-between">
|
||||
<Introduce />
|
||||
<Project />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
import { useUserStore } from '/admin/stores/modules/user'
|
||||
import Introduce from './introduce.vue'
|
||||
import Project from './project.vue'
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const nickname = computed(() => {
|
||||
return userStore.getNickname
|
||||
})
|
||||
|
||||
const avatar = computed(() => {
|
||||
return userStore.getAvatar
|
||||
})
|
||||
const itsTimeDo = computed(() => {
|
||||
const date = new Date()
|
||||
const now = date.getHours()
|
||||
if (isInRange(now, 2, 5)) {
|
||||
return '凌晨了,该休息了!注意身体!😪'
|
||||
} else if (isInRange(now, 5, 8)) {
|
||||
return '早晨,开始全新的一天!😊'
|
||||
} else if (isInRange(now, 8, 12)) {
|
||||
return '上午好,开始摸鱼的一天!😄'
|
||||
} else if (isInRange(now, 12, 18)) {
|
||||
return '下午好,快要下班了!再坚持下💪'
|
||||
} else if (isInRange(now, 18, 23)) {
|
||||
return '晚上了,请点击右上角关闭!👉'
|
||||
} else {
|
||||
return '深夜了,为什么还在打开该系统?💢'
|
||||
}
|
||||
})
|
||||
|
||||
const context = computed(() => {
|
||||
const contexts: string[] = [
|
||||
'资本主义社会里的民主是一种残缺不全的,贫乏和虚伪和民主,是只供富人,只供少数人享受的民主',
|
||||
'资本来到世间,从头到脚,每个毛孔都滴着血和肮脏的东西',
|
||||
'既然掠夺给少数人造成了天然的权利,那么多数人就只得积聚足够的力量,来取得夺回他们被夺去的一切的天然权利',
|
||||
'资本家有百分之五十的利润,就会铤而走险;有了百分之一百的利润就敢践踏人间一切法律;有了百分之三百的利润就敢冒上绞刑架的危险',
|
||||
]
|
||||
|
||||
return contexts[Math.floor(Math.random() * contexts.length)]
|
||||
})
|
||||
|
||||
function isInRange(compare: number, min: number, max: number) {
|
||||
return compare >= min && compare < max
|
||||
}
|
||||
</script>
|
121
resources/admin/views/dashboard/introduce.vue
Normal file
121
resources/admin/views/dashboard/introduce.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<div class="w-full sm:w-[72%]">
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<div class="flex flex-row justify-between">
|
||||
<span class="text-lg">项目基于</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-1">
|
||||
<el-card shadow="hover">
|
||||
<div class="flex justify-between">
|
||||
<Vue class="w-10 h-10" />
|
||||
<div class="text-lg">
|
||||
<el-link href="https://cn.vuejs.org/" target="_blank" :underline="false"><el-button type="success" size="small">GO</el-button></el-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm text-gray-400 pt-2">渐进式 JavaScript 框架 易学易用,性能出色,适用场景丰富的 Web 前端框架Go</div>
|
||||
</el-card>
|
||||
<el-card shadow="hover">
|
||||
<div class="flex justify-between">
|
||||
<Laravel class="w-10 h-10" />
|
||||
<div class="text-lg">
|
||||
<el-link href="https://learnku.com/docs/laravel" target="_blank" :underline="false"><el-button type="danger" size="small">GO</el-button></el-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm text-gray-400 pt-2">Laravel 是一个具有表现力、优雅语法的 Web 应用程序框架</div>
|
||||
</el-card>
|
||||
<el-card shadow="hover">
|
||||
<div class="flex justify-between">
|
||||
<Element class="w-10 h-10" />
|
||||
<div class="text-lg">
|
||||
<el-link href="https://element-plus.org/" target="_blank" :underline="false"><el-button type="primary" size="small">GO</el-button></el-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm text-gray-400 pt-2">Element Plus 基于 Vue3,面向设计师和开发者的组件库</div>
|
||||
</el-card>
|
||||
<el-card shadow="hover">
|
||||
<div class="flex justify-between">
|
||||
<Tailwindcss class="w-10 h-10" />
|
||||
<div class="text-lg">
|
||||
<el-link href="https://tailwindcss.com/" target="_blank" :underline="false"><el-button size="small">GO</el-button></el-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm text-gray-400 pt-2">Tailwind CSS 是一个功能类优先的 CSS 框架,无需离开您的HTML,即可快速建立现代网站</div>
|
||||
</el-card>
|
||||
<el-card shadow="hover">
|
||||
<div class="flex justify-between">
|
||||
<Composer class="w-10 h-10" />
|
||||
<div class="text-lg">
|
||||
<el-link href="https://getcomposer.org/" target="_blank" :underline="false"><el-button type="info" size="small">GO</el-button></el-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm text-gray-400 pt-2">Composer 是 PHP 中用于依赖管理的工具。它允许您声明项目所依赖的库,并将为您管理(安装/更新)它们。</div>
|
||||
</el-card>
|
||||
<el-card shadow="hover">
|
||||
<div class="flex justify-between">
|
||||
<Vite class="w-10 h-10" />
|
||||
<div class="text-lg">
|
||||
<el-link href="https://cn.vitejs.dev/" target="_blank" :underline="false"><el-button type="warning" size="small">Go</el-button></el-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm text-gray-400 pt-2">Vite 下一代的前端工具链 为开发提供极速响应</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<div>
|
||||
<el-card shadow="never" class="mt-4">
|
||||
<template #header>
|
||||
<div class="flex flex-row justify-between">
|
||||
<span class="text-lg">项目动态</span>
|
||||
</div>
|
||||
</template>
|
||||
<ul>
|
||||
<li class="flex border-b border-b-slate-200 dark:border-b-slate-700 pt-2">
|
||||
<div><el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" /></div>
|
||||
<div class="flex flex-col ml-4">
|
||||
<div class="text">JaguarJack 提交一个 PR</div>
|
||||
<div class="text-sm text-gray-400 mt-1 mb-2">1 小时前</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="flex border-b border-b-slate-200 dark:border-b-slate-700 pt-2">
|
||||
<div><el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" /></div>
|
||||
<div class="flex flex-col ml-4 mt-1">
|
||||
<div>JaguarJack 关闭了一个 Issue</div>
|
||||
<div class="text-sm text-gray-400 mt-1 mb-2">2 小时前</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="flex border-b border-b-slate-200 dark:border-b-slate-700 pt-2">
|
||||
<div><el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" /></div>
|
||||
<div class="flex flex-col ml-4 mt-1">
|
||||
<div>JaguarJack 提交新的 commit</div>
|
||||
<div class="text-sm text-gray-400 mt-1 mb-2">24 小时前</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="flex border-b border-b-slate-200 dark:border-b-slate-700 pt-2">
|
||||
<div><el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png" /></div>
|
||||
<div class="flex flex-col ml-4 mt-1">
|
||||
<div>JaguarJack 创建了一个 new project</div>
|
||||
<div class="text-sm text-gray-400 mt-1 mb-2">2021.10.26</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
// @ts-ignores
|
||||
import Laravel from '~icons/logos/laravel'
|
||||
// @ts-ignores
|
||||
import Vue from '~icons/logos/vue'
|
||||
// @ts-ignores
|
||||
import Vite from '~icons/logos/vitejs'
|
||||
// @ts-ignores
|
||||
import Element from '~icons/logos/element'
|
||||
// @ts-ignores
|
||||
import Composer from '~icons/logos/composer'
|
||||
// @ts-ignores
|
||||
import Tailwindcss from '~icons/logos/tailwindcss-icon'
|
||||
</script>
|
39
resources/admin/views/dashboard/project.vue
Normal file
39
resources/admin/views/dashboard/project.vue
Normal file
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<div class="w-full sm:w-[27%]">
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<div class="flex flex-row justify-between">
|
||||
<span class="text-lg">项目信息</span>
|
||||
</div>
|
||||
</template>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-1 gap-1">
|
||||
<div>
|
||||
<div class="text-xl text-center">Catch-admin</div>
|
||||
<div class="text-base text-gray-400">
|
||||
是一个基于Vue3.0、Vite、 ElementPlus 、TypeScript 的后台解决方案,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型。
|
||||
<el-link href="https://catchadmin.com/" target="_blank">更多...</el-link>
|
||||
</div>
|
||||
<div class="flex justify-between pl-4 pr-4 mt-2 w-full sm:w-[75%] m-auto">
|
||||
<a href="https://github.com/JaguarJack/catch-admin/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/JaguarJack/catch-admin" /></a>
|
||||
<a href="https://github.com/JaguarJack/catch-admin/network"><img alt="GitHub forks" src="https://img.shields.io/github/forks/JaguarJack/catch-admin" /></a>
|
||||
<a href="https://github.com/JaguarJack/catch-admin/blob/master/LICENSE.txt"><img alt="GitHub license" src="https://img.shields.io/github/license/JaguarJack/catch-admin" /></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-3 gap-1 mt-2">
|
||||
<el-card shadow="hover">
|
||||
<div class="text-center">易用</div>
|
||||
<div class="text-sm text-gray-400 pt-2">catchadmin 是从头开始设计的模块化框架,解耦化的设计让你轻松驾驭框架</div>
|
||||
</el-card>
|
||||
<el-card shadow="hover">
|
||||
<div class="text-center">专注</div>
|
||||
<div class="text-sm text-gray-400 pt-2">catchadmin 加入大量快速开发组件,让你专注于后台管理的开发,而无需重复无意义的工作</div>
|
||||
</el-card>
|
||||
<el-card shadow="hover">
|
||||
<div class="text-center">强大</div>
|
||||
<div class="text-sm text-gray-400 pt-2">catchadmin 基于 PHP 庞大的生态,使其稳定并且强大。使用 catchadmin 可以开发任意 web 应用</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
74
resources/admin/views/login/index.vue
Normal file
74
resources/admin/views/login/index.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<div class="bg-gray-50 h-screen flex items-center justify-center">
|
||||
<div class="flex w-full sm:w-[32rem] shadow bg-white lg:rounded-lg">
|
||||
<!--<div class="w-1/2 hidden sm:block">
|
||||
<img src="@/assets/login-left.png" />
|
||||
</div>-->
|
||||
<div class="w-full mx-auto pt-6 pb-6 pl-4 pr-4">
|
||||
<div class="flex mt-2">
|
||||
<img :src="logo" class="mx-auto w-8" />
|
||||
</div>
|
||||
<div class="w-full text-center text-2xl mt-6 mb-8 text-indigo-700">Hi, {{ $t('login.welcome') }}</div>
|
||||
<el-divider>{{ $t('login.sign_in') }}</el-divider>
|
||||
<div>
|
||||
<el-form
|
||||
ref="form"
|
||||
:model="params"
|
||||
status-icon
|
||||
v-loading.fullscreen.lock="loading"
|
||||
:rules="rules"
|
||||
element-loading-background="rgba(0, 0, 0, 0.7)"
|
||||
label-width="70px"
|
||||
class="w-11/12 sm:w-4/5 pt-2 space-y-8 mx-auto"
|
||||
>
|
||||
<el-form-item prop="email">
|
||||
<el-input v-model="params.email" type="email" autocomplete="off" :placeholder="$t('login.email')" size="large" :prefix-icon="Message" class="h-12 text-base" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
<el-input v-model="params.password" type="password" autocomplete="off" size="large" :placeholder="$t('login.password')" show-password :prefix-icon="Lock" class="h-12 text-base" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="flex justify-between w-11/12 sm:w-4/5 mx-auto mt-3">
|
||||
<el-checkbox v-model="params.remember" class="top-2">
|
||||
{{ $t('login.remember') }}
|
||||
</el-checkbox>
|
||||
<div class="text-sm pt-3 text-indigo-600 cursor-pointer">
|
||||
{{ $t('login.lost_password') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-11/12 sm:w-4/5 mx-auto mt-5">
|
||||
<el-button type="primary" @click="submit(form)" size="large" class="w-full text-xl">
|
||||
{{ $t('login.sign_in') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<div class="w-full text-center text-sm text-gray-400 mt-8 mb-10">{{ $t('system.name') }} @copyright 2018-{{ new Date().getFullYear() }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Lock, Message } from '@element-plus/icons-vue'
|
||||
import { onMounted } from 'vue'
|
||||
import { useLogin } from './login'
|
||||
import logo from '/admin/assets/logo.png'
|
||||
|
||||
const { params, loading, submit, form, rules } = useLogin()
|
||||
|
||||
// set default color-theme light
|
||||
onMounted(() => {
|
||||
document.querySelector('html')?.setAttribute('class', 'light')
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.el-form-item__content) {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
:deep(.el-divider__text) {
|
||||
@apply text-xl text-slate-400;
|
||||
}
|
||||
</style>
|
60
resources/admin/views/login/login.ts
Normal file
60
resources/admin/views/login/login.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { reactive, ref } from 'vue'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import { useUserStore } from '/admin/stores/modules/user'
|
||||
import router from '/admin/router'
|
||||
import { t } from '/admin/support/helper'
|
||||
|
||||
export const useLogin = () => {
|
||||
const params = reactive({
|
||||
email: '',
|
||||
password: '',
|
||||
remember: false,
|
||||
})
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
const rules = reactive({
|
||||
email: [
|
||||
{ required: true, message: t('login.verify.email.required'), trigger: 'blur' },
|
||||
{ type: 'email', message: t('login.verify.email.invalid'), trigger: 'blur' },
|
||||
],
|
||||
password: [{ required: true, message: t('login.verify.password.required'), trigger: 'blur' }],
|
||||
})
|
||||
|
||||
const form = ref<FormInstance>()
|
||||
|
||||
const submit = (loginForm: FormInstance | undefined) => {
|
||||
if (!loginForm) return
|
||||
|
||||
loginForm.validate(valid => {
|
||||
if (valid) {
|
||||
loading.value = true
|
||||
const store = useUserStore()
|
||||
|
||||
store
|
||||
.login(params)
|
||||
.then(() => {
|
||||
loading.value = false
|
||||
router.push({ path: '/' })
|
||||
})
|
||||
.catch(e => {
|
||||
loading.value = false
|
||||
})
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
params,
|
||||
|
||||
rules,
|
||||
|
||||
loading,
|
||||
|
||||
submit,
|
||||
|
||||
form,
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user