master
parent
9391743acc
commit
624344672b
|
@ -1,4 +1,11 @@
|
|||
import { createApp, css, html } from 'wkitd'
|
||||
/**
|
||||
* {}
|
||||
* @author yutent<yutent.io@gmail.com>
|
||||
* @date 2023/11/14 18:52:57
|
||||
*/
|
||||
|
||||
import { createApp } from 'wkitd'
|
||||
import { css, html } from 'wkit'
|
||||
|
||||
import 'es.shim'
|
||||
// import '//jscdn.ink/@bd/ui/latest/form/input.js'
|
||||
|
@ -15,6 +22,10 @@ import 'es.shim'
|
|||
|
||||
import router from './router.js'
|
||||
import store from './store.js'
|
||||
import fetch from '/lib/fetch.js'
|
||||
|
||||
import './components/header.js'
|
||||
import './components/footer.js'
|
||||
|
||||
const app = createApp({
|
||||
render() {
|
||||
|
@ -23,6 +34,39 @@ const app = createApp({
|
|||
<div class="main-body"><router-view></router-view></div>
|
||||
<wc-footer></wc-footer>
|
||||
`
|
||||
},
|
||||
|
||||
styles: css`
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
}
|
||||
.main-body {
|
||||
flex: 1;
|
||||
}
|
||||
`,
|
||||
|
||||
mounted() {
|
||||
var user = localStorage.getItem('user')
|
||||
var checked = sessionStorage.getItem('session_checked')
|
||||
|
||||
if (user) {
|
||||
if (checked) {
|
||||
return (this.$store.user = JSON.parse(user))
|
||||
}
|
||||
fetch('/login/check')
|
||||
.then(r => {
|
||||
localStorage.setItem('token', r.data.token)
|
||||
sessionStorage.setItem('session_checked', 1)
|
||||
this.$store.user = JSON.parse(user)
|
||||
})
|
||||
.catch(r => {
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('user')
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
<template>
|
||||
<Header :searchInput="$store.searchInput" />
|
||||
<div class="main-body"><router-view /></div>
|
||||
<Footer />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Header from './components/header.vue'
|
||||
import Footer from './components/footer.vue'
|
||||
|
||||
import fetch from '@/lib/fetch.js'
|
||||
|
||||
export default {
|
||||
components: { Header, Footer },
|
||||
|
||||
mounted() {
|
||||
var user = localStorage.getItem('user')
|
||||
var checked = sessionStorage.getItem('session_checked')
|
||||
|
||||
if (user) {
|
||||
if (checked) {
|
||||
return (this.$store.user = JSON.parse(user))
|
||||
}
|
||||
fetch('/login/check')
|
||||
.then(r => {
|
||||
localStorage.setItem('token', r.data.token)
|
||||
sessionStorage.setItem('session_checked', 1)
|
||||
this.$store.user = JSON.parse(user)
|
||||
})
|
||||
.catch(r => {
|
||||
localStorage.removeItem('token')
|
||||
localStorage.removeItem('user')
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
background: var(--color-plain-3);
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--color-dark-a);
|
||||
|
||||
&:hover {
|
||||
background: var(--color-dark-1);
|
||||
}
|
||||
}
|
||||
body {
|
||||
line-height: 1.5;
|
||||
font-size: 14px;
|
||||
color: var(--color-dark-1);
|
||||
}
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
.app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.main-body {
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,22 @@
|
|||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
background: var(--color-plain-3);
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--color-dark-a);
|
||||
|
||||
&:hover {
|
||||
background: var(--color-dark-1);
|
||||
}
|
||||
}
|
||||
body {
|
||||
line-height: 1.5;
|
||||
font-size: 14px;
|
||||
color: var(--color-dark-1);
|
||||
}
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import { html, css, Component } from 'wkit'
|
||||
|
||||
class Footer extends Component {
|
||||
static styles = css`
|
||||
.copyright {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 128px;
|
||||
background: var(--color-plain-1);
|
||||
color: var(--color-grey-2);
|
||||
|
||||
.link {
|
||||
margin-left: 6px;
|
||||
color: var(--color-blue-1);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<footer class="copyright">
|
||||
<span>©Copyright 2022 jscdn.ink Power by</span>
|
||||
<a class="link" target="_blank" href="https://git.wkit.fun/bytedo/wkitd"
|
||||
>wkitd</a
|
||||
>
|
||||
</footer>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
Footer.reg('footer')
|
|
@ -1,29 +0,0 @@
|
|||
<template>
|
||||
<footer class="copyright">
|
||||
<span>©Copyright 2022 jscdn.ink Power by</span>
|
||||
<a class="link" target="_blank" href="//github.com/bytedo/vue-live">vue-live</a>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.copyright {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 128px;
|
||||
background: var(--color-plain-1);
|
||||
color: var(--color-grey-2);
|
||||
|
||||
.link {
|
||||
margin-left: 6px;
|
||||
color: var(--color-blue-1);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,172 @@
|
|||
import { html, css, Component, classMap } from 'wkit'
|
||||
|
||||
import fetch from '/lib/fetch.js'
|
||||
|
||||
class Header extends Component {
|
||||
static props = {
|
||||
input: ''
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
.common-header {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 240px;
|
||||
background: var(--color-red-1);
|
||||
color: #fff;
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
width: 1024px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.navibar {
|
||||
height: 36px;
|
||||
margin-top: 24px;
|
||||
|
||||
.logo {
|
||||
font-weight: bold;
|
||||
font-size: 26px;
|
||||
|
||||
& img {
|
||||
display: block;
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.navi {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
|
||||
& router-link {
|
||||
margin: 0 16px;
|
||||
padding: 3px 6px;
|
||||
border-radius: 4px;
|
||||
transition: background 0.2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
&.router-link-active {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.banner {
|
||||
width: 640px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.search {
|
||||
display: none;
|
||||
width: 520px;
|
||||
color: #fff;
|
||||
--bg-color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
&.search-show {
|
||||
height: 320px;
|
||||
.search {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
&::after {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
font-size: 16px;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
content: '免费、快速、开放的 CDN 服务';
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 1024px) {
|
||||
.common-header {
|
||||
.navibar {
|
||||
width: 100%;
|
||||
padding: 0 32px;
|
||||
}
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
search() {
|
||||
let id = this.input.trim()
|
||||
if (id) {
|
||||
fetch('/package/search/' + encodeURIComponent(id)).then(r => {
|
||||
let dict = { versions: [], id }
|
||||
let last = null
|
||||
for (let it of r.data) {
|
||||
let tmp = it.split('/')
|
||||
let v = tmp.shift()
|
||||
let n = tmp.join('/')
|
||||
if (last === v) {
|
||||
dict[last].push(n)
|
||||
} else {
|
||||
last = v
|
||||
dict.versions.push(last)
|
||||
dict[last] = [n]
|
||||
}
|
||||
}
|
||||
this.$store.result = dict
|
||||
})
|
||||
} else {
|
||||
this.$store.result = null
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div
|
||||
class="common-header noselect"
|
||||
:class=${classMap({ 'search-show': this.$store.searchShow })}
|
||||
>
|
||||
<header class="navibar">
|
||||
<div class="wrapper">
|
||||
<a class="logo"><img src="/assets/logo.svg" /></a>
|
||||
|
||||
<nav class="navi">
|
||||
<router-link :to=${{ path: '/' }}>首 页</router-link>
|
||||
<router-link :to=${{ path: '/request' }}>收 录</router-link>
|
||||
<router-link :to=${{ path: '/about' }}>关 于</router-link>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<cite class="banner">
|
||||
<p>
|
||||
我们的目标是提供这样一个仓库,让它尽可能全面收录优秀的支持ESM访问的开源库,并免费为之提供
|
||||
CDN加速服务,使之有更好的访问速度和稳定的环境。
|
||||
</p>
|
||||
<p>同时我们也提供自主提交开源库的收录(前提是在npm上发布的)</p>
|
||||
</cite>
|
||||
|
||||
<wc-input
|
||||
class="search"
|
||||
no-border
|
||||
placeholder="请输入开源库的名字~~"
|
||||
clearable
|
||||
value=${this.input}
|
||||
@submit=${this.search}
|
||||
></wc-input>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
Header.reg('header')
|
|
@ -1,177 +0,0 @@
|
|||
<template>
|
||||
<div
|
||||
class="common-header noselect"
|
||||
:class="{ 'search-show': $store.searchShow }"
|
||||
>
|
||||
<header class="navibar">
|
||||
<div class="wrapper">
|
||||
<a class="logo"><img src="/assets/logo.svg" /></a>
|
||||
|
||||
<nav class="navi">
|
||||
<router-link to="/">首 页</router-link>
|
||||
<router-link to="/request">收 录</router-link>
|
||||
<router-link to="/about">关 于</router-link>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<cite class="banner">
|
||||
<p>
|
||||
我们的目标是提供这样一个仓库,让它尽可能全面收录优秀的支持ESM访问的开源库,并免费为之提供
|
||||
CDN加速服务,使之有更好的访问速度和稳定的环境。
|
||||
</p>
|
||||
<p>同时我们也提供自主提交开源库的收录(前提是在npm上发布的)</p>
|
||||
</cite>
|
||||
|
||||
<wc-input
|
||||
class="search"
|
||||
no-border
|
||||
placeholder="请输入开源库的名字~~"
|
||||
clearable
|
||||
v-model="input"
|
||||
@submit="search"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import fetch from '@/lib/fetch'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { input: '' }
|
||||
},
|
||||
|
||||
watch: {
|
||||
'$store.searchInput'(v) {
|
||||
this.input = v
|
||||
this.search()
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
search() {
|
||||
let id = this.input.trim()
|
||||
if (id) {
|
||||
fetch('/package/search/' + encodeURIComponent(id)).then(r => {
|
||||
let dict = { versions: [], id }
|
||||
let last = null
|
||||
for (let it of r.data) {
|
||||
let tmp = it.split('/')
|
||||
let v = tmp.shift()
|
||||
let n = tmp.join('/')
|
||||
if (last === v) {
|
||||
dict[last].push(n)
|
||||
} else {
|
||||
last = v
|
||||
dict.versions.push(last)
|
||||
dict[last] = [n]
|
||||
}
|
||||
}
|
||||
this.$store.result = dict
|
||||
})
|
||||
} else {
|
||||
this.$store.result = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.common-header {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 240px;
|
||||
background: var(--color-red-1);
|
||||
color: #fff;
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
width: 1024px;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.navibar {
|
||||
height: 36px;
|
||||
margin-top: 24px;
|
||||
|
||||
.logo {
|
||||
font-weight: bold;
|
||||
font-size: 26px;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.navi {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
|
||||
a {
|
||||
margin: 0 16px;
|
||||
padding: 3px 6px;
|
||||
border-radius: 4px;
|
||||
transition: background 0.2s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
&.router-link-active {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.banner {
|
||||
width: 640px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.search {
|
||||
display: none;
|
||||
width: 520px;
|
||||
color: #fff;
|
||||
--bg-color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
&.search-show {
|
||||
height: 320px;
|
||||
.search {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
&::after {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
font-size: 16px;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
content: '免费、快速、开放的 CDN 服务';
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 1024px) {
|
||||
.common-header {
|
||||
.navibar {
|
||||
width: 100%;
|
||||
padding: 0 32px;
|
||||
}
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -8,6 +8,7 @@
|
|||
<meta name="keywords" content="免费、快速、开放的 CDN 服务">
|
||||
<meta name="description" content="免费、快速、开放的 CDN 服务">
|
||||
<link rel="stylesheet" href="//jscdn.ink/@bd/ui/latest/css/reset-basic.css">
|
||||
<link rel="stylesheet" href="/assets/app.css">
|
||||
<script async src="//jscdn.ink/es-module-shims/1.6.3/es-module-shims.wasm.js"></script>
|
||||
<script type="importmap">{
|
||||
"imports":{
|
||||
|
|
|
@ -10,8 +10,7 @@ const router = createRouter({
|
|||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'wc-home',
|
||||
component: Home
|
||||
name: 'wc-home'
|
||||
},
|
||||
{
|
||||
path: '/about',
|
||||
|
|
|
@ -0,0 +1,390 @@
|
|||
import { html, css, Component } from 'wkit'
|
||||
|
||||
class Request extends Component {
|
||||
static styles = [
|
||||
css`
|
||||
.packages {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-top: 16px;
|
||||
|
||||
.toolbar,
|
||||
.list {
|
||||
width: 1024px;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 16px 0;
|
||||
|
||||
wc-input {
|
||||
width: 480px;
|
||||
}
|
||||
wc-link {
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.pager {
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.request-form {
|
||||
width: 640px;
|
||||
background: #fff;
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 48px;
|
||||
padding: 0 16px;
|
||||
font-size: 20px;
|
||||
color: var(--color-grey-3);
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 16px 16px 32px;
|
||||
|
||||
.field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 12px;
|
||||
|
||||
&.center {
|
||||
margin-top: 16px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.label {
|
||||
width: 120px;
|
||||
}
|
||||
wc-input,
|
||||
.value {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
]
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<main class="packages">
|
||||
<div class="toolbar">
|
||||
<wc-input
|
||||
v-model="filter"
|
||||
placeholder="请输入开源库的名字"
|
||||
@submit="search"
|
||||
/>
|
||||
|
||||
<wc-switch v-model="onlyShowWaited" @change="search"
|
||||
>只显示待审核</wc-switch
|
||||
>
|
||||
<wc-link type="info" @click="openDialog">
|
||||
没找到你想的库?点击申请收录
|
||||
</wc-link>
|
||||
</div>
|
||||
|
||||
<wc-table class="list" :thead="thead">
|
||||
<wc-tr v-for="it of list" :key="it.id">
|
||||
<wc-td align="center">
|
||||
<router-link :to="'/?name=' + it.id">{{ it.id }}</router-link>
|
||||
</wc-td>
|
||||
<wc-td align="center">{{ it.author }}</wc-td>
|
||||
<wc-td align="center">{{ it.latest || '-' }}</wc-td>
|
||||
<wc-td align="center">{{ it.latest ? it.sync_date : '-' }}</wc-td>
|
||||
<wc-td align="center">{{ $store.stats[it.stat] }}</wc-td>
|
||||
<wc-td>{{ it.remark || '-' }}</wc-td>
|
||||
<wc-td align="center">
|
||||
<wc-link
|
||||
v-if="it.stat === 2"
|
||||
:disabled="loading"
|
||||
@click="handlePackgae('sync', it.id)"
|
||||
type="info"
|
||||
>更新</wc-link
|
||||
>
|
||||
<wc-link
|
||||
v-if="$store.user.admin && it.stat !== 2"
|
||||
@click="handlePackgae('accept', it.id)"
|
||||
type="info"
|
||||
>通过</wc-link
|
||||
>
|
||||
<wc-link
|
||||
v-if="$store.user.admin && it.stat !== 0"
|
||||
@click="handlePackgae('reject', it.id)"
|
||||
type="warning"
|
||||
>拒绝</wc-link
|
||||
>
|
||||
<wc-link
|
||||
v-if="$store.user.admin && it.stat !== 0"
|
||||
@click="handlePackgae('delete', it.id)"
|
||||
type="danger"
|
||||
>删除</wc-link
|
||||
>
|
||||
</wc-td>
|
||||
</wc-tr>
|
||||
</wc-table>
|
||||
|
||||
<wc-pager
|
||||
class="pager"
|
||||
layout="prev,pages,next,info"
|
||||
red
|
||||
@page-changed="pageChanged"
|
||||
:total="total"
|
||||
:page="page"
|
||||
/>
|
||||
</main>
|
||||
|
||||
<wc-layer ref="form" mask mask-close>
|
||||
<div class="request-form">
|
||||
<header class="title">申请收录开源库</header>
|
||||
<content class="content">
|
||||
<section class="field">
|
||||
<span class="label">开源库名称:</span>
|
||||
<wc-input v-model="lib.name" @input="autoUpdateInfo" />
|
||||
</section>
|
||||
<section class="field">
|
||||
<span class="label">作者:</span>
|
||||
<span class="value">{{ lib.author }}</span>
|
||||
</section>
|
||||
<section class="field">
|
||||
<span class="label">简介:</span>
|
||||
<span class="value">{{ lib.description }}</span>
|
||||
</section>
|
||||
<section class="field">
|
||||
<span class="label">最新版本:</span>
|
||||
<span class="value">{{ lib.latest }}</span>
|
||||
</section>
|
||||
<section class="field center">
|
||||
<wc-button
|
||||
type="danger"
|
||||
:disabled="disabled"
|
||||
:loading="loading"
|
||||
@click="submit"
|
||||
>提交申请</wc-button
|
||||
>
|
||||
</section>
|
||||
</content>
|
||||
</div>
|
||||
</wc-layer>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
Request.reg('request')
|
||||
|
||||
import '//jscdn.ink/@bytedo/wcui/1.0.12/table/index.js'
|
||||
import fetch from '/lib/fetch.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
content: '这是关于我们页面',
|
||||
list: [],
|
||||
thead: JSON.stringify([
|
||||
'开源库',
|
||||
'作者',
|
||||
'最后同步版本',
|
||||
'最后同步日期',
|
||||
'收录状态',
|
||||
'备注',
|
||||
'操作'
|
||||
]),
|
||||
page: 1,
|
||||
total: 0,
|
||||
filter: '',
|
||||
onlyShowWaited: false,
|
||||
loading: false,
|
||||
disabled: true,
|
||||
lib: {
|
||||
name: '',
|
||||
author: '-',
|
||||
description: '-',
|
||||
latest: '-'
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$store.searchShow = false
|
||||
|
||||
this.fetchList()
|
||||
},
|
||||
methods: {
|
||||
fetchList() {
|
||||
fetch('/package/list').then(r => {
|
||||
this.$list = r.data.map(
|
||||
it => ((it.sync_date = new Date(it.sync_date).format('Y/m/d')), it)
|
||||
)
|
||||
this.fetchPage()
|
||||
this.total = this.$list.length
|
||||
})
|
||||
},
|
||||
|
||||
fetchPage() {
|
||||
let start = (this.page - 1) * 20
|
||||
let end = start + 20
|
||||
this.list = this.$list
|
||||
.filter(it => (this.onlyShowWaited ? it.stat === 1 : true))
|
||||
.slice(start, end)
|
||||
},
|
||||
|
||||
pageChanged(ev) {
|
||||
this.page = ev.data
|
||||
console.log('<><><>', this.page)
|
||||
this.fetchPage()
|
||||
},
|
||||
|
||||
search() {
|
||||
let filter = this.filter.trim()
|
||||
let onlyShowWaited = this.onlyShowWaited
|
||||
|
||||
if (filter) {
|
||||
this.list = this.$list.filter(
|
||||
it =>
|
||||
it.id.indexOf(filter) > -1 &&
|
||||
(onlyShowWaited ? it.stat === 1 : true)
|
||||
)
|
||||
} else {
|
||||
this.list = this.$list.filter(it =>
|
||||
onlyShowWaited ? it.stat === 1 : true
|
||||
)
|
||||
}
|
||||
this.total = this.list.length
|
||||
},
|
||||
|
||||
openDialog() {
|
||||
if (this.$store.user.id) {
|
||||
this.$refs.form.show()
|
||||
} else {
|
||||
layer.confirm('你还没有登录, 请先登录之后, 再申请').then(_ => {
|
||||
localStorage.setItem('login_callback_path', this.$route.path)
|
||||
this.$router.push('/login')
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
resetForm(force) {
|
||||
force && (this.lib.name = '')
|
||||
this.lib.author = '-'
|
||||
this.lib.description = '-'
|
||||
this.lib.latest = '-'
|
||||
this.disabled = true
|
||||
},
|
||||
|
||||
autoUpdateInfo() {
|
||||
let name = this.lib.name.trim()
|
||||
clearTimeout(this.$timer)
|
||||
if (name) {
|
||||
if (name.startsWith('@') && name.indexOf('/') === -1) {
|
||||
return
|
||||
}
|
||||
|
||||
this.$timer = setTimeout(_ => {
|
||||
this.getPackageInfo(name)
|
||||
}, 800)
|
||||
}
|
||||
},
|
||||
|
||||
getPackageInfo(name) {
|
||||
return fetch('https://registry.npmmirror.com/' + name)
|
||||
.then(r => {
|
||||
let author = r.author
|
||||
? r.author.name
|
||||
: r.maintainers
|
||||
? r.maintainers[0].name
|
||||
: 'unknow'
|
||||
|
||||
this.lib.author = author
|
||||
this.lib.description = r.description || r.homepage
|
||||
this.lib.latest = r['dist-tags'].latest
|
||||
|
||||
this.disabled = false
|
||||
return {
|
||||
author,
|
||||
description: this.lib.description,
|
||||
latest: r['dist-tags'].latest
|
||||
}
|
||||
})
|
||||
.catch(_ => {
|
||||
this.resetForm()
|
||||
layer.toast(
|
||||
`开源库【${name}】在npm上找不到, 请确认名称是否正确`,
|
||||
'error'
|
||||
)
|
||||
})
|
||||
},
|
||||
|
||||
uploadPackge(body) {
|
||||
fetch('/package/upload', { method: 'post', body })
|
||||
.then(r => {
|
||||
layer.toast('提交成功,等待审核', 'success')
|
||||
this.resetForm(true)
|
||||
this.fetchList()
|
||||
this.$refs.form.close()
|
||||
})
|
||||
.catch(e => {
|
||||
layer.toast(e.msg, 'error')
|
||||
})
|
||||
},
|
||||
|
||||
submit() {
|
||||
let name = this.lib.name.trim()
|
||||
if (name) {
|
||||
if (name.startsWith('@') && name.indexOf('/') === -1) {
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
this.getPackageInfo(name)
|
||||
.then(({ author, description, latest }) => {
|
||||
//
|
||||
this.uploadPackge({ name, author, description, latest })
|
||||
})
|
||||
|
||||
.finally(_ => (this.loading = false))
|
||||
} else {
|
||||
layer.toast(`请填写正确的名称`, 'warning')
|
||||
}
|
||||
},
|
||||
|
||||
handlePackgae(act, id) {
|
||||
if (act !== 'sync' && !this.$store.user.admin) {
|
||||
return layer.alert('别闹, 老实等管理员通过~~')
|
||||
}
|
||||
let req
|
||||
if (act === 'reject' || act === 'delete') {
|
||||
req = layer.prompt('请输入理由').then(remark => {
|
||||
return fetch(`/package/${act}/${encodeURIComponent(id)}`, {
|
||||
method: 'PUT',
|
||||
body: { remark }
|
||||
})
|
||||
})
|
||||
} else if (act === 'accept') {
|
||||
req = layer.prompt('请输入文件目录', 'dist').then(dist => {
|
||||
return fetch(`/package/${act}/${encodeURIComponent(id)}`, {
|
||||
method: 'PUT',
|
||||
body: { dist }
|
||||
})
|
||||
})
|
||||
} else {
|
||||
req = fetch(`/package/${act}/${encodeURIComponent(id)}`, {
|
||||
method: 'PUT'
|
||||
})
|
||||
}
|
||||
this.loading = true
|
||||
req
|
||||
.then(r => {
|
||||
layer.toast('操作成功', 'success')
|
||||
this.fetchList()
|
||||
})
|
||||
.catch(r => {
|
||||
r && layer.toast(r.msg, 'error')
|
||||
})
|
||||
.finally(_ => (this.loading = false))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
import { resolve } from 'path'
|
||||
|
||||
export default {
|
||||
devServer: {
|
||||
port: 8080,
|
||||
domain: '',
|
||||
https: false,
|
||||
ssl: {
|
||||
key: '',
|
||||
cert: ''
|
||||
// ca: ''
|
||||
}
|
||||
},
|
||||
pages: {
|
||||
// 如果多页应用, 则这里写传入多个值即可(注意不是数组格式)
|
||||
// 这里的key值, 将是最终的页面的名称
|
||||
index: {
|
||||
// 这里的resolve可将相对路径转为绝对路径
|
||||
// 如果传入的路径已经是绝对路径的, 可不需要resolve
|
||||
entry: resolve('./src/main.js'),
|
||||
title: '免费、快速、开放的 CDN 服务'
|
||||
}
|
||||
},
|
||||
// 以下cdn地址, 可自行修改为适合的
|
||||
// 有用到其他的库, 可以手动添加,
|
||||
// 也可以在页面中直接引入完整的路径, 而不必须在这里声明
|
||||
imports: {
|
||||
'es.shim': '//jscdn.ink/es.shim/2.1.0/index.js',
|
||||
fetch: '//jscdn.ink/@bytedo/fetch/latest/next.js',
|
||||
wkit: '//jscdn.ink/wkit/latest/index.js',
|
||||
wkitd: '//jscdn.ink/wkitd/latest/index.js',
|
||||
'@ui/': '/assets/lib/ui/'
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue