Add topic management

Signed-off-by: kocoler <tsglsdrs@163.com>
This commit is contained in:
kocoler 2020-09-29 02:41:22 +08:00
parent 642d330e1f
commit 50bc54bff5
22 changed files with 590369 additions and 34 deletions

View File

@ -829,7 +829,7 @@ var accessKeySecret = beego.AppConfig.String("accessKeySecret")
var roleArn = beego.AppConfig.String("roleArn")
func (c *APIController) GetMemberStsToken() {
sessionName := c.GetSessionUser()
sessionName := util.ConvertToPinyin(c.GetSessionUser())
if accessKeyID == "" {
resp := Response{Status: "fail", Msg: "Missing sts config."}

View File

@ -48,6 +48,42 @@ func (c *APIController) GetTopics() {
c.ServeJSON()
}
func (c *APIController) GetTopicsAdmin() {
limitStr := c.Input().Get("limit")
pageStr := c.Input().Get("page")
usernameSearchKw := c.Input().Get("un") // search: username(author)
titleSearchKw := c.Input().Get("ti") // search: title
contentSearchKw := c.Input().Get("cn") // search: content
showDeletedTopics := c.Input().Get("sdt") // sort: show deleted topics
createdTimeSort := c.Input().Get("cs") // sort: created time
lastReplySort := c.Input().Get("lrs") // sort: last reply time
usernameSort := c.Input().Get("us") // sort: username
replyCountSort := c.Input().Get("rcs") // sort: reply count
hotSort := c.Input().Get("hs") // sort: hot
favCountSort := c.Input().Get("fcs") // sort: favorite count
defaultLimit := object.DefaultHomePageNum
var limit, offset int
if len(limitStr) != 0 {
limit = util.ParseInt(limitStr)
} else {
limit = defaultLimit
}
if len(pageStr) != 0 {
page := util.ParseInt(pageStr)
offset = page*limit - limit
}
res, num := object.GetTopicsAdmin(usernameSearchKw, titleSearchKw, contentSearchKw, showDeletedTopics, createdTimeSort, lastReplySort, usernameSort, replyCountSort, hotSort, favCountSort, limit, offset)
c.Data["json"] = Response{Status: "ok", Msg: "success", Data: res, Data2: num}
c.ServeJSON()
}
func (c *APIController) GetTopic() {
memberId := c.GetSessionUser()
idStr := c.Input().Get("id")
@ -69,6 +105,15 @@ func (c *APIController) GetTopic() {
c.ServeJSON()
}
func (c *APIController) GetTopicAdmin() {
idStr := c.Input().Get("id")
id := util.ParseInt(idStr)
c.Data["json"] = object.GetTopicAdmin(id)
c.ServeJSON()
}
func (c *APIController) UpdateTopic() {
idStr := c.Input().Get("id")
@ -167,7 +212,7 @@ func (c *APIController) DeleteTopic() {
}
func (c *APIController) GetTopicsNum() {
c.Data["json"] = object.GetTopicCount()
c.Data["json"] = object.GetTopicNum()
c.ServeJSON()
}

589032
dictionary/dictionary.txt Normal file

File diff suppressed because it is too large Load Diff

4
go.mod
View File

@ -3,6 +3,7 @@ module github.com/casbin/casbin-forum
go 1.14
require (
github.com/adamzy/cedar-go v0.0.0-20170805034717-80a9c64b256d // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.61.370
github.com/aliyun/aliyun-oss-go-sdk v2.1.4+incompatible
github.com/aliyun/aliyun-sts-go-sdk v0.0.0-20171106034748-98d3903a2309
@ -10,7 +11,10 @@ require (
github.com/dchest/captcha v0.0.0-20170622155422-6a29415a8364
github.com/go-gomail/gomail v0.0.0-20160411212932-81ebce5c23df
github.com/go-sql-driver/mysql v1.5.0
github.com/huichen/sego v0.0.0-20180617034105-3f3c8a8cfacc
github.com/mileusna/crontab v0.0.0-20180909013013-f182897de5d8
github.com/mozillazg/go-slugify v0.2.0
github.com/mozillazg/go-unidecode v0.1.1 // indirect
github.com/satori/go.uuid v1.2.0 // indirect
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 // indirect
golang.org/x/net v0.0.0-20190620200207-3b0461eec859

8
go.sum
View File

@ -7,6 +7,8 @@ github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8L
github.com/OwnLocal/goes v1.0.0/go.mod h1:8rIFjBGTue3lCU0wplczcUgt9Gxgrkkrw7etMIcn8TM=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/adamzy/cedar-go v0.0.0-20170805034717-80a9c64b256d h1:ir/IFJU5xbja5UaBEQLjcvn7aAU01nqU/NUyOBEU+ew=
github.com/adamzy/cedar-go v0.0.0-20170805034717-80a9c64b256d/go.mod h1:PRWNwWq0yifz6XDPZu48aSld8BWwBfr2JKB2bGWiEd4=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.370 h1:YB6kPMuCtNQSyCZQToeyUsKgQwBp1J9Ks1QbXOxlhHg=
@ -76,6 +78,8 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huichen/sego v0.0.0-20180617034105-3f3c8a8cfacc h1:3LXYtoxQGFSjIL5ZJAn4PceSpwRohuTKYL1W4kJ7G8g=
github.com/huichen/sego v0.0.0-20180617034105-3f3c8a8cfacc/go.mod h1:+/Bm7uk1bnJJMi9l6P88FgHeGtscOQiYbxW1j+BmgBY=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE=
@ -102,6 +106,10 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mozillazg/go-slugify v0.2.0 h1:SIhqDlnJWZH8OdiTmQgeXR28AOnypmAXPeOTcG7b9lk=
github.com/mozillazg/go-slugify v0.2.0/go.mod h1:z7dPH74PZf2ZPFkyxx+zjPD8CNzRJNa1CGacv0gg8Ns=
github.com/mozillazg/go-unidecode v0.1.1 h1:uiRy1s4TUqLbcROUrnCN/V85Jlli2AmDF6EeAXOeMHE=
github.com/mozillazg/go-unidecode v0.1.1/go.mod h1:fYMdhyjni9ZeEmS6OE/GJHDLsF8TQvIVDwYR/drR26Q=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=

View File

@ -23,12 +23,14 @@ import (
"github.com/casbin/casbin-forum/object"
"github.com/casbin/casbin-forum/routers"
"github.com/casbin/casbin-forum/service"
"github.com/casbin/casbin-forum/util"
)
func main() {
object.InitAdapter()
controllers.InitHttpClient()
service.InitAliOSS()
util.InitSegmenter()
beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
AllowOrigins: []string{"*"},

View File

@ -52,6 +52,15 @@ func GetTopicCount() int {
return int(count)
}
func GetTopicNum() int {
count, err := adapter.engine.Where("deleted = ?", 0).Count(&Topic{})
if err != nil {
panic(err)
}
return int(count)
}
func GetCreatedTopicsNum(memberId string) int {
topic := new(Topic)
total, err := adapter.engine.Where("author = ?", memberId).And("deleted = ?", 0).Count(topic)
@ -81,6 +90,101 @@ func GetTopics(limit int, offset int) []*TopicWithAvatar {
return res
}
// GetTopicsAdmin *sort: 1 means Asc, 2 means Desc, 0 means no effect.
func GetTopicsAdmin(usernameSearchKw, titleSearchKw, contentSearchKw, showDeletedTopic, createdTimeSort, lastReplySort, usernameSort, replyCountSort, hotSort, favCountSort string, limit int, offset int) ([]*AdminTopicInfo, int) {
topics := []*Topic{}
db := adapter.engine.Table("topic")
// created time sort
switch createdTimeSort {
case "1":
db = db.Asc("created_time")
case "2":
db = db.Desc("created_time")
}
// last reply time sort
switch lastReplySort {
case "1":
db = db.Asc("last_reply_time")
case "2":
db = db.Desc("last_reply_time")
}
// author sort
switch usernameSort {
case "1":
db = db.Asc("author")
case "2":
db = db.Desc("author")
}
// reply count sort
switch replyCountSort {
case "1":
db = db.Asc("reply_count")
case "2":
db = db.Desc("reply_count")
}
// hot sort
switch hotSort {
case "1":
db = db.Asc("hot")
case "2":
db = db.Desc("hot")
}
// favorite count sort
switch favCountSort {
case "1":
db = db.Asc("favorite_count")
case "2":
db = db.Desc("favorite_count")
}
if usernameSearchKw != "" {
unKw := util.SplitWords(usernameSearchKw)
for _, v := range unKw {
db.Or("author like ?", "%"+v+"%")
}
}
if titleSearchKw != "" {
tiKw := util.SplitWords(titleSearchKw)
for _, v := range tiKw {
db.Or("title like ?", "%"+v+"%")
}
}
if contentSearchKw != "" {
coKw := util.SplitWords(contentSearchKw)
for _, v := range coKw {
db.Or("content like ?", "%"+v+"%")
}
}
if showDeletedTopic == "0" {
db = db.Where("deleted = ?", 0)
}
num, err := db.Limit(limit, offset).FindAndCount(&topics, &Topic{})
if err != nil {
panic(err)
}
var res []*AdminTopicInfo
for _, v := range topics {
temp := AdminTopicInfo{
Topic: *v,
Deleted: v.Deleted,
}
res = append(res, &temp)
}
return res, int(num)
}
func GetTopicWithAvatar(id int, memberId string) *TopicWithAvatar {
topic := Topic{Id: id}
existed, err := adapter.engine.Get(&topic)
@ -116,6 +220,23 @@ func GetTopic(id int) *Topic {
}
}
func GetTopicAdmin(id int) *AdminTopicInfo {
topic := Topic{Id: id}
existed, err := adapter.engine.Get(&topic)
if err != nil {
panic(err)
}
if existed {
return &AdminTopicInfo{
Topic: topic,
Deleted: topic.Deleted,
}
} else {
return nil
}
}
func GetTopicTitle(id int) string {
topic := Topic{Id: id}
existed, err := adapter.engine.Cols("title").Get(&topic)

View File

@ -123,3 +123,8 @@ type AdminPlaneInfo struct {
NodesNum int `json:"nodesNum"`
Nodes []*Node `json:"nodes"`
}
type AdminTopicInfo struct {
Topic
Deleted bool `json:"deleted"`
}

View File

@ -34,8 +34,10 @@ func initAPI() {
beego.AddNamespace(ns)
beego.Router("/api/get-topics", &controllers.APIController{}, "GET:GetTopics")
beego.Router("/api/get-topics-admin", &controllers.APIController{}, "GET:GetTopicsAdmin")
beego.Router("/api/get-topic", &controllers.APIController{}, "GET:GetTopic")
beego.Router("/api/update-topic", &controllers.APIController{}, "POST:UpdateTopic")
beego.Router("/api/get-topic-admin", &controllers.APIController{}, "GET:GetTopicAdmin")
//beego.Router("/api/update-topic", &controllers.APIController{}, "POST:UpdateTopic") // no necessary to explore this api.
beego.Router("/api/add-topic", &controllers.APIController{}, "POST:AddTopic")
beego.Router("/api/delete-topic", &controllers.APIController{}, "POST:DeleteTopic")
beego.Router("/api/get-all-created-topics", &controllers.APIController{}, "GET:GetAllCreatedTopics")

View File

@ -18,6 +18,9 @@ import (
"io/ioutil"
"regexp"
"strconv"
"github.com/huichen/sego"
"github.com/mozillazg/go-slugify"
)
func ParseInt(s string) int {
@ -55,3 +58,24 @@ func WriteStringToPath(s string, path string) {
panic(err)
}
}
var Segmenter sego.Segmenter
func InitSegmenter() {
// load dictionary
Segmenter.LoadDictionary("dictionary/dictionary.txt")
}
// SplitWords split string into single words.
func SplitWords(str string) []string {
if Segmenter.Dictionary() != nil {
var res []string
res = sego.SegmentsToSlice(Segmenter.Segment([]byte(str)), true)
return res
}
return []string{}
}
func ConvertToPinyin(content string) string {
return slugify.Slugify(content)
}

View File

@ -17,6 +17,7 @@
"js-md5": "^0.7.3",
"moment": "^2.26.0",
"pangu": "^4.0.7",
"pinyin": "^2.9.1",
"rc-collapse": "^2.0.0",
"re-resizable": "^6.5.4",
"react": "^16.13.1",

View File

@ -66,6 +66,7 @@ import AdminTab from "./admin/AdminTab";
import AdminMember from "./admin/AdminMember";
import i18next from "i18next";
import AdminPlane from "./admin/AdminPlane";
import AdminTopic from "./admin/AdminTopic";
class App extends Component {
constructor(props) {
@ -363,12 +364,6 @@ class App extends Component {
<AdminMember account={this.state.account} />
</div>
</Route>
<Route exact path="/admin/member/new">
<div id={pcBrowser ? "Main" : ""}>
{pcBrowser ? <div className="sep20" /> : null}
<AdminMember account={this.state.account} event={"new"} />
</div>
</Route>
<Route exact path="/admin/member/edit/:memberId">
<div id={pcBrowser ? "Main" : ""}>
{pcBrowser ? <div className="sep20" /> : null}
@ -393,6 +388,18 @@ class App extends Component {
<AdminPlane account={this.state.account} />
</div>
</Route>
<Route exact path="/admin/topic">
<div id={pcBrowser ? "Main" : ""}>
{pcBrowser ? <div className="sep20" /> : null}
<AdminTopic account={this.state.account} />
</div>
</Route>
<Route exact path="/admin/topic/edit/:topicId">
<div id={pcBrowser ? "Main" : ""}>
{pcBrowser ? <div className="sep20" /> : null}
<AdminTopic account={this.state.account} />
</div>
</Route>
</Switch>
)
}

View File

@ -24,6 +24,7 @@ import oss from "ali-oss";
import * as i18n from "./i18n"
import i18next from "i18next";
const pinyin = require('pinyin');
const pangu = require("pangu");
export let ServerUrl = '';
@ -162,9 +163,20 @@ export function initNewOSSClient(accessKeyId, accessKeySecret, stsToken) {
OSSClient = newClient;
}
export function convertToPinyin(content) {
content = pinyin(content, {style: pinyin.STYLE_NORMAL, heteronym: false, segment: false});
let pinyinData = "";
for(let i = 0; i < content.length; i++){
pinyinData = pinyinData + content[i][0];
}
return pinyinData;
}
export function initOSSClient(id) {
getOSSClient(initNewOSSClient);
let url, fileUrl;
id = convertToPinyin(id);
if (Conf.OSSCustomDomain.length !== 0) {
url = `https://${Conf.OSSCustomDomain}/${Conf.OSSBasicPath}/${id}`;
} else {

View File

@ -758,7 +758,7 @@ class AdminMember extends React.Component {
{
this.state.loading ?
<div className="cell" style={{textAlign: "center", height: "100px", lineHeight: "100px"}}>
{i18next.t("member:Data is loading")}
{i18next.t("loading:Data is loading...")}
</div> :
<div id="all-members">
{

View File

@ -860,7 +860,7 @@ class AdminNode extends React.Component {
<span className="chevron">&nbsp;&nbsp;</span>{" "}{i18next.t("node:Node management")}
<div className="fr f12">
<span className="snow">{i18next.t("node:Total nodes")}{" "}&nbsp;</span>
<strong className="gray">{this.state.nodes.length}</strong>
<strong className="gray">{this.state.nodes === null ? 0 : this.state.nodes.length}</strong>
</div>
<div className="fr f12">
<strong className="gray">
@ -871,8 +871,14 @@ class AdminNode extends React.Component {
</div>
<div id="all-nodes">
{
this.state.nodes.length !== 0 ?
this.state.nodes.map(node => this.renderNodes(node)) : null
this.state.nodes !== null && this.state.nodes.length !== 0 ?
this.state.nodes.map(node => this.renderNodes(node)) :
<div className="cell" style={{textAlign: "center", height: "100px", lineHeight: "100px"}}>
{
this.state.nodes === null ?
i18next.t("node:No node yet") : i18next.t("loading:Data is loading...")
}
</div>
}
</div>
</div>

View File

@ -686,7 +686,7 @@ class AdminPlane extends React.Component {
<span className="chevron">&nbsp;&nbsp;</span>{" "}{i18next.t("plane:Plane management")}
<div className="fr f12">
<span className="snow">{i18next.t("plane:Total planes")}{" "}&nbsp;</span>
<strong className="gray">{this.state.planes.length}</strong>
<strong className="gray">{this.state.planes === null ? 0 : this.state.planes.length}</strong>
</div>
<div className="fr f12">
<strong className="gray">
@ -705,8 +705,14 @@ class AdminPlane extends React.Component {
}
<div id="all-planes">
{
this.state.planes.length !== 0 ?
this.state.planes.map(plane => this.renderPlanes(plane)) : null
this.state.planes !== null && this.state.planes.length !== 0 ?
this.state.planes.map(plane => this.renderPlanes(plane)) :
<div className="cell" style={{textAlign: "center", height: "100px", lineHeight: "100px"}}>
{
this.state.planes === null ?
i18next.t("plane:No plant yet") : i18next.t("loading:Data is loading...")
}
</div>
}
</div>
</div>

View File

@ -506,7 +506,7 @@ class AdminTab extends React.Component {
<span className="chevron">&nbsp;&nbsp;</span>{" "}{i18next.t("tab:Tab management")}
<div className="fr f12">
<span className="snow">{i18next.t("tab:Total tabs")}{" "}&nbsp;</span>
<strong className="gray">{this.state.tabs.length}</strong>
<strong className="gray">{this.state.tabs === null ? 0 : this.state.tabs.length}</strong>
</div>
<div className="fr f12">
<strong className="gray">
@ -525,8 +525,14 @@ class AdminTab extends React.Component {
}
<div id="all-tabs">
{
this.state.tabs.length !== 0 ?
this.state.tabs.map(tab => this.renderTabs(tab)) : null
this.state.tabs !== null && this.state.tabs.length !== 0 ?
this.state.tabs.map(tab => this.renderTabs(tab)) :
<div className="cell" style={{textAlign: "center", height: "100px", lineHeight: "100px"}}>
{
this.state.tabs === null ?
i18next.t("tab:No tab yet") : i18next.t("loading:Data is loading...")
}
</div>
}
</div>
</div>

735
web/src/admin/AdminTopic.js Normal file
View File

@ -0,0 +1,735 @@
// Copyright 2020 The casbin Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import React from "react";
import {withRouter} from "react-router-dom";
import * as TopicBackend from "../backend/TopicBackend.js";
import * as Setting from "../Setting";
import PageColumn from "../main/PageColumn";
import Collapse, {Panel} from "rc-collapse";
import ReactMarkdown from "react-markdown";
import Zmage from "react-zmage";
import i18next from "i18next";
class AdminTopic extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
message: "",
errorMessage: "",
form: {},
//event: props.match.params.event,
width: "",
p: "",
topicId: props.match.params.topicId,
event: "basic",
page: 1,
limit: 100,
minPage: 1,
maxPage: -1,
showSearch: false,
loading: true,
topicsNum: 0,
topics: [],
topic: [],
//un, ti, cn, cs, lrs, us, rcs, hs, fcs
un: "", // username search
ti: "", // title search
cn: "", // content search
sdt: 1, // show deleted topics, default: Show
cs: 1, // created time sort, default: Asc
lrs: 0, // last reply time sort, default: None
us: 0, // username sort, default: None
rcs: 0, // reply count sort, default: None
hs: 0, // hot sort, default: None
fcs: 0, // favorite count sort, default: None
Status_LIST: [
{label: "Normal", value: 1},
{label: "Deleted", value: 2},
{label: "Topping", value: 3},
],
Management_LIST: [
{label: "Basic Info", value: "basic"},
{label: "Content", value: "content"},
],
};
const params = new URLSearchParams(this.props.location.search);
this.state.p = params.get("p");
if (this.state.p === null) {
this.state.page = 1;
}else {
this.state.page = parseInt(this.state.p);
}
this.state.url = `/admin/topic`;
}
componentDidMount() {
this.getTopics();
this.getTopic();
}
getTopics() {
//un, ti, cn, sdt, cs, lrs, us, rcs, hs, fcs
TopicBackend.getTopicsAdmin(this.state.un, this.state.ti, this.state.cn, this.state.sdt, this.state.cs, this.state.lrs, this.state.us, this.state.rcs, this.state.hs, this.state.fcs, this.state.limit, this.state.page)
.then((res) => {
this.setState({
topics: res?.data,
topicsNum: res?.data2,
});
});
}
getTopic() {
if (this.state.topicId === undefined) {
return;
}
TopicBackend.getTopicAdmin(this.state.topicId)
.then((res) => {
this.setState({
topic: res,
}, () => {
this.initForm();
});
});
}
initForm() {
let form = this.state.form;
form["deleted"] = this.state.topic?.deleted;
this.setState({
form: form,
});
}
updateFormField(key, value) {
let form = this.state.form;
form[key] = value;
this.setState({
form: form,
});
}
getSearchResult() {
TopicBackend.getTopicsAdmin(this.state.un, this.state.ti, this.state.cn, this.state.sdt, this.state.cs, this.state.lrs, this.state.us, this.state.rcs, this.state.hs, this.state.fcs, this.state.limit, 1)
.then((res) => {
if (res.status === 'ok') {
window.history.pushState({}, 0, `/admin/topic`)
this.setState({
message: i18next.t("admin:Get search result success"),
topics: res?.data,
topicsNum: res?.data2,
page: 1,
});
} else {
this.setState({
message: res?.msg,
});
}
});
}
renderImage = ({alt, src}) => {
return(
<Zmage src={src} alt={alt} />
);
};
renderLink = (props) => {
return(
<a {...props} target="_blank" />
);
};
showPageColumn() {
if (this.state.topicsNum < this.state.limit) {
return;
}
return (
<PageColumn page={this.state.page} total={this.state.topicsNum} url={this.state.url} defaultPageNum={this.state.limit} />
);
}
clearMessage() {
this.setState({
message: "",
});
}
clearErrorMessage() {
this.setState({
errorMessage: "",
});
}
changeShowSearch() {
this.setState({
showSearch: !this.state.showSearch
});
}
changeEvent(event) {
this.setState({
event: event,
message: "",
});
if (this.props.event !== "new") {
this.initForm();
}
}
renderRadioButton(type) {
switch (type) {
case "sdt":
return (
<span>
<input type="radio" onClick={() => this.setState({sdt: 1})} checked={this.state.sdt === 1} name="sdt" />{i18next.t("admin:Show")}{" "}
<input type="radio" onClick={() => this.setState({sdt: 0})} checked={this.state.sdt === 0} name="sdt" />{i18next.t("admin:Hidden")}
</span>
);
case "us":
return (
<span>
<input type="radio" onClick={() => this.setState({us: 1})} checked={this.state.us === 1} name="us" />{i18next.t("admin:Asc")}{" "}
<input type="radio" onClick={() => this.setState({us: 2})} checked={this.state.us === 2} name="us" />{i18next.t("admin:Desc")}{" "}
<input type="radio" onClick={() => this.setState({us: 0})} checked={this.state.us === 0} name="us" />{i18next.t("admin:Ignore")}
</span>
);
case "cs":
return (
<span>
<input type="radio" onClick={() => this.setState({cs: 1})} checked={this.state.cs === 1} name="cs" />{i18next.t("admin:Asc")}{" "}
<input type="radio" onClick={() => this.setState({cs: 2})} checked={this.state.cs === 2} name="cs" />{i18next.t("admin:Desc")}{" "}
<input type="radio" onClick={() => this.setState({cs: 0})} checked={this.state.cs === 0} name="cs" />{i18next.t("admin:Ignore")}
</span>
);
case "lrs":
return (
<span>
<input type="radio" onClick={() => this.setState({lrs: 1})} checked={this.state.lrs === 1} name="lrs" />{i18next.t("admin:Asc")}{" "}
<input type="radio" onClick={() => this.setState({lrs: 2})} checked={this.state.lrs === 2} name="lrs" />{i18next.t("admin:Desc")}{" "}
<input type="radio" onClick={() => this.setState({lrs: 0})} checked={this.state.lrs === 0} name="lrs" />{i18next.t("admin:Ignore")}
</span>
);
case "rcs":
return (
<span>
<input type="radio" onClick={() => this.setState({rcs: 1})} checked={this.state.rcs === 1} name="rcs" />{i18next.t("admin:Asc")}{" "}
<input type="radio" onClick={() => this.setState({rcs: 2})} checked={this.state.rcs === 2} name="rcs" />{i18next.t("admin:Desc")}{" "}
<input type="radio" onClick={() => this.setState({rcs: 0})} checked={this.state.rcs === 0} name="rcs" />{i18next.t("admin:Ignore")}
</span>
);
case "hs":
return (
<span>
<input type="radio" onClick={() => this.setState({hs: 1})} checked={this.state.hs === 1} name="hs" />{i18next.t("admin:Asc")}{" "}
<input type="radio" onClick={() => this.setState({hs: 2})} checked={this.state.hs === 2} name="hs" />{i18next.t("admin:Desc")}{" "}
<input type="radio" onClick={() => this.setState({hs: 0})} checked={this.state.hs === 0} name="hs" />{i18next.t("admin:Ignore")}
</span>
);
case "fcs":
return (
<span>
<input type="radio" onClick={() => this.setState({fcs: 1})} checked={this.state.fcs === 1} name="fcs" />{i18next.t("admin:Asc")}{" "}
<input type="radio" onClick={() => this.setState({fcs: 2})} checked={this.state.fcs === 2} name="fcs" />{i18next.t("admin:Desc")}{" "}
<input type="radio" onClick={() => this.setState({fcs: 0})} checked={this.state.fcs === 0} name="fcs" />{i18next.t("admin:Ignore")}
</span>
);
}
}
renderSearchList() {
const pcBrowser = Setting.PcBrowser;
return (
<table cellPadding="5" cellSpacing="0" border="0" width="100%">
<tbody>
<tr>
<td width={pcBrowser ? "200" : "auto"} align="left">
<span className="gray">
{i18next.t("topic:Author")}
</span>
</td>
<td width={pcBrowser ? "100" : "auto"} align="left">
<input value={this.state.un} onChange={event => this.setState({un: event.target.value})}/>
</td>
</tr>
<tr>
<td width={pcBrowser ? "200" : "auto"} align="left">
<span className="gray">
{i18next.t("topic:Title")}
</span>
</td>
<td width={pcBrowser ? "100" : "auto"} align="left">
<input value={this.state.ti} onChange={event => this.setState({ti: event.target.value})}/>
</td>
</tr>
<tr>
<td width={pcBrowser ? "200" : "auto"} align="left">
<span className="gray">
{i18next.t("topic:Content")}
</span>
</td>
<td width={pcBrowser ? "100" : "auto"} align="left">
<input value={this.state.cn} onChange={event => this.setState({cn: event.target.value})}/>
</td>
</tr>
<tr>
<td width={pcBrowser ? "200" : "auto"} align="left">
<span className="gray">
{i18next.t("topic:Show deleted topics")}
</span>
</td>
<td width={pcBrowser ? "100" : "auto"} align="left">
{this.renderRadioButton("sdt")}
</td>
</tr>
<tr>
<td width={pcBrowser ? "200" : "auto"} align="left">
<span className="gray">
{i18next.t("admin:Sorter")}
</span>
</td>
<td width={pcBrowser ? "100" : "auto"} align="left">
{i18next.t("topic:Created time")}
</td>
<td width={pcBrowser ? "150" : "auto"} align="left">
{this.renderRadioButton("cs")}
</td>
</tr>
<tr>
<td width="10"></td>
<td width={pcBrowser ? "100" : "auto"} align="left">
{i18next.t("topic:Author")}
</td>
<td width={pcBrowser ? "150" : "auto"} align="left">
{this.renderRadioButton("us")}
</td>
</tr>
<tr>
<td width="10"></td>
<td width={pcBrowser ? "100" : "auto"} align="left">
{i18next.t("topic:Reply count")}
</td>
<td width={pcBrowser ? "150" : "auto"} align="left">
{this.renderRadioButton("rcs")}
</td>
</tr>
<tr>
<td width="10"></td>
<td width={pcBrowser ? "100" : "auto"} align="left">
{i18next.t("topic:Hot")}
</td>
<td width={pcBrowser ? "150" : "auto"} align="left">
{this.renderRadioButton("hs")}
</td>
</tr>
<tr>
<td width="10"></td>
<td width={pcBrowser ? "100" : "auto"} align="left">
{i18next.t("topic:Favorite count")}
</td>
<td width={pcBrowser ? "150" : "auto"} align="left">
{this.renderRadioButton("fcs")}
</td>
</tr>
<tr>
<td width="10"></td>
<td width="auto" align="left">
<input type="submit" className="super normal button" value={i18next.t("topic:Search")} onClick={() => this.getSearchResult()}/>
</td>
</tr>
</tbody>
</table>
);
}
renderManagementList(item){
return (
<a href="javascript:void(0);" className={this.state.event === item.value ? "tab_current" : "tab"} onClick={() => this.changeEvent(item.value)}>{i18next.t(`topic:${item.label}`)}</a>
);
}
renderHeader() {
return (
<div className="box">
<div className="header"><a href="/">{Setting.getForumName()}</a>
{" "}<span className="chevron">&nbsp;&nbsp;</span>
<a href={`/admin`}>{i18next.t("admin:Backstage management")}</a>
{" "}<span className="chevron">&nbsp;&nbsp;</span>
<a href={`/admin/topic`}>{i18next.t("topic:Topic management")}</a>
{" "}<span className="chevron">&nbsp;&nbsp;</span>
<span>
{this.state.topic?.title}
</span>
</div>
<div className="cell">
{
this.state.Management_LIST.map((item) => {
return this.renderManagementList(item);
})
}
</div>
</div>
);
}
renderTopicStatus(status, homePageTopTime, tabTopTime, nodeTopTime) {
if (status === false) {
status = 1;
} else {
status = 2;
}
if (homePageTopTime !== "" || tabTopTime !== "" || nodeTopTime !== "") {
status = 3; // topping
}
switch (status) {
case 1:
return (
<span className="gray">
{i18next.t("topic:Normal")}
</span>
);
case 2:
return (
<span className="negative">
{i18next.t("topic:Deleted")}
</span>
);
case 3:
return (
<span className="positive">
{i18next.t("topic:Topping")}
</span>
);
default:
return (
<span className="gray">
{i18next.t("topic:Unknown status")}
</span>
);
}
}
renderTopics(topic) {
const pcBrowser = Setting.PcBrowser;
return (
<div className="cell">
<table cellPadding="0" cellSpacing="0" border="0" width="100%">
<tbody>
<tr>
<td width={pcBrowser ? "200" : "auto"} align="left">
<span className="gray">
<a href={`/t/${topic?.id}`} target="_blank">
{
topic?.title.length > 30 ?
topic?.title.slice(0, 30) + "..." : topic?.title
}
</a>
</span>
</td>
<td width="200" align="center">
<a href={`/admin/topic/edit/${topic?.id}`}>
{i18next.t("admin:Manage")}
</a>
</td>
<td width="10"></td>
<td width="60" align="left" style={{textAlign: "right"}}>
{
this.renderTopicStatus(topic?.deleted, topic?.homePageTopTime, topic?.tabTopTime, topic?.nodeTopTime)
}
</td>
</tr>
</tbody>
</table>
</div>
);
}
render() {
if (this.state.topicId !== undefined) {
if (this.state.topic !== null && this.state.topic.length === 0) {
return (
<div className="box">
<div className="header"><a href="/">{Setting.getForumName()}</a><span className="chevron">&nbsp;&nbsp;</span>{" "}{i18next.t("loading:Page is loading")}</div>
<div className="cell"><span className="gray bigger">{i18next.t("loading:Please wait patiently...")}</span></div>
</div>
);
}
if (this.state.topic === null) {
return (
<div class="box">
<div className="box">
<div className="header"><a href="/">{Setting.getForumName()}</a> <span
className="chevron">&nbsp;&nbsp;</span>{" "}{i18next.t("error:Topic does not exist")}</div>
<div className="cell"><span className="gray bigger">404 Topic Not Found</span></div>
<div className="inner"> <a href="/">{i18next.t("error:Back to Home Page")}</a></div>
</div>
</div>
);
}
const topic = this.state.topic;
if (this.state.event === "basic") {
return (
<div>
{this.renderHeader()}
<div className="box">
{
this.state.message !== "" ?
<div className="message" onClick={() => this.clearMessage()}>
<li className="fa fa-exclamation-triangle"></li>
&nbsp;{" "}
{this.state.message}
</div> : null
}
<div className="inner">
<table cellPadding="5" cellSpacing="0" border="0" width="100%">
<tbody>
<tr>
<td width="120" align="right">{i18next.t("topic:Topic ID")}</td>
<td width="auto" align="left">
<span className="gray">
{topic?.id}
</span>
</td>
</tr>
<tr>
<td width="120" align="right">{i18next.t("topic:Author")}</td>
<td width="auto" align="left">
<span className="gray">
<a href={`/member/${topic.author}`} target="_blank">
{topic?.author}
</a>
</span>
</td>
</tr>
<tr>
<td width="120" align="right">{i18next.t("topic:Node")}</td>
<td width="auto" align="left">
<span className="gray">
<a href={`/go/${topic?.nodeId}`} target="_blank">
{topic?.nodeName}
</a>
</span>
&nbsp;{" "}&nbsp;{" "}
<a href={`/move/topic/${topic?.id}`} target="_blank">
{i18next.t("topic:Move topic")}
</a>
</td>
</tr>
<tr>
<td width="120" align="right">{i18next.t("topic:Created time")}</td>
<td width="auto" align="left">
<span className="gray">
{topic?.createdTime}
</span>
</td>
</tr>
<tr>
<td width="120" align="right">{i18next.t("topic:Last reply user")}</td>
<td width="auto" align="left">
<span className="gray">
{
topic.lastReplyUser === "" ?
i18next.t("topic: No reply yet") : <a href={`/member/${topic?.lastReplyUser}`}>{topic?.lastReplyUser}</a>
}
</span>
</td>
</tr>
{
topic.lastReplyUser !== "" ?
<tr>
<td width="120" align="right">{i18next.t("topic:Last reply time")}</td>
<td width="auto" align="left">
<span className="gray">
{topic?.lastReplyTime}
</span>
</td>
</tr> : null
}
<tr>
<td width="120" align="right">{i18next.t("topic:Reply count")}</td>
<td width="auto" align="left">
<span className="gray">
{topic?.replyCount}
</span>
</td>
</tr>
<tr>
<td width="120" align="right">{i18next.t("topic:Hit count")}</td>
<td width="auto" align="left">
<span className="gray">
{topic?.hitCount}
</span>
</td>
</tr>
<tr>
<td width="120" align="right">{i18next.t("topic:Favorite count")}</td>
<td width="auto" align="left">
<span className="gray">
{topic?.favoriteCount}
</span>
</td>
</tr>
<tr>
<td width="120" align="right">{i18next.t("topic:Hot")}</td>
<td width="auto" align="left">
<span className="gray">
{topic?.hot}
</span>
</td>
</tr>
<tr>
<td width="120" align="right">{i18next.t("topic:Status")}</td>
<td width="auto" align="left">
<span className="gray">
{this.renderTopicStatus(topic?.status, topic?.homePageTopTime, topic?.tabTopTime, topic?.nodeTopTime)}
</span>
</td>
</tr>
<tr>
<td width="120" align="right"></td>
<td width="auto" align="left">
<span className="gray">
{i18next.t("topic:Please change the basic information through the topic page")}
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
);
}
return (
<div>
{this.renderHeader()}
<div className="box">
<div className="inner">
<table cellPadding="5" cellSpacing="0" border="0" width="100%">
<tbody>
<tr>
<td width="120" align="right">
{i18next.t("topic:Title")}
</td>
<td width="500" align="left">
<a href={`/t/${topic?.id}`} target="_blank">
{topic?.title}
</a>
</td>
</tr>
<tr>
<td width="120" align="right"></td>
<td width="120" align="right"></td>
</tr>
<tr>
<td width="120" align="right">
{i18next.t("topic:Content")}
</td>
<td width="500" align="left">
<div className="payload">
<ReactMarkdown
className={"notification"}
renderers={{
image: this.renderImage,
link: this.renderLink
}}
source={Setting.getFormattedContent(this.state.topic?.content, true)}
escapeHtml={false}
/>
</div>
</td>
</tr>
<tr>
<td width="120" align="right"></td>
<td width="120" align="right"></td>
</tr>
<tr>
<td width="120" align="right"></td>
<td width="auto" align="left">
<a href={`/edit/topic/${topic?.id}`} target="_blank">
{i18next.t("topic:Edit")}&nbsp;{" "}&nbsp;
</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
);
}
return (
<div className="box">
<div className="header">
<a href="/">{Setting.getForumName()}</a>
{" "}<span className="chevron">&nbsp;&nbsp;</span>
<a href={`/admin`}>{i18next.t("admin:Backstage management")}</a>
<span className="chevron">&nbsp;&nbsp;</span>{" "}{i18next.t("topic:Topic management")}
<div className="fr f12">
<span className="snow">{i18next.t("topic:Total topics")}{" "}&nbsp;</span>
<strong className="gray">{this.state.topicsNum}</strong>
</div>
</div>
{
this.state.message !== "" ?
<div className="message" onClick={() => this.clearMessage()}>
<li className="fa fa-exclamation-triangle"></li>
&nbsp;{" "}
{this.state.message}
</div> : null
}
<div className="cell">
<Collapse
onChange={() => this.changeShowSearch()}
style={{border: "0", fontSize: "14px", padding: "0", backgroundColor: "#ffffff"}}
>
<Panel header={<span style={{color: "#666"}}>{i18next.t("admin:Condition search")}</span>} >
{
this.renderSearchList()
}
</Panel>
</Collapse>
</div>
{this.showPageColumn()}
<div id="all-tabs">
{
this.state.topics !== null && this.state.topics.length !== 0 ?
this.state.topics.map(topic => this.renderTopics(topic)) :
<div className="cell" style={{textAlign: "center", height: "100px", lineHeight: "100px"}}>
{
this.state.topics === null ?
i18next.t("admin:No matching data") : i18next.t("loading:Data is loading...")
}
</div>
}
</div>
{this.showPageColumn()}
</div>
);
}
}
export default withRouter(AdminTopic);

View File

@ -21,6 +21,19 @@ export function getTopics(limit, page) {
}).then(res => res.json());
}
// un: search with username(author), ti: search with title
// cn: search with content
// sdt: show deleted topics
// cs: sort with created time, lrs: sort with last reply time
// us: sort with username, rcs: sort with reply count
// hs: sort with hot, fcs: sort with favorite count
export function getTopicsAdmin(un, ti, cn, sdt, cs, lrs, us, rcs, hs, fcs, limit, page) {
return fetch(`${Setting.ServerUrl}/api/get-topics-admin?un=${un}&ti=${ti}&cn=${cn}&sdt=${sdt}&cs=${cs}&lrs=${lrs}&us=${us}&rcs=${rcs}&hs=${hs}&fcs=${fcs}&limit=${limit}&page=${page}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function getTopic(id) {
return fetch(`${Setting.ServerUrl}/api/get-topic?id=${id}`, {
method: "GET",
@ -28,6 +41,13 @@ export function getTopic(id) {
}).then(res => res.json());
}
export function getTopicAdmin(id) {
return fetch(`${Setting.ServerUrl}/api/get-topic-admin?id=${id}`, {
method: "GET",
credentials: "include"
}).then(res => res.json());
}
export function updateTopic(id, topic) {
return fetch(`${Setting.ServerUrl}/api/update-topic?id=${id}`, {
method: 'POST',

View File

@ -212,7 +212,29 @@
"CancelNodeTop": "CancelNodeTop",
"words": "words",
"Next": "Next",
"Last": "Last"
"Last": "Last",
"Topic management": "Topic management",
"Author": "Author",
"Title": "Title",
"Content": "Content",
"Show deleted topics": "Show deleted topics",
"Created time": "Created time",
"Reply count": "Reply count",
"Favorite count": "Favorite count",
"Condition search": "Condition search",
"Normal": "Normal",
"Deleted": "Deleted",
"Topping": "Topping",
"Basic Info": "Basic Info",
"Move topic": "Move topic",
"Last reply user": "Last reply user",
"Last reply time": "Last reply time",
"Hit count": "Hit count",
"Status": "Status",
"Topic ID": "Topic ID",
"Edit": "Edit",
"Search": "Search",
"Please change the basic information through the topic page": "Please change the basic information through the topic page"
},
"new":
{
@ -604,7 +626,17 @@
"Topic management": "Topic management",
"Member management": "Member management",
"Tab management": "Tab management",
"Plane management": "Plane management"
"Plane management": "Plane management",
"Get search result success": "Get search result success",
"Sorter": "Sorter",
"Show": "Show",
"Hidden": "Hidden",
"Condition search": "Condition search",
"No matching data": "No matching data",
"Manage": "Manage",
"Asc": "Asc",
"Desc": "Desc",
"Ignore": "Ignore"
},
"error":
{

View File

@ -180,7 +180,7 @@
"Creator": "创建者",
"Node": "所在节点",
"Text syntax format": "正文语法格式",
"Hot": "查看次数",
"Hot": "热度",
"Topic created": "主题已创建",
"Sticky state": "是否处于置顶状态",
"Remaining time to top": "置顶状态剩余时间",
@ -212,7 +212,29 @@
"CancelNodeTop": "取消节点置顶",
"words": "个字符",
"Next": "下一页",
"Last": "上一页"
"Last": "上一页",
"Topic management": "帖子管理",
"Author": "作者",
"Title": "标题",
"Content": "内容",
"Show deleted topics": "显示已删除的主题",
"Created time": "创建时间",
"Reply count": "回复数量",
"Favorite count": "收藏数量",
"Condition search": "条件搜索",
"Normal": "正常",
"Deleted": "已被删除",
"Topping": "已被置顶",
"Basic Info": "基本信息",
"Move topic": "移动主题",
"Last reply user": "最新回复用户",
"Last reply time": "最新回复时间",
"Hit count": "点击量",
"Status": "状态",
"Topic ID": "主题 ID",
"Edit": "编辑",
"Search": "搜索",
"Please change the basic information through the topic page": "请通过主题页面来更改部分信息"
},
"new":
{
@ -604,7 +626,17 @@
"Topic management": "帖子管理",
"Member management": "用户管理",
"Tab management": "类别管理",
"Plane management": "位面管理"
"Plane management": "位面管理",
"Get search result success": "获取搜索结果成功",
"Sorter": "排序",
"Show": "显示",
"Hidden": "隐藏",
"Condition search": "条件搜索",
"No matching data": "没有匹配信息",
"Manage": "管理",
"Asc": "升序",
"Desc": "降序",
"Ignore": "忽略"
},
"error":
{

View File

@ -1873,6 +1873,11 @@ abab@^2.0.0:
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a"
integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==
abbrev@1:
version "1.1.1"
resolved "https://registry.npm.taobao.org/abbrev/download/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
integrity sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=
accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
version "1.3.7"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
@ -2146,11 +2151,19 @@ anymatch@~3.1.1:
normalize-path "^3.0.0"
picomatch "^2.0.4"
aproba@^1.1.1:
aproba@^1.0.3, aproba@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
are-we-there-yet@~1.1.2:
version "1.1.5"
resolved "https://registry.npm.taobao.org/are-we-there-yet/download/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
integrity sha1-SzXClE8GKov82mZBB2A1D+nd/CE=
dependencies:
delegates "^1.0.0"
readable-stream "^2.0.6"
argparse@^1.0.7:
version "1.0.10"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
@ -3231,6 +3244,13 @@ commander@^4.1.1:
resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
commander@~1.1.1:
version "1.1.1"
resolved "https://registry.npm.taobao.org/commander/download/commander-1.1.1.tgz?cache=0&sync_timestamp=1598576059374&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-1.1.1.tgz#50d1651868ae60eccff0a2d9f34595376bc6b041"
integrity sha1-UNFlGGiuYOzP8KLZ80WVN2vGsEE=
dependencies:
keypress "0.1.x"
common-tags@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937"
@ -3308,6 +3328,11 @@ console-browserify@^1.1.0:
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==
console-control-strings@^1.0.0, console-control-strings@~1.1.0:
version "1.1.0"
resolved "https://registry.npm.taobao.org/console-control-strings/download/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
constants-browserify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
@ -3781,7 +3806,7 @@ debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
dependencies:
ms "^2.1.1"
debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5:
debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6:
version "3.2.6"
resolved "https://registry.npm.taobao.org/debug/download/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
integrity sha1-6D0X3hbYp++3cX7b5fsQE17uYps=
@ -3810,6 +3835,11 @@ deep-equal@^1.0.1:
object-keys "^1.1.1"
regexp.prototype.flags "^1.2.0"
deep-extend@^0.6.0:
version "0.6.0"
resolved "https://registry.npm.taobao.org/deep-extend/download/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
integrity sha1-xPp8lUBKF6nD6Mp+FTcxK3NjMKw=
deep-is@~0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
@ -3886,6 +3916,11 @@ delayed-stream@~1.0.0:
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.npm.taobao.org/delegates/download/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
depd@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
@ -3904,6 +3939,11 @@ destroy@^1.0.4, destroy@~1.0.4:
resolved "https://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
detect-libc@^1.0.2:
version "1.0.3"
resolved "https://registry.npm.taobao.org/detect-libc/download/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
detect-newline@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
@ -5032,6 +5072,13 @@ fs-extra@^8.1.0:
jsonfile "^4.0.0"
universalify "^0.1.0"
fs-minipass@^1.2.5:
version "1.2.7"
resolved "https://registry.npm.taobao.org/fs-minipass/download/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
integrity sha1-zP+FcIQef+QmVpPaiJNsVa7X98c=
dependencies:
minipass "^2.6.0"
fs-minipass@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
@ -5085,6 +5132,20 @@ functional-red-black-tree@^1.0.1:
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
gauge@~2.7.3:
version "2.7.4"
resolved "https://registry.npm.taobao.org/gauge/download/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=
dependencies:
aproba "^1.0.3"
console-control-strings "^1.0.0"
has-unicode "^2.0.0"
object-assign "^4.1.0"
signal-exit "^3.0.0"
string-width "^1.0.1"
strip-ansi "^3.0.1"
wide-align "^1.1.0"
gensync@^1.0.0-beta.1:
version "1.0.0-beta.1"
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269"
@ -5288,6 +5349,11 @@ has-symbols@^1.0.0, has-symbols@^1.0.1:
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
has-unicode@^2.0.0:
version "2.0.1"
resolved "https://registry.npm.taobao.org/has-unicode/download/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
has-value@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
@ -5596,7 +5662,7 @@ i18next@^19.6.0:
dependencies:
"@babel/runtime" "^7.10.1"
iconv-lite@0.4.24, iconv-lite@^0.4.15, iconv-lite@^0.4.24:
iconv-lite@0.4.24, iconv-lite@^0.4.15, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
version "0.4.24"
resolved "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.24.tgz?cache=0&sync_timestamp=1594184325364&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=
@ -5627,6 +5693,13 @@ iferr@^0.1.5:
resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE=
ignore-walk@^3.0.1:
version "3.0.3"
resolved "https://registry.npm.taobao.org/ignore-walk/download/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37"
integrity sha1-AX4kRxhL/q3nwjjkrv3R6PlbHjc=
dependencies:
minimatch "^3.0.4"
ignore@^3.3.5:
version "3.3.10"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
@ -5723,7 +5796,7 @@ inherits@2.0.3:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
ini@^1.3.5:
ini@^1.3.5, ini@~1.3.0:
version "1.3.5"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
@ -6842,6 +6915,11 @@ jsx-ast-utils@^2.2.1, jsx-ast-utils@^2.2.3:
array-includes "^3.0.3"
object.assign "^4.1.0"
keypress@0.1.x:
version "0.1.0"
resolved "https://registry.npm.taobao.org/keypress/download/keypress-0.1.0.tgz#4a3188d4291b66b4f65edb99f806aa9ae293592a"
integrity sha1-SjGI1CkbZrT2XtuZ+AaqmuKTWSo=
killable@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
@ -7379,6 +7457,14 @@ minipass-pipeline@^1.2.2:
dependencies:
minipass "^3.0.0"
minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
version "2.9.0"
resolved "https://registry.npm.taobao.org/minipass/download/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
integrity sha1-5xN2Ln0+Mv7YAxFc+T4EvKn8yaY=
dependencies:
safe-buffer "^5.1.2"
yallist "^3.0.0"
minipass@^3.0.0, minipass@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5"
@ -7386,6 +7472,13 @@ minipass@^3.0.0, minipass@^3.1.1:
dependencies:
yallist "^4.0.0"
minizlib@^1.2.1:
version "1.3.3"
resolved "https://registry.npm.taobao.org/minizlib/download/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
integrity sha1-IpDeloGKNMKVUcio0wEha9Zahh0=
dependencies:
minipass "^2.9.0"
mississippi@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
@ -7425,6 +7518,13 @@ mkdirp@0.5.1:
dependencies:
minimist "0.0.8"
mkdirp@^0.5.0:
version "0.5.5"
resolved "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.5.tgz?cache=0&sync_timestamp=1591257007439&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmkdirp%2Fdownload%2Fmkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
integrity sha1-2Rzv1i0UNsoPQWIOJRKI1CAJne8=
dependencies:
minimist "^1.2.5"
mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@~0.5.1:
version "0.5.3"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.3.tgz#5a514b7179259287952881e94410ec5465659f8c"
@ -7507,6 +7607,11 @@ nan@^2.12.1:
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
nan@^2.14.0:
version "2.14.1"
resolved "https://registry.npm.taobao.org/nan/download/nan-2.14.1.tgz?cache=0&sync_timestamp=1587497111086&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnan%2Fdownload%2Fnan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
integrity sha1-174036MQW5FJTDFHCJMV7/iHSwE=
nanomatch@^1.2.9:
version "1.2.13"
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
@ -7529,6 +7634,15 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
needle@^2.2.1:
version "2.5.2"
resolved "https://registry.npm.taobao.org/needle/download/needle-2.5.2.tgz#cf1a8fce382b5a280108bba90a14993c00e4010a"
integrity sha1-zxqPzjgrWigBCLupChSZPADkAQo=
dependencies:
debug "^3.2.6"
iconv-lite "^0.4.4"
sax "^1.2.4"
negotiator@0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
@ -7617,6 +7731,22 @@ node-notifier@^5.4.2:
shellwords "^0.1.1"
which "^1.3.0"
node-pre-gyp@^0.14.0:
version "0.14.0"
resolved "https://registry.npm.taobao.org/node-pre-gyp/download/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83"
integrity sha1-mgWWUzuHcom8rU4UOYLKPZBN3IM=
dependencies:
detect-libc "^1.0.2"
mkdirp "^0.5.1"
needle "^2.2.1"
nopt "^4.0.1"
npm-packlist "^1.1.6"
npmlog "^4.0.2"
rc "^1.2.7"
rimraf "^2.6.1"
semver "^5.3.0"
tar "^4.4.2"
node-releases@^1.1.52:
version "1.1.52"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.52.tgz#bcffee3e0a758e92e44ecfaecd0a47554b0bcba9"
@ -7624,6 +7754,22 @@ node-releases@^1.1.52:
dependencies:
semver "^6.3.0"
nodejieba@^2.2.1:
version "2.4.1"
resolved "https://registry.npm.taobao.org/nodejieba/download/nodejieba-2.4.1.tgz#2c3e422fbcc6d8d449f2d02226da053ba594736c"
integrity sha1-LD5CL7zG2NRJ8tAiJtoFO6WUc2w=
dependencies:
nan "^2.14.0"
node-pre-gyp "^0.14.0"
nopt@^4.0.1:
version "4.0.3"
resolved "https://registry.npm.taobao.org/nopt/download/nopt-4.0.3.tgz?cache=0&sync_timestamp=1597649956050&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnopt%2Fdownload%2Fnopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
integrity sha1-o3XK2dAv2SEnjZVMIlTVqlfhXkg=
dependencies:
abbrev "1"
osenv "^0.1.4"
normalize-package-data@^2.3.2:
version "2.5.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
@ -7666,6 +7812,27 @@ normalize-url@^3.0.0:
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
npm-bundled@^1.0.1:
version "1.1.1"
resolved "https://registry.npm.taobao.org/npm-bundled/download/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b"
integrity sha1-Ht1XCGWpTNsbyCIHdeKUZsn7I0s=
dependencies:
npm-normalize-package-bin "^1.0.1"
npm-normalize-package-bin@^1.0.1:
version "1.0.1"
resolved "https://registry.npm.taobao.org/npm-normalize-package-bin/download/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2"
integrity sha1-bnmkHyP9I1wGIyGCKNp9nCO49uI=
npm-packlist@^1.1.6:
version "1.4.8"
resolved "https://registry.npm.taobao.org/npm-packlist/download/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e"
integrity sha1-Vu5swTW5+YrT1Rwcldoiu7my7z4=
dependencies:
ignore-walk "^3.0.1"
npm-bundled "^1.0.1"
npm-normalize-package-bin "^1.0.1"
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
@ -7673,6 +7840,16 @@ npm-run-path@^2.0.0:
dependencies:
path-key "^2.0.0"
npmlog@^4.0.2:
version "4.1.2"
resolved "https://registry.npm.taobao.org/npmlog/download/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
integrity sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=
dependencies:
are-we-there-yet "~1.1.2"
console-control-strings "~1.1.0"
gauge "~2.7.3"
set-blocking "~2.0.0"
nth-check@^1.0.2, nth-check@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c"
@ -7891,6 +8068,11 @@ os-browserify@^0.3.0:
resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=
os-homedir@^1.0.0:
version "1.0.2"
resolved "https://registry.npm.taobao.org/os-homedir/download/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
os-locale@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
@ -7908,11 +8090,19 @@ os-name@~1.0.3:
osx-release "^1.0.0"
win-release "^1.0.0"
os-tmpdir@~1.0.2:
os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
osenv@^0.1.4:
version "0.1.5"
resolved "https://registry.npm.taobao.org/osenv/download/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
integrity sha1-hc36+uso6Gd/QW4odZK18/SepBA=
dependencies:
os-homedir "^1.0.0"
os-tmpdir "^1.0.0"
osx-release@^1.0.0:
version "1.1.0"
resolved "https://registry.npm.taobao.org/osx-release/download/osx-release-1.1.0.tgz#f217911a28136949af1bf9308b241e2737d3cd6c"
@ -8285,6 +8475,16 @@ pinkie@^2.0.0:
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
pinyin@^2.9.1:
version "2.9.1"
resolved "https://registry.npm.taobao.org/pinyin/download/pinyin-2.9.1.tgz#4570d3e03f1430f69c08d4166b087392c9227718"
integrity sha1-RXDT4D8UMPacCNQWawhzkskidxg=
dependencies:
commander "~1.1.1"
object-assign "^4.0.1"
optionalDependencies:
nodejieba "^2.2.1"
pirates@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87"
@ -9602,6 +9802,16 @@ rc-virtual-list@^1.1.0, rc-virtual-list@^1.1.2:
raf "^3.4.1"
rc-util "^5.0.0"
rc@^1.2.7:
version "1.2.8"
resolved "https://registry.npm.taobao.org/rc/download/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
integrity sha1-zZJL9SAKB1uDwYjNa54hG3/A0+0=
dependencies:
deep-extend "^0.6.0"
ini "~1.3.0"
minimist "^1.2.0"
strip-json-comments "~2.0.1"
re-resizable@^6.5.4:
version "6.5.4"
resolved "https://registry.npm.taobao.org/re-resizable/download/re-resizable-6.5.4.tgz?cache=0&sync_timestamp=1594630415854&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fre-resizable%2Fdownload%2Fre-resizable-6.5.4.tgz#909a1e37f9d1a3afd356893a5779a030167be641"
@ -9891,7 +10101,7 @@ read-pkg@^3.0.0:
normalize-package-data "^2.3.2"
path-type "^3.0.0"
"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
@ -10442,7 +10652,7 @@ selfsigned@^1.10.7:
dependencies:
node-forge "0.9.0"
"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
version "5.7.1"
resolved "https://registry.npm.taobao.org/semver/download/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha1-qVT5Ma66UI0we78Gnv8MAclhFvc=
@ -10504,7 +10714,7 @@ serve-static@1.14.1:
parseurl "~1.3.3"
send "0.17.1"
set-blocking@^2.0.0:
set-blocking@^2.0.0, set-blocking@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
@ -10976,7 +11186,7 @@ string-width@^1.0.1:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
string-width@^2.0.0, string-width@^2.1.1:
"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
@ -11116,6 +11326,11 @@ strip-json-comments@^3.0.1:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7"
integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==
strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.npm.taobao.org/strip-json-comments/download/strip-json-comments-2.0.1.tgz?cache=0&sync_timestamp=1594567586410&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstrip-json-comments%2Fdownload%2Fstrip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
style-loader@0.23.1:
version "0.23.1"
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.1.tgz#cb9154606f3e771ab6c4ab637026a1049174d925"
@ -11203,6 +11418,19 @@ tapable@^1.0.0, tapable@^1.1.3:
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
tar@^4.4.2:
version "4.4.13"
resolved "https://registry.npm.taobao.org/tar/download/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
integrity sha1-Q7NkvFKIjVVSmGN7ENYHkCVKtSU=
dependencies:
chownr "^1.1.1"
fs-minipass "^1.2.5"
minipass "^2.8.6"
minizlib "^1.2.1"
mkdirp "^0.5.0"
safe-buffer "^5.1.2"
yallist "^3.0.3"
terser-webpack-plugin@2.3.5:
version "2.3.5"
resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.5.tgz#5ad971acce5c517440ba873ea4f09687de2f4a81"
@ -12073,6 +12301,13 @@ which@^2.0.1:
dependencies:
isexe "^2.0.0"
wide-align@^1.1.0:
version "1.1.3"
resolved "https://registry.npm.taobao.org/wide-align/download/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
integrity sha1-rgdOa9wMFKQx6ATmJFScYzsABFc=
dependencies:
string-width "^1.0.2 || 2"
win-release@^1.0.0:
version "1.1.1"
resolved "https://registry.npm.taobao.org/win-release/download/win-release-1.1.1.tgz#5fa55e02be7ca934edfc12665632e849b72e5209"
@ -12336,7 +12571,7 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
yallist@^3.0.2:
yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==