408 lines
10 KiB
JavaScript
408 lines
10 KiB
JavaScript
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 {
|
|
static props = {
|
|
list: [],
|
|
page: 'num!1',
|
|
total: 'num!0',
|
|
loading: false,
|
|
disabled: true
|
|
}
|
|
|
|
static styles = [
|
|
css`
|
|
::selection {
|
|
background: var(--color-plain-a);
|
|
}
|
|
.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;
|
|
}
|
|
}
|
|
|
|
.pager {
|
|
margin-top: 16px;
|
|
}
|
|
}
|
|
`,
|
|
css`
|
|
.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 {
|
|
display: block;
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
`
|
|
]
|
|
|
|
#thead = JSON.stringify([
|
|
'开源库',
|
|
'作者',
|
|
'最后同步版本',
|
|
'最后同步日期',
|
|
'收录状态',
|
|
'备注',
|
|
'操作'
|
|
])
|
|
|
|
#filter = ''
|
|
|
|
#list = []
|
|
#onlyShowWaited = false
|
|
|
|
#lib = {
|
|
name: '',
|
|
author: '-',
|
|
description: '-',
|
|
latest: '-'
|
|
}
|
|
|
|
#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()
|
|
})
|
|
}
|
|
|
|
#fetchPage() {
|
|
let start = (this.page - 1) * 20
|
|
let end = start + 20
|
|
let filter = this.#filter
|
|
let waited = this.#onlyShowWaited
|
|
|
|
let list = this.#list.filter(
|
|
it => it.id.includes(filter) && (waited ? it.stat === 1 : true)
|
|
)
|
|
|
|
this.list = list.slice(start, end)
|
|
|
|
this.total = list.length
|
|
}
|
|
|
|
#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.#fetchPage()
|
|
}
|
|
|
|
#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(ev) {
|
|
let name = ev.target.value.trim()
|
|
this.#lib.name = name
|
|
|
|
clearTimeout(this.$timer)
|
|
if (name) {
|
|
if (name.startsWith('@') && name.indexOf('/') === -1) {
|
|
return
|
|
}
|
|
|
|
this.$timer = setTimeout(async _ => {
|
|
await this.#getPackageInfo(name)
|
|
this.$requestUpdate()
|
|
}, 800)
|
|
} else {
|
|
this.#resetForm()
|
|
}
|
|
}
|
|
|
|
#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: this.#lib.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_path => {
|
|
return fetch(`/package/${act}/${encodeURIComponent(id)}`, {
|
|
method: 'PUT',
|
|
body: { dist_path }
|
|
})
|
|
})
|
|
} 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))
|
|
}
|
|
|
|
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 === 1
|
|
? html`<wc-link
|
|
@click=${_ => this.#handlePackgae('reject', it.id)}
|
|
type="warning"
|
|
>拒绝</wc-link
|
|
>`
|
|
: ''}
|
|
${this.$store.user.admin && (it.stat === 1 || it.stat === 2)
|
|
? 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')
|