优化项目管理

This commit is contained in:
marvzhang
2020-02-02 14:04:38 +08:00
parent 024f9ac3b2
commit 18c8dd6253
6 changed files with 103 additions and 18 deletions

View File

@@ -2,6 +2,7 @@
### 功能 / 优化
- **交互式教程**. 引导用户了解 Crawlab 的主要功能.
- **加入全局环境变量**. 可以设置全局环境变量,然后传入到所有爬虫程序中. [#177](https://github.com/crawlab-team/crawlab/issues/177)
- **项目**. 允许用户将爬虫关联到项目上. [#316](https://github.com/crawlab-team/crawlab/issues/316)
- **用户管理优化**. 限制管理用户的权限. [#456](https://github.com/crawlab-team/crawlab/issues/456)
- **设置页面优化**.

View File

@@ -2,6 +2,7 @@
### Features / Enhancement
- **Interactive Tutorial**. Guide users through the main functionalities of Crawlab.
- **Global Environment Variables**. Allow users to set global environment variables, which will be passed into all spider programs. [#177](https://github.com/crawlab-team/crawlab/issues/177)
- **Project**. Allow users to link spiders to projects. [#316](https://github.com/crawlab-team/crawlab/issues/316)
- **User Admin Optimization**. Restrict privilleges of admin users. [#456](https://github.com/crawlab-team/crawlab/issues/456)
- **Setting Page Optimization**.

View File

@@ -232,6 +232,7 @@ func main() {
// 项目
{
authGroup.GET("/projects", routes.GetProjectList) // 列表
authGroup.GET("/projects/tags", routes.GetProjectTags) // 项目标签
authGroup.PUT("/projects", routes.PutProject) //修改
authGroup.POST("/projects/:id", routes.PostProject) // 新增
authGroup.DELETE("/projects/:id", routes.DeleteProject) //删除

View File

@@ -2,6 +2,7 @@ package routes
import (
"crawlab/constants"
"crawlab/database"
"crawlab/model"
"github.com/gin-gonic/gin"
"github.com/globalsign/mgo/bson"
@@ -9,15 +10,23 @@ import (
)
func GetProjectList(c *gin.Context) {
tag := c.Query("tag")
// 筛选条件
query := bson.M{}
if tag != "" {
query["tags"] = tag
}
// 获取列表
projects, err := model.GetProjectList(nil, 0, "+_id")
projects, err := model.GetProjectList(query, 0, "+_id")
if err != nil {
HandleError(http.StatusInternalServerError, c, err)
return
}
// 获取总数
total, err := model.GetProjectListTotal(nil)
total, err := model.GetProjectListTotal(query)
if err != nil {
HandleError(http.StatusInternalServerError, c, err)
return
@@ -34,18 +43,20 @@ func GetProjectList(c *gin.Context) {
}
// 获取未被分配的爬虫数量
noProject := model.Project{
Id: bson.ObjectIdHex(constants.ObjectIdNull),
Name: "No Project",
Description: "Not assigned to any project",
if tag == "" {
noProject := model.Project{
Id: bson.ObjectIdHex(constants.ObjectIdNull),
Name: "No Project",
Description: "Not assigned to any project",
}
spiders, err := noProject.GetSpiders()
if err != nil {
HandleError(http.StatusInternalServerError, c, err)
return
}
noProject.Spiders = spiders
projects = append(projects, noProject)
}
spiders, err := noProject.GetSpiders()
if err != nil {
HandleError(http.StatusInternalServerError, c, err)
return
}
noProject.Spiders = spiders
projects = append(projects, noProject)
c.JSON(http.StatusOK, ListResponse{
Status: "ok",
@@ -117,3 +128,45 @@ func DeleteProject(c *gin.Context) {
Message: "success",
})
}
func GetProjectTags(c *gin.Context) {
type Result struct {
Tag string `json:"tag" bson:"tag"`
}
s, col := database.GetCol("projects")
defer s.Close()
pipeline := []bson.M{
{
"$unwind": "$tags",
},
{
"$group": bson.M{
"_id": "$tags",
},
},
{
"$sort": bson.M{
"_id": 1,
},
},
{
"$addFields": bson.M{
"tag": "$_id",
},
},
}
var items []Result
if err := col.Pipe(pipeline).All(&items); err != nil {
HandleError(http.StatusInternalServerError, c, err)
return
}
c.JSON(http.StatusOK, Response{
Status: "ok",
Message: "success",
Data: items,
})
}

View File

@@ -219,6 +219,9 @@ export default {
// 部署
'Time': '时间',
// 项目
'All Tags': '全部标签',
// 定时任务
'Schedule Name': '定时任务名称',
'Schedule Description': '定时任务描述',

View File

@@ -43,7 +43,23 @@
<!--./add popup-->
<div class="action-wrapper">
<div class="buttons">
<div class="left">
<el-select
v-model="filter.tag"
size="small"
:placeholder="$t('Select Tag')"
@change="onFilterChange"
>
<el-option value="" :label="$t('All Tags')"/>
<el-option
v-for="tag in projectTags"
:key="tag"
:label="tag"
:value="tag"
/>
</el-select>
</div>
<div class="right">
<el-button
icon="el-icon-plus"
type="primary"
@@ -112,19 +128,27 @@ export default {
data () {
return {
defaultTags: [],
dialogVisible: false
dialogVisible: false,
filter: {
tag: ''
}
}
},
computed: {
...mapState('project', [
'projectForm',
'projectList'
'projectList',
'projectTags'
])
},
methods: {
onDialogClose () {
this.dialogVisible = false
},
onFilterChange () {
this.$store.dispatch('project/getProjectList', this.filter)
this.$st.sendEv('项目', '筛选项目')
},
onAdd () {
this.isEdit = false
this.dialogVisible = true
@@ -193,14 +217,16 @@ export default {
}
},
async created () {
await this.$store.dispatch('project/getProjectList')
await this.$store.dispatch('project/getProjectList', this.filter)
await this.$store.dispatch('project/getProjectTags')
}
}
</script>
<style scoped>
.action-wrapper {
text-align: right;
display: flex;
justify-content: space-between;
padding-bottom: 10px;
border-bottom: 1px solid #EBEEF5;
}