完成所有的重构
parent
624344672b
commit
d2ff91b761
|
@ -8,17 +8,12 @@ import { createApp } from 'wkitd'
|
||||||
import { css, html } from 'wkit'
|
import { css, html } from 'wkit'
|
||||||
|
|
||||||
import 'es.shim'
|
import 'es.shim'
|
||||||
// import '//jscdn.ink/@bd/ui/latest/form/input.js'
|
import '@ui/form/input.js'
|
||||||
// import '//jscdn.ink/@bd/ui/latest/form/button.js'
|
import '@ui/form/button.js'
|
||||||
// import '//jscdn.ink/@bd/ui/latest/form/checkbox.js'
|
import '@ui/form/switch.js'
|
||||||
// import '//jscdn.ink/@bd/ui/latest/form/switch.js'
|
import '@ui/form/link.js'
|
||||||
// import '//jscdn.ink/@bd/ui/latest/form/link.js'
|
import '@ui/layer/index.js'
|
||||||
// import '//jscdn.ink/@bd/ui/latest/layer/index.js'
|
import '@ui/pager/index.js'
|
||||||
// // import 'http://127.0.0.1:8090/dist/layer/index.js'
|
|
||||||
// import '//jscdn.ink/@bd/ui/latest/pager/index.js'
|
|
||||||
// import '//jscdn.ink/@bytedo/wcui/1.0.12/form/dropdown.js'
|
|
||||||
|
|
||||||
// import App from './app.vue'
|
|
||||||
|
|
||||||
import router from './router.js'
|
import router from './router.js'
|
||||||
import store from './store.js'
|
import store from './store.js'
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
background: var(--color-dark-1);
|
background: var(--color-dark-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { html, css, Component, classMap } from 'wkit'
|
import { html, css, Component, classMap } from 'wkit'
|
||||||
|
import { watch } from 'wkitd'
|
||||||
|
|
||||||
import fetch from '/lib/fetch.js'
|
import fetch from '/lib/fetch.js'
|
||||||
|
|
||||||
class Header extends Component {
|
class Header extends Component {
|
||||||
static props = {
|
|
||||||
input: ''
|
|
||||||
}
|
|
||||||
|
|
||||||
static styles = css`
|
static styles = css`
|
||||||
|
::selection {
|
||||||
|
background: var(--color-plain-a);
|
||||||
|
}
|
||||||
.common-header {
|
.common-header {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -51,13 +51,10 @@ class Header extends Component {
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
transition: background 0.2s ease-in-out;
|
transition: background 0.2s ease-in-out;
|
||||||
|
|
||||||
&:hover {
|
&:hover,
|
||||||
|
&.active {
|
||||||
background: rgba(255, 255, 255, 0.3);
|
background: rgba(255, 255, 255, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.router-link-active {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,6 +75,7 @@ class Header extends Component {
|
||||||
height: 320px;
|
height: 320px;
|
||||||
.search {
|
.search {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
--wc-input-border-color: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,10 +103,12 @@ class Header extends Component {
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
search() {
|
#search(ev) {
|
||||||
let id = this.input.trim()
|
let id = this.$store.searchInput
|
||||||
|
|
||||||
if (id) {
|
if (id) {
|
||||||
fetch('/package/search/' + encodeURIComponent(id)).then(r => {
|
fetch('/package/search/' + encodeURIComponent(id))
|
||||||
|
.then(r => {
|
||||||
let dict = { versions: [], id }
|
let dict = { versions: [], id }
|
||||||
let last = null
|
let last = null
|
||||||
for (let it of r.data) {
|
for (let it of r.data) {
|
||||||
|
@ -123,18 +123,39 @@ class Header extends Component {
|
||||||
dict[last] = [n]
|
dict[last] = [n]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dict.version = last
|
||||||
this.$store.result = dict
|
this.$store.result = dict
|
||||||
})
|
})
|
||||||
|
.catch(err => {
|
||||||
|
this.$store.result = { version: '', versions: [], id: '' }
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
this.$store.result = null
|
this.$store.result = { version: '', versions: [], id: '' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#handleInput(ev) {
|
||||||
|
this.$store.searchInput = ev.target.value
|
||||||
|
}
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
watch('$store.searchInput', val => {
|
||||||
|
this.#search()
|
||||||
|
})
|
||||||
|
watch('$route', route => {
|
||||||
|
if (route.path === '/' && !route.query.name) {
|
||||||
|
this.$store.searchInput = ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html`
|
return html`
|
||||||
<div
|
<div
|
||||||
class="common-header noselect"
|
class=${classMap({
|
||||||
:class=${classMap({ 'search-show': this.$store.searchShow })}
|
'common-header': true,
|
||||||
|
'search-show': this.$store.searchShow
|
||||||
|
})}
|
||||||
>
|
>
|
||||||
<header class="navibar">
|
<header class="navibar">
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
|
@ -161,8 +182,9 @@ class Header extends Component {
|
||||||
no-border
|
no-border
|
||||||
placeholder="请输入开源库的名字~~"
|
placeholder="请输入开源库的名字~~"
|
||||||
clearable
|
clearable
|
||||||
value=${this.input}
|
value=${this.$store.searchInput}
|
||||||
@submit=${this.search}
|
@submit=${this.#handleInput}
|
||||||
|
@change=${this.#handleInput}
|
||||||
></wc-input>
|
></wc-input>
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
|
|
|
@ -15,8 +15,10 @@
|
||||||
"es.shim": "//jscdn.ink/es.shim/2.1.0/index.js",
|
"es.shim": "//jscdn.ink/es.shim/2.1.0/index.js",
|
||||||
"fetch": "//jscdn.ink/@bytedo/fetch/latest/next.js",
|
"fetch": "//jscdn.ink/@bytedo/fetch/latest/next.js",
|
||||||
"wkit": "//jscdn.ink/wkit/latest/index.js",
|
"wkit": "//jscdn.ink/wkit/latest/index.js",
|
||||||
|
"wkit2": "http://127.0.0.1:9999/src/index.js",
|
||||||
"wkitd": "//jscdn.ink/wkitd/latest/index.js",
|
"wkitd": "//jscdn.ink/wkitd/latest/index.js",
|
||||||
"@ui/": "/assets/lib/ui/"
|
"wkitd2": "http://127.0.0.1:23333/src/index.js",
|
||||||
|
"@ui/": "/lib/ui/"
|
||||||
}
|
}
|
||||||
}</script>
|
}</script>
|
||||||
<script type="module" src="/app.js"></script>
|
<script type="module" src="/app.js"></script>
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -18,12 +18,12 @@ import{css as c,html as n,Component as p}from"wkit";import"../form/button.js";co
|
||||||
disabled=${a}
|
disabled=${a}
|
||||||
class="item"
|
class="item"
|
||||||
icon="right"
|
icon="right"
|
||||||
></wc-button>`,curr:a=>n`<span class="curr item">${a}</span>`,info:(a,e)=>n`<span class="item">共 ${a}条, ${e}页</span>`,jump(a){return n`<section class="item jump">
|
></wc-button>`,curr:a=>n`<span class="curr item">${a}</span>`,info:(a,t)=>n`<span class="item">共 ${a}条, ${t}页</span>`,jump(a){return n`<section class="item jump">
|
||||||
<span>Go to</span>
|
<span>Go to</span>
|
||||||
<input ref="input" @keydown=${this.__gotoPage} maxlength="6" value=${a} />
|
<input ref="input" @keydown=${this.__gotoPage} maxlength="6" value=${a} />
|
||||||
</section>`}};function u(a,e){let i=[],o=0,s=a<3?6-a:2;if(e<2)return i.push({to:a,txt:a}),i;if(a-s>1&&e>5){let t=a-2*s;t=t<1?1:t,i.push({to:t,txt:"..."})}e-a<s&&(o=s-e+a);for(let t=a-s-o;t<a+s+1&&t<=e;t++)t>0&&i.push({to:t,txt:t});if(a+s<e){let t=a+2*s;t=t>e?e:t,i.push({to:t,txt:"..."})}return i}class h extends p{static props={layout:"str!home, prev, pages, next, end",total:{type:Number,default:0,attribute:!1,observer(e){this.totalpage=Math.ceil(e/this.pagesize)}},totalpage:{type:Number,default:1,attribute:!1,observer(e){this.page>e&&(this.page=e)}},page:{type:Number,default:1,attribute:!1,observer(e){e>this.totalpage?this.page=this.totalpage:e<1&&(this.page=1)}},pagesize:{type:Number,default:20,attribute:!1,observer(e){this.total>0&&(this.totalpage=Math.ceil(this.total/e))}}};static styles=[c`:host{display:block;line-height:1;font-size:14px;user-select:none;-moz-user-select:none;color:var(--color-dark-1)}:host .layout{display:flex;justify-content:center;align-items:center;margin:10px auto;--wc-button-icon-size: 10px;--wc-button-border-color: none;--wc-button-background: var(--color-plain-1);--wc-button-color-hover: var(--color-teal-1)}:host .item{min-width:32px;width:auto;margin:0 5px;border-radius:3px}:host .item.curr{display:inline-flex;align-items:center;justify-content:center;height:32px;background:var(--color-teal-1);color:#fff}:host .item.jump{display:flex;align-items:center}:host input{width:48px;height:24px;padding:0 4px;margin-left:4px;border:1px solid var(--color-grey-2);border-radius:3px;text-align:center;outline:none;transition:box-shadow .15s linear}:host input:focus{box-shadow:0 0 0 2px var(--color-plain-a)}`,c``];#t(e){let i=e.target;if(i.tagName==="WC-BUTTON"){let{page:o,totalpage:s}=this,t=i.dataset.act;if(i.disabled)return;switch(t){case"prev":t=o-1;break;case"next":console.log(t,o),t=o+1;break;case"end":t=s;break}if(+t===o)return;this.page=t,this.$refs.input&&(this.$refs.input.value=t),this.$emit("page-change",{data:t})}}__gotoPage(e){if(e.keyCode===13){let i=+e.target.value;i===i&&(this.page=i,this.$emit("page-change",{data:i})),e.target.value=this.page}}render(){let e=this.layout.split(",").map(t=>t.trim()),{page:i,total:o,totalpage:s}=this;return n`
|
</section>`}};function u(a,t){let i=[],o=0,s=a<3?6-a:2;if(t<2)return i.push({to:a,txt:a}),i;if(a-s>1&&t>5){let e=a-2*s;e=e<1?1:e,i.push({to:e,txt:"..."})}t-a<s&&(o=s-t+a);for(let e=a-s-o;e<a+s+1&&e<=t;e++)e>0&&i.push({to:e,txt:e});if(a+s<t){let e=a+2*s;e=e>t?t:e,i.push({to:e,txt:"..."})}return i}class h extends p{static props={layout:"str!home, prev, pages, next, end",total:{type:Number,default:0,attribute:!1,observer(t){this.totalpage=Math.ceil(t/this.pagesize)||1}},totalpage:{type:Number,default:1,attribute:!1,observer(t){t<1&&(t=1),this.page>t&&(this.page=t)}},page:{type:Number,default:1,attribute:!1,observer(t){t>this.totalpage?this.page=this.totalpage:t<1&&(this.page=1)}},pagesize:{type:Number,default:20,attribute:!1,observer(t){this.total>0&&(this.totalpage=Math.ceil(this.total/t))}}};static styles=[c`:host{display:block;line-height:1;font-size:14px;user-select:none;-moz-user-select:none;color:var(--color-dark-1)}:host .layout{display:flex;justify-content:center;align-items:center;margin:10px auto;--wc-button-icon-size: 10px;--wc-button-border-color: none;--wc-button-background: var(--color-plain-1);--wc-button-color-hover: var(--color-teal-1)}:host .item{min-width:32px;width:auto;margin:0 5px;border-radius:3px}:host .item.curr{display:inline-flex;align-items:center;justify-content:center;height:32px;background:var(--color-teal-1);color:#fff}:host .item.jump{display:flex;align-items:center}:host input{width:48px;height:24px;padding:0 4px;margin-left:4px;border:1px solid var(--color-grey-2);border-radius:3px;text-align:center;outline:none;transition:box-shadow .15s linear}:host input:focus{box-shadow:0 0 0 2px var(--color-plain-a)}`,c``];#t(t){let i=t.target;if(i.tagName==="WC-BUTTON"){let{page:o,totalpage:s}=this,e=i.dataset.act;if(i.disabled)return;switch(e){case"prev":e=o-1;break;case"next":console.log(e,o),e=o+1;break;case"end":e=s;break}if(+e===o)return;this.page=e,this.$refs.input&&(this.$refs.input.value=e),this.$emit("page-change",{data:e})}}__gotoPage(t){if(t.keyCode===13){let i=+t.target.value;i===i&&(this.page=i,this.$emit("page-change",{data:i})),t.target.value=this.page}}render(){let t=this.layout.split(",").map(e=>e.trim()),{page:i,total:o,totalpage:s}=this;return n`
|
||||||
<div class="layout" @click=${this.#t}>
|
<div class="layout" @click=${this.#t}>
|
||||||
${e.map(t=>{switch(t){case"pages":return u(i,s).map(l=>i===l.to?r.curr(i):n`<wc-button class="item" data-act="${l.to}"
|
${t.map(e=>{switch(e){case"pages":return u(i,s).map(l=>i===l.to?r.curr(i):n`<wc-button class="item" data-act="${l.to}"
|
||||||
>${l.txt}</wc-button
|
>${l.txt}</wc-button
|
||||||
>`);case"home":return r.home(i===1);case"prev":return r.prev(i===1);case"next":return r.next(i>=s);case"end":return r.end(i>=s);case"curr":return r.curr(i);case"info":return r.info(o,s);case"jump":return r.jump.call(this,i);default:return""}})}
|
>`);case"home":return r.home(i===1);case"prev":return r.prev(i===1);case"next":return r.next(i>=s);case"end":return r.end(i>=s);case"curr":return r.curr(i);case"info":return r.info(o,s);case"jump":return r.jump.call(this,i);default:return""}})}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,5 +8,6 @@ export default createStore({
|
||||||
2: '✅正常',
|
2: '✅正常',
|
||||||
9: '🙅🏻拒绝收录'
|
9: '🙅🏻拒绝收录'
|
||||||
},
|
},
|
||||||
result: null // 搜索结果
|
searchInput: '',
|
||||||
|
result: { version: '', versions: [], id: '' } // 搜索结果
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
import { html, css, Component } from 'wkit'
|
||||||
|
|
||||||
|
class About extends Component {
|
||||||
|
static styles = css`
|
||||||
|
::selection {
|
||||||
|
background: var(--color-plain-a);
|
||||||
|
}
|
||||||
|
.about-page {
|
||||||
|
width: 1024px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
& dl {
|
||||||
|
font-size: 16px;
|
||||||
|
|
||||||
|
& dt {
|
||||||
|
margin-top: 32px;
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--color-grey-3);
|
||||||
|
}
|
||||||
|
& dd {
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& p {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
& a {
|
||||||
|
color: var(--color-red-1);
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
mounted() {
|
||||||
|
this.$store.searchShow = false
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return html`
|
||||||
|
<main class="about-page">
|
||||||
|
<dl>
|
||||||
|
<dt>一、背景和目标</dt>
|
||||||
|
<dd>
|
||||||
|
<p>国内免费的几个js cdn加速站, 要么收录太少, 要么已经不维护。</p>
|
||||||
|
<p>
|
||||||
|
我们的目标是提供这样一个仓库,让它尽可能全面收录优秀的支持ESM访问的开源库,并免费为之提供
|
||||||
|
CDN加速服务,使之有更好的访问速度和稳定的环境。
|
||||||
|
</p>
|
||||||
|
<p>同时我们也提供自主提交开源库的收录(前提是在npm上发布的)</p>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>二、更新开源库</dt>
|
||||||
|
<dd>
|
||||||
|
<p>
|
||||||
|
理论上, 程序会自动更新开源库, 目前更新周期为1个星期,
|
||||||
|
如果你有需要使用新版而我们还未更新, 可以来手动同步。
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
原则上我们不会删除旧版本(如发现该开源库包含无用的大文件如图片,
|
||||||
|
音视频及其他附件时, 则会清除所有的旧版本, 只保留最新的一份,
|
||||||
|
严重时直接下架该库)。
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>三、收录事项</dt>
|
||||||
|
<dd>
|
||||||
|
<p>
|
||||||
|
开源库未发布到npm上时,
|
||||||
|
我们原则上不会收录(如有特殊且合理原因未提交到npm又想收录的,
|
||||||
|
可在意见反馈处提交相关信息)。
|
||||||
|
</p>
|
||||||
|
<p>原则上我们只收录支持esm方式访问的开源库。</p>
|
||||||
|
</dd>
|
||||||
|
|
||||||
|
<dt>四、维护者</dt>
|
||||||
|
<dd>
|
||||||
|
<p><a href="//github.com/yutent" target="_blank">yutent</a></p>
|
||||||
|
<p>
|
||||||
|
<a target="_blank" href="//git.wkit.fun/bytedo/jscdn.ink/issues"
|
||||||
|
>建议和反馈</a
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
<p>项目托管于阿里云oss。</p>
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
</main>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
About.reg('about')
|
|
@ -1,87 +0,0 @@
|
||||||
<template>
|
|
||||||
<main class="about-page">
|
|
||||||
<dl>
|
|
||||||
<dt>一、背景和目标</dt>
|
|
||||||
<dd>
|
|
||||||
<p>国内免费的几个js cdn加速站, 要么收录太少, 要么已经不维护。</p>
|
|
||||||
<p>
|
|
||||||
我们的目标是提供这样一个仓库,让它尽可能全面收录优秀的支持ESM访问的开源库,并免费为之提供
|
|
||||||
CDN加速服务,使之有更好的访问速度和稳定的环境。
|
|
||||||
</p>
|
|
||||||
<p>同时我们也提供自主提交开源库的收录(前提是在npm上发布的)</p>
|
|
||||||
</dd>
|
|
||||||
|
|
||||||
<dt>二、更新开源库</dt>
|
|
||||||
<dd>
|
|
||||||
<p>
|
|
||||||
理论上, 程序会自动更新开源库, 目前更新周期为1个星期, 如果你有需要使用新版而我们还未更新,
|
|
||||||
可以来手动同步。
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
原则上我们不会删除旧版本(如发现该开源库包含无用的大文件如图片, 音视频及其他附件时,
|
|
||||||
则会清除所有的旧版本, 只保留最新的一份, 严重时直接下架该库)。
|
|
||||||
</p>
|
|
||||||
</dd>
|
|
||||||
|
|
||||||
<dt>三、收录事项</dt>
|
|
||||||
<dd>
|
|
||||||
<p>
|
|
||||||
开源库未发布到npm上时, 我们原则上不会收录(如有特殊且合理原因未提交到npm又想收录的,
|
|
||||||
可在意见反馈处提交相关信息)。
|
|
||||||
</p>
|
|
||||||
<p>原则上我们只收录支持esm方式访问的开源库。</p>
|
|
||||||
</dd>
|
|
||||||
|
|
||||||
<dt>四、维护者</dt>
|
|
||||||
<dd>
|
|
||||||
<p><a href="//github.com/yutent" target="_blank">yutent</a></p>
|
|
||||||
<p><a target="_blank" href="//github.com/bytedo/jscdn.ink/issues">建议和反馈</a></p>
|
|
||||||
<p>项目托管于阿里云oss。</p>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
</main>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
content: '这是关于我们页面'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.$store.searchShow = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.about-page {
|
|
||||||
width: 1024px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 16px;
|
|
||||||
|
|
||||||
dl {
|
|
||||||
font-size: 16px;
|
|
||||||
|
|
||||||
dt {
|
|
||||||
margin-top: 32px;
|
|
||||||
font-size: 22px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: var(--color-grey-3);
|
|
||||||
}
|
|
||||||
dd {
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin-top: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--color-red-1);
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
import { html, css, Component } from 'wkit'
|
||||||
|
|
||||||
|
class Home extends Component {
|
||||||
|
static styles = css`
|
||||||
|
.home {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 16px 0 32px;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
.card {
|
||||||
|
width: 1024px;
|
||||||
|
margin-top: 24px;
|
||||||
|
border: 1px solid var(--color-plain-2);
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 12px 16px;
|
||||||
|
font-size: 22px;
|
||||||
|
background: var(--color-plain-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.select {
|
||||||
|
position: relative;
|
||||||
|
display: inline-flex;
|
||||||
|
margin: 0 15px;
|
||||||
|
border: 1px solid var(--color-grey-2);
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
& select {
|
||||||
|
appearance: none;
|
||||||
|
width: 113px;
|
||||||
|
height: 24px;
|
||||||
|
padding: 0 6px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: inherit;
|
||||||
|
font: inherit;
|
||||||
|
font-size: 12px;
|
||||||
|
background: #fff;
|
||||||
|
color: inherit;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trigon {
|
||||||
|
position: absolute;
|
||||||
|
right: 8px;
|
||||||
|
top: 8px;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border: 1px solid var(--color-grey-2);
|
||||||
|
border-top: 0;
|
||||||
|
border-right: 0;
|
||||||
|
content: '';
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
& option {
|
||||||
|
appearance: none;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
padding: 16px 8px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
display: block;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: background 0.1s ease;
|
||||||
|
|
||||||
|
& b {
|
||||||
|
color: var(--color-teal-1);
|
||||||
|
}
|
||||||
|
& i {
|
||||||
|
color: var(--color-blue-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--color-plain-1);
|
||||||
|
}
|
||||||
|
&:active {
|
||||||
|
background: var(--color-plain-a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
#libs = [
|
||||||
|
{
|
||||||
|
name: 'wkit',
|
||||||
|
version: '1.10.11',
|
||||||
|
files: ['index.es6.js', 'index.js']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'wkitd',
|
||||||
|
version: '1.3.0',
|
||||||
|
files: ['index.es6.js', 'index.js']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
#copy(ev) {
|
||||||
|
let elem = ev.target
|
||||||
|
if (elem.tagName === 'CODE' || elem.parentNode.tagName === 'CODE') {
|
||||||
|
if (elem.parentNode.tagName === 'CODE') {
|
||||||
|
elem = elem.parentNode
|
||||||
|
}
|
||||||
|
navigator.clipboard.writeText(elem.textContent.trim())
|
||||||
|
layer.toast('复制成功', 'success')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#versionChanged(ev) {
|
||||||
|
this.$store.result.version = ev.target.value
|
||||||
|
}
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
let route = this.$route
|
||||||
|
this.$store.searchShow = true
|
||||||
|
if (route.query.name) {
|
||||||
|
this.$store.searchInput = route.query.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let { result, searchInput } = this.$store
|
||||||
|
let { version, versions } = result
|
||||||
|
let list = result[version]
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<main class="home" @click=${this.#copy}>
|
||||||
|
${searchInput
|
||||||
|
? html`
|
||||||
|
<dl class="card noselect">
|
||||||
|
<dt class="title">
|
||||||
|
${result.id || searchInput} -
|
||||||
|
<section
|
||||||
|
class="select"
|
||||||
|
style=${versions.length < 1 ? 'display:none' : ''}
|
||||||
|
>
|
||||||
|
<select @change=${this.#versionChanged}>
|
||||||
|
${versions.map(
|
||||||
|
v =>
|
||||||
|
html`<option value=${v} :selected=${v === version}>
|
||||||
|
${v}
|
||||||
|
</option>`
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
<i class="trigon"></i>
|
||||||
|
</section>
|
||||||
|
</dt>
|
||||||
|
<dd class="list">
|
||||||
|
${list
|
||||||
|
? list.map(
|
||||||
|
f => html`
|
||||||
|
<code class="link">
|
||||||
|
//jscdn.ink/<b>${result.id}</b>/<i>${version}</i>/${f}
|
||||||
|
</code>
|
||||||
|
`
|
||||||
|
)
|
||||||
|
: '没有你要找的库'}
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
`
|
||||||
|
: this.#libs.map(
|
||||||
|
it => html`
|
||||||
|
<dl class="card noselect">
|
||||||
|
<dt class="title">${it.name} - v${it.version}</dt>
|
||||||
|
<dd class="list">
|
||||||
|
${it.files.map(
|
||||||
|
f => html`
|
||||||
|
<code class="link">
|
||||||
|
//jscdn.ink/<b>${it.name}</b>/<i>${it.version}</i>/${f}
|
||||||
|
</code>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</main>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Home.reg('home')
|
|
@ -1,151 +0,0 @@
|
||||||
<template>
|
|
||||||
<main class="home" @click="copy">
|
|
||||||
<dl class="card noselect" v-if="version">
|
|
||||||
<dt class="title">
|
|
||||||
{{ $store.result.id }} -
|
|
||||||
<wc-dropdown v-model="version">
|
|
||||||
<wc-option
|
|
||||||
v-for="v in $store.result.versions"
|
|
||||||
:key="v"
|
|
||||||
:value="v"
|
|
||||||
:label="v"
|
|
||||||
/>
|
|
||||||
</wc-dropdown>
|
|
||||||
</dt>
|
|
||||||
<dd class="list">
|
|
||||||
<section class="link" v-for="f in $store.result[version]">
|
|
||||||
//jscdn.ink/<b>{{ $store.result.id }}</b
|
|
||||||
>/<i>{{ version }}</i
|
|
||||||
>/<q>{{ f }}</q>
|
|
||||||
</section>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<dl class="card noselect" v-else v-for="it in libs" :key="it.name">
|
|
||||||
<dt class="title">{{ it.name }} - v{{ it.version }}</dt>
|
|
||||||
<dd class="list">
|
|
||||||
<section class="link" v-for="f in it.files">
|
|
||||||
//jscdn.ink/<b>{{ it.name }}</b
|
|
||||||
>/<i>{{ it.version }}</i
|
|
||||||
>/<q>{{ f }}</q>
|
|
||||||
</section>
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
</main>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
libs: [
|
|
||||||
{
|
|
||||||
name: 'vue',
|
|
||||||
version: '3.2.47',
|
|
||||||
files: [
|
|
||||||
'vue.cjs.js',
|
|
||||||
'vue.cjs.prod.js',
|
|
||||||
'vue.esm-browser.js',
|
|
||||||
'vue.esm-browser.prod.js',
|
|
||||||
'vue.esm-bundler.js',
|
|
||||||
'vue.global.js',
|
|
||||||
'vue.global.prod.js',
|
|
||||||
'vue.runtime.esm-browser.js',
|
|
||||||
'vue.runtime.esm-browser.prod.js',
|
|
||||||
'vue.runtime.esm-bundler.js',
|
|
||||||
'vue.runtime.global.js',
|
|
||||||
'vue.runtime.global.prod.js'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '@bytedo/fetch',
|
|
||||||
version: '2.1.1',
|
|
||||||
files: ['index.js', 'next.js']
|
|
||||||
}
|
|
||||||
],
|
|
||||||
version: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
watch: {
|
|
||||||
'$store.result'(val) {
|
|
||||||
if (val) {
|
|
||||||
this.version = val.versions[val.versions.length - 1]
|
|
||||||
} else {
|
|
||||||
this.version = ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
this.$store.searchShow = true
|
|
||||||
if (this.$route.query.name) {
|
|
||||||
this.$store.searchInput = this.$route.query.name
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
copy(ev) {
|
|
||||||
let elem = ev.target
|
|
||||||
if (elem.tagName === 'SECTION' || elem.parentNode.tagName === 'SECTION') {
|
|
||||||
if (elem.parentNode.tagName === 'SECTION') {
|
|
||||||
elem = elem.parentNode
|
|
||||||
}
|
|
||||||
navigator.clipboard.writeText(elem.textContent.trim())
|
|
||||||
layer.toast('复制成功', 'success')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.home {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
padding: 16px 0 32px;
|
|
||||||
|
|
||||||
.card {
|
|
||||||
width: 1024px;
|
|
||||||
margin-top: 24px;
|
|
||||||
box-shadow: 0 3px 12px rgba(0, 0, 0, 0.1);
|
|
||||||
|
|
||||||
.title {
|
|
||||||
padding: 16px;
|
|
||||||
font-size: 26px;
|
|
||||||
background: var(--color-plain-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.list {
|
|
||||||
padding: 16px;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.link {
|
|
||||||
padding: 0 6px;
|
|
||||||
border-radius: 4px;
|
|
||||||
transition: background 0.1s ease;
|
|
||||||
|
|
||||||
b,
|
|
||||||
i,
|
|
||||||
q {
|
|
||||||
padding: 0 2px;
|
|
||||||
}
|
|
||||||
b {
|
|
||||||
color: var(--color-teal-1);
|
|
||||||
}
|
|
||||||
i {
|
|
||||||
color: var(--color-blue-1);
|
|
||||||
}
|
|
||||||
q {
|
|
||||||
}
|
|
||||||
&:hover {
|
|
||||||
background: var(--color-plain-1);
|
|
||||||
}
|
|
||||||
&:active {
|
|
||||||
background: var(--color-plain-a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -0,0 +1,178 @@
|
||||||
|
import { html, css, Component } from 'wkit'
|
||||||
|
import fetch from '/lib/fetch.js'
|
||||||
|
|
||||||
|
class Login extends Component {
|
||||||
|
static styles = css`
|
||||||
|
.login-page {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
width: 1024px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 16px;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
.login-form,
|
||||||
|
.user-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 320px;
|
||||||
|
min-height: 160px;
|
||||||
|
padding: 32px;
|
||||||
|
margin-top: 32px;
|
||||||
|
box-shadow: 0 0 12px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form {
|
||||||
|
.title {
|
||||||
|
margin-bottom: 32px;
|
||||||
|
line-height: 2;
|
||||||
|
border-bottom: 1px solid var(--color-plain-2);
|
||||||
|
font-size: 20px;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--color-grey-3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.third-part {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
& a {
|
||||||
|
display: inline-flex;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin: 0 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-card {
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 96px;
|
||||||
|
height: 96px;
|
||||||
|
border: 3px solid var(--color-plain-1);
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 0 16px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
line-height: 2;
|
||||||
|
}
|
||||||
|
.homepage {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
--wc-icon-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
|
||||||
|
& a {
|
||||||
|
margin-left: 6px;
|
||||||
|
text-decoration: underline;
|
||||||
|
color: var(--color-blue-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout {
|
||||||
|
margin-top: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
#jumpLogin(site = 'github') {
|
||||||
|
switch (site) {
|
||||||
|
case 'github':
|
||||||
|
location.replace(
|
||||||
|
'https://github.com/login/oauth/authorize?' +
|
||||||
|
`client_id=57d9d247bda6302fd9d1&redirect_uri=https://www.jscdn.ink/login`
|
||||||
|
)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#logout() {
|
||||||
|
this.$store.user = {}
|
||||||
|
localStorage.removeItem('user')
|
||||||
|
localStorage.removeItem('token')
|
||||||
|
}
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
let route = this.$route
|
||||||
|
this.$store.searchShow = false
|
||||||
|
|
||||||
|
if (route.query.code) {
|
||||||
|
fetch('/login/github', {
|
||||||
|
method: 'post',
|
||||||
|
body: {
|
||||||
|
code: route.query.code
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(r => {
|
||||||
|
let lastPath = localStorage.getItem('login_callback_path')
|
||||||
|
layer.toast('登录成功', 'success')
|
||||||
|
this.$store.user = r.data.user
|
||||||
|
localStorage.setItem('user', JSON.stringify(r.data.user))
|
||||||
|
localStorage.setItem('token', r.data.token)
|
||||||
|
if (lastPath) {
|
||||||
|
localStorage.removeItem('login_callback_path')
|
||||||
|
this.$router.replace(lastPath)
|
||||||
|
} else {
|
||||||
|
this.$router.replace('/login')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(r => {
|
||||||
|
console.log(r)
|
||||||
|
layer.toast(r.msg, 'error')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return html`
|
||||||
|
<main class="login-page">
|
||||||
|
${this.$store.user.id
|
||||||
|
? html`
|
||||||
|
<div class="user-card">
|
||||||
|
<img class="avatar" :src=${this.$store.user.avatar} />
|
||||||
|
<h3 class="name">${this.$store.user.name}</h3>
|
||||||
|
<cite class="homepage">
|
||||||
|
<wc-icon name="home"></wc-icon>主页:
|
||||||
|
<a target="_blank" :href=${this.$store.user.homepage}
|
||||||
|
>${this.$store.user.homepage}</a
|
||||||
|
>
|
||||||
|
</cite>
|
||||||
|
<wc-button type="danger" class="logout" @click=${this.#logout}
|
||||||
|
>注销登录</wc-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
: html`
|
||||||
|
<div class="login-form">
|
||||||
|
<section class="title">请使用以下方式登录</section>
|
||||||
|
<section class="third-part">
|
||||||
|
<a
|
||||||
|
class="github"
|
||||||
|
title="github"
|
||||||
|
@click=${_ => this.#jumpLogin('github')}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="ico"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
fill="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 01-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 010 8c0-4.42 3.58-8 8-8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a title="wait...">...</a>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
`}
|
||||||
|
</main>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Login.reg('login')
|
|
@ -1,169 +0,0 @@
|
||||||
<template>
|
|
||||||
<main class="login-page">
|
|
||||||
<div class="user-card" v-if="$store.user.id">
|
|
||||||
<img class="avatar" :src="$store.user.avatar" />
|
|
||||||
<h3 class="name">{{ $store.user.name }}</h3>
|
|
||||||
<cite class="homepage">
|
|
||||||
<wc-icon is="home" />主页:
|
|
||||||
<a target="_blank" :href="$store.user.homepage">{{
|
|
||||||
$store.user.homepage
|
|
||||||
}}</a>
|
|
||||||
</cite>
|
|
||||||
<wc-button class="logout" @click="logout">注销登录</wc-button>
|
|
||||||
</div>
|
|
||||||
<div class="login-form" v-else>
|
|
||||||
<section class="title">请使用以下方式登录</section>
|
|
||||||
<section class="third-part">
|
|
||||||
<a class="github" title="github" @click="jumpLogin()">
|
|
||||||
<svg
|
|
||||||
class="ico"
|
|
||||||
viewBox="0 0 16 16"
|
|
||||||
width="32"
|
|
||||||
height="32"
|
|
||||||
fill="currentColor"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 01-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 010 8c0-4.42 3.58-8 8-8z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
<a title="wait...">...</a>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import fetch from '@/lib/fetch'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
content: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.$store.searchShow = false
|
|
||||||
|
|
||||||
if (this.$route.query.code) {
|
|
||||||
fetch('/login/github', {
|
|
||||||
method: 'post',
|
|
||||||
body: {
|
|
||||||
code: this.$route.query.code
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(r => {
|
|
||||||
let lastPath = localStorage.getItem('login_callback_path')
|
|
||||||
layer.toast('登录成功', 'success')
|
|
||||||
this.$store.user = r.data.user
|
|
||||||
localStorage.setItem('user', JSON.stringify(r.data.user))
|
|
||||||
localStorage.setItem('token', r.data.token)
|
|
||||||
if (lastPath) {
|
|
||||||
localStorage.removeItem('login_callback_path')
|
|
||||||
this.$router.replace(lastPath)
|
|
||||||
} else {
|
|
||||||
this.$router.replace('/login')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(r => {
|
|
||||||
console.log(r)
|
|
||||||
layer.toast(r.msg, 'error')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
jumpLogin(site = 'github') {
|
|
||||||
switch (site) {
|
|
||||||
case 'github':
|
|
||||||
location.replace(
|
|
||||||
'https://github.com/login/oauth/authorize?' +
|
|
||||||
`client_id=57d9d247bda6302fd9d1&redirect_uri=https://www.jscdn.ink/login`
|
|
||||||
)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
logout() {
|
|
||||||
this.$store.user = {}
|
|
||||||
localStorage.removeItem('user')
|
|
||||||
localStorage.removeItem('token')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.login-page {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
width: 1024px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 16px;
|
|
||||||
|
|
||||||
.login-form,
|
|
||||||
.user-card {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 320px;
|
|
||||||
min-height: 160px;
|
|
||||||
padding: 32px;
|
|
||||||
margin-top: 32px;
|
|
||||||
box-shadow: 0 0 12px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-form {
|
|
||||||
.title {
|
|
||||||
margin-bottom: 32px;
|
|
||||||
line-height: 2;
|
|
||||||
border-bottom: 1px solid var(--color-plain-2);
|
|
||||||
font-size: 20px;
|
|
||||||
text-align: center;
|
|
||||||
color: var(--color-grey-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.third-part {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
display: inline-flex;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
margin: 0 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-card {
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.avatar {
|
|
||||||
width: 96px;
|
|
||||||
height: 96px;
|
|
||||||
border: 3px solid var(--color-plain-1);
|
|
||||||
border-radius: 50%;
|
|
||||||
box-shadow: 0 0 16px rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.name {
|
|
||||||
line-height: 2;
|
|
||||||
}
|
|
||||||
.homepage {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
--size: 12px;
|
|
||||||
font-style: normal;
|
|
||||||
|
|
||||||
a {
|
|
||||||
margin-left: 6px;
|
|
||||||
text-decoration: underline;
|
|
||||||
color: var(--color-blue-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.logout {
|
|
||||||
margin-top: 32px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,8 +1,22 @@
|
||||||
import { html, css, Component } from 'wkit'
|
import { html, css, Component } from 'wkit'
|
||||||
|
|
||||||
|
import '//jscdn.ink/@bytedo/wcui/1.0.12/table/index.js'
|
||||||
|
import fetch from '/lib/fetch.js'
|
||||||
|
|
||||||
class Request extends Component {
|
class Request extends Component {
|
||||||
|
static props = {
|
||||||
|
list: [],
|
||||||
|
page: 'num!1',
|
||||||
|
total: 'num!0',
|
||||||
|
loading: false,
|
||||||
|
disabled: true
|
||||||
|
}
|
||||||
|
|
||||||
static styles = [
|
static styles = [
|
||||||
css`
|
css`
|
||||||
|
::selection {
|
||||||
|
background: var(--color-plain-a);
|
||||||
|
}
|
||||||
.packages {
|
.packages {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -20,19 +34,17 @@ class Request extends Component {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
|
|
||||||
wc-input {
|
& wc-input {
|
||||||
width: 480px;
|
width: 480px;
|
||||||
}
|
}
|
||||||
wc-link {
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.pager {
|
.pager {
|
||||||
margin-top: 16px;
|
margin-top: 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
`,
|
||||||
|
css`
|
||||||
.request-form {
|
.request-form {
|
||||||
width: 640px;
|
width: 640px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
@ -47,6 +59,7 @@ class Request extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
display: block;
|
||||||
padding: 16px 16px 32px;
|
padding: 16px 16px 32px;
|
||||||
|
|
||||||
.field {
|
.field {
|
||||||
|
@ -62,7 +75,7 @@ class Request extends Component {
|
||||||
.label {
|
.label {
|
||||||
width: 120px;
|
width: 120px;
|
||||||
}
|
}
|
||||||
wc-input,
|
& wc-input,
|
||||||
.value {
|
.value {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
@ -72,121 +85,7 @@ class Request extends Component {
|
||||||
`
|
`
|
||||||
]
|
]
|
||||||
|
|
||||||
render() {
|
#thead = JSON.stringify([
|
||||||
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([
|
|
||||||
'开源库',
|
'开源库',
|
||||||
'作者',
|
'作者',
|
||||||
'最后同步版本',
|
'最后同步版本',
|
||||||
|
@ -194,70 +93,60 @@ export default {
|
||||||
'收录状态',
|
'收录状态',
|
||||||
'备注',
|
'备注',
|
||||||
'操作'
|
'操作'
|
||||||
]),
|
])
|
||||||
page: 1,
|
|
||||||
total: 0,
|
#filter = ''
|
||||||
filter: '',
|
|
||||||
onlyShowWaited: false,
|
#list = []
|
||||||
loading: false,
|
#onlyShowWaited = false
|
||||||
disabled: true,
|
|
||||||
lib: {
|
#lib = {
|
||||||
name: '',
|
name: '',
|
||||||
author: '-',
|
author: '-',
|
||||||
description: '-',
|
description: '-',
|
||||||
latest: '-'
|
latest: '-'
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.$store.searchShow = false
|
|
||||||
|
|
||||||
this.fetchList()
|
#fetchList() {
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
fetchList() {
|
|
||||||
fetch('/package/list').then(r => {
|
fetch('/package/list').then(r => {
|
||||||
this.$list = r.data.map(
|
this.#list = r.data.map(
|
||||||
it => ((it.sync_date = new Date(it.sync_date).format('Y/m/d')), it)
|
it => ((it.sync_date = new Date(it.sync_date).format('Y/m/d')), it)
|
||||||
)
|
)
|
||||||
this.fetchPage()
|
this.#fetchPage()
|
||||||
this.total = this.$list.length
|
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
|
|
||||||
fetchPage() {
|
#fetchPage() {
|
||||||
let start = (this.page - 1) * 20
|
let start = (this.page - 1) * 20
|
||||||
let end = start + 20
|
let end = start + 20
|
||||||
this.list = this.$list
|
let filter = this.#filter
|
||||||
.filter(it => (this.onlyShowWaited ? it.stat === 1 : true))
|
let waited = this.#onlyShowWaited
|
||||||
|
|
||||||
|
this.list = this.#list
|
||||||
|
.filter(it => it.id.includes(filter) && (waited ? it.stat === 1 : true))
|
||||||
.slice(start, end)
|
.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
|
this.total = this.list.length
|
||||||
},
|
}
|
||||||
|
|
||||||
openDialog() {
|
#pageChanged(ev) {
|
||||||
|
this.page = ev.data
|
||||||
|
this.#fetchPage()
|
||||||
|
}
|
||||||
|
|
||||||
|
#search(ev) {
|
||||||
|
let filter = ev.type === 'submit' ? ev.target.value.trim() : this.#filter
|
||||||
|
let waited = ev.type === 'change' ? ev.value : this.#onlyShowWaited
|
||||||
|
|
||||||
|
this.#filter = filter
|
||||||
|
this.#onlyShowWaited = waited
|
||||||
|
|
||||||
|
this.list = this.#list.filter(
|
||||||
|
it => it.id.includes(filter) && (waited ? it.stat === 1 : true)
|
||||||
|
)
|
||||||
|
this.total = this.list.length
|
||||||
|
}
|
||||||
|
|
||||||
|
#openDialog() {
|
||||||
if (this.$store.user.id) {
|
if (this.$store.user.id) {
|
||||||
this.$refs.form.show()
|
this.$refs.form.show()
|
||||||
} else {
|
} else {
|
||||||
|
@ -266,31 +155,36 @@ export default {
|
||||||
this.$router.push('/login')
|
this.$router.push('/login')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
resetForm(force) {
|
#resetForm(force) {
|
||||||
force && (this.lib.name = '')
|
force && (this.#lib.name = '')
|
||||||
this.lib.author = '-'
|
this.#lib.author = '-'
|
||||||
this.lib.description = '-'
|
this.#lib.description = '-'
|
||||||
this.lib.latest = '-'
|
this.#lib.latest = '-'
|
||||||
this.disabled = true
|
this.disabled = true
|
||||||
},
|
}
|
||||||
|
|
||||||
|
#autoUpdateInfo(ev) {
|
||||||
|
let name = ev.target.value.trim()
|
||||||
|
this.#lib.name = name
|
||||||
|
|
||||||
autoUpdateInfo() {
|
|
||||||
let name = this.lib.name.trim()
|
|
||||||
clearTimeout(this.$timer)
|
clearTimeout(this.$timer)
|
||||||
if (name) {
|
if (name) {
|
||||||
if (name.startsWith('@') && name.indexOf('/') === -1) {
|
if (name.startsWith('@') && name.indexOf('/') === -1) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$timer = setTimeout(_ => {
|
this.$timer = setTimeout(async _ => {
|
||||||
this.getPackageInfo(name)
|
await this.#getPackageInfo(name)
|
||||||
|
this.$requestUpdate()
|
||||||
}, 800)
|
}, 800)
|
||||||
|
} else {
|
||||||
|
this.#resetForm()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
getPackageInfo(name) {
|
#getPackageInfo(name) {
|
||||||
return fetch('https://registry.npmmirror.com/' + name)
|
return fetch('https://registry.npmmirror.com/' + name)
|
||||||
.then(r => {
|
.then(r => {
|
||||||
let author = r.author
|
let author = r.author
|
||||||
|
@ -299,59 +193,59 @@ export default {
|
||||||
? r.maintainers[0].name
|
? r.maintainers[0].name
|
||||||
: 'unknow'
|
: 'unknow'
|
||||||
|
|
||||||
this.lib.author = author
|
this.#lib.author = author
|
||||||
this.lib.description = r.description || r.homepage
|
this.#lib.description = r.description || r.homepage
|
||||||
this.lib.latest = r['dist-tags'].latest
|
this.#lib.latest = r['dist-tags'].latest
|
||||||
|
|
||||||
this.disabled = false
|
this.disabled = false
|
||||||
return {
|
return {
|
||||||
author,
|
author,
|
||||||
description: this.lib.description,
|
description: this.#lib.description,
|
||||||
latest: r['dist-tags'].latest
|
latest: this.#lib.latest
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(_ => {
|
.catch(_ => {
|
||||||
this.resetForm()
|
this.#resetForm()
|
||||||
layer.toast(
|
layer.toast(
|
||||||
`开源库【${name}】在npm上找不到, 请确认名称是否正确`,
|
`开源库【${name}】在npm上找不到, 请确认名称是否正确`,
|
||||||
'error'
|
'error'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
|
|
||||||
uploadPackge(body) {
|
#uploadPackge(body) {
|
||||||
fetch('/package/upload', { method: 'post', body })
|
fetch('/package/upload', { method: 'post', body })
|
||||||
.then(r => {
|
.then(r => {
|
||||||
layer.toast('提交成功,等待审核', 'success')
|
layer.toast('提交成功,等待审核', 'success')
|
||||||
this.resetForm(true)
|
this.#resetForm(true)
|
||||||
this.fetchList()
|
this.#fetchList()
|
||||||
this.$refs.form.close()
|
this.$refs.form.close()
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
layer.toast(e.msg, 'error')
|
layer.toast(e.msg, 'error')
|
||||||
})
|
})
|
||||||
},
|
}
|
||||||
|
|
||||||
submit() {
|
#submit() {
|
||||||
let name = this.lib.name.trim()
|
let name = this.#lib.name.trim()
|
||||||
if (name) {
|
if (name) {
|
||||||
if (name.startsWith('@') && name.indexOf('/') === -1) {
|
if (name.startsWith('@') && name.indexOf('/') === -1) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.getPackageInfo(name)
|
this.#getPackageInfo(name)
|
||||||
.then(({ author, description, latest }) => {
|
.then(({ author, description, latest }) => {
|
||||||
//
|
//
|
||||||
this.uploadPackge({ name, author, description, latest })
|
this.#uploadPackge({ name, author, description, latest })
|
||||||
})
|
})
|
||||||
|
|
||||||
.finally(_ => (this.loading = false))
|
.finally(_ => (this.loading = false))
|
||||||
} else {
|
} else {
|
||||||
layer.toast(`请填写正确的名称`, 'warning')
|
layer.toast(`请填写正确的名称`, 'warning')
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
handlePackgae(act, id) {
|
#handlePackgae(act, id) {
|
||||||
if (act !== 'sync' && !this.$store.user.admin) {
|
if (act !== 'sync' && !this.$store.user.admin) {
|
||||||
return layer.alert('别闹, 老实等管理员通过~~')
|
return layer.alert('别闹, 老实等管理员通过~~')
|
||||||
}
|
}
|
||||||
|
@ -379,12 +273,135 @@ export default {
|
||||||
req
|
req
|
||||||
.then(r => {
|
.then(r => {
|
||||||
layer.toast('操作成功', 'success')
|
layer.toast('操作成功', 'success')
|
||||||
this.fetchList()
|
this.#fetchList()
|
||||||
})
|
})
|
||||||
.catch(r => {
|
.catch(r => {
|
||||||
r && layer.toast(r.msg, 'error')
|
r && layer.toast(r.msg, 'error')
|
||||||
})
|
})
|
||||||
.finally(_ => (this.loading = false))
|
.finally(_ => (this.loading = false))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$store.searchShow = false
|
||||||
|
this.#fetchList()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return html`
|
||||||
|
<main class="packages">
|
||||||
|
<div class="toolbar">
|
||||||
|
<wc-input
|
||||||
|
:value=${this.#filter}
|
||||||
|
placeholder="请输入开源库的名字"
|
||||||
|
@submit=${this.#search}
|
||||||
|
></wc-input>
|
||||||
|
|
||||||
|
<wc-switch :value=${this.#onlyShowWaited} @change=${this.#search}
|
||||||
|
>只显示待审核</wc-switch
|
||||||
|
>
|
||||||
|
<wc-link type="info" @click=${this.#openDialog}>
|
||||||
|
没找到你想的库?点击申请收录
|
||||||
|
</wc-link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<wc-table class="list" thead=${this.#thead}>
|
||||||
|
${this.list.map(
|
||||||
|
it => html`
|
||||||
|
<wc-tr>
|
||||||
|
<wc-td align="center">
|
||||||
|
<router-link
|
||||||
|
:to=${{ path: it.stat === 2 ? '/?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">${this.$store.stats[it.stat]}</wc-td>
|
||||||
|
<wc-td>${it.remark || '-'}</wc-td>
|
||||||
|
<wc-td align="center">
|
||||||
|
${it.stat === 2
|
||||||
|
? html`<wc-link
|
||||||
|
:disabled=${this.loading}
|
||||||
|
@click=${_ => this.#handlePackgae('sync', it.id)}
|
||||||
|
type="info"
|
||||||
|
>更新</wc-link
|
||||||
|
>`
|
||||||
|
: ''}
|
||||||
|
${this.$store.user.admin && it.stat !== 2
|
||||||
|
? html`<wc-link
|
||||||
|
@click=${_ => this.#handlePackgae('accept', it.id)}
|
||||||
|
type="info"
|
||||||
|
>通过</wc-link
|
||||||
|
>`
|
||||||
|
: ''}
|
||||||
|
${this.$store.user.admin && it.stat !== 0
|
||||||
|
? html`<wc-link
|
||||||
|
@click=${_ => this.#handlePackgae('reject', it.id)}
|
||||||
|
type="warning"
|
||||||
|
>拒绝</wc-link
|
||||||
|
>`
|
||||||
|
: ''}
|
||||||
|
${this.$store.user.admin && it.stat !== 0
|
||||||
|
? html`<wc-link
|
||||||
|
@click=${_ => this.#handlePackgae('delete', it.id)}
|
||||||
|
type="danger"
|
||||||
|
>删除</wc-link
|
||||||
|
>`
|
||||||
|
: ''}
|
||||||
|
</wc-td>
|
||||||
|
</wc-tr>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</wc-table>
|
||||||
|
|
||||||
|
<wc-pager
|
||||||
|
class="pager"
|
||||||
|
layout="prev,pages,next,info"
|
||||||
|
@page-change=${this.#pageChanged}
|
||||||
|
:total=${this.total}
|
||||||
|
:page=${this.page}
|
||||||
|
/>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<wc-layer ref="form" mask mask-close>
|
||||||
|
<div class="request-form">
|
||||||
|
<header class="title">申请收录开源库</header>
|
||||||
|
<main class="content">
|
||||||
|
<section class="field">
|
||||||
|
<span class="label">开源库名称:</span>
|
||||||
|
<wc-input
|
||||||
|
:value=${this.#lib.name}
|
||||||
|
@input=${this.#autoUpdateInfo}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
<section class="field">
|
||||||
|
<span class="label">作者:</span>
|
||||||
|
<span class="value">${this.#lib.author}</span>
|
||||||
|
</section>
|
||||||
|
<section class="field">
|
||||||
|
<span class="label">简介:</span>
|
||||||
|
<span class="value">${this.#lib.description}</span>
|
||||||
|
</section>
|
||||||
|
<section class="field">
|
||||||
|
<span class="label">最新版本:</span>
|
||||||
|
<span class="value">${this.#lib.latest}</span>
|
||||||
|
</section>
|
||||||
|
<section class="field center">
|
||||||
|
<wc-button
|
||||||
|
type="info"
|
||||||
|
:disabled=${this.disabled}
|
||||||
|
:loading=${this.loading}
|
||||||
|
@click=${this.#submit}
|
||||||
|
>提交申请</wc-button
|
||||||
|
>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
</wc-layer>
|
||||||
|
`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Request.reg('request')
|
||||||
|
|
|
@ -1,382 +0,0 @@
|
||||||
<template>
|
|
||||||
<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>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
Loading…
Reference in New Issue