mirror of
https://github.com/crawlab-team/crawlab.git
synced 2026-01-21 17:21:09 +01:00
@@ -38,6 +38,7 @@ other:
|
||||
version: 0.4.7
|
||||
setting:
|
||||
allowRegister: "N"
|
||||
enableTutorial: "N"
|
||||
notification:
|
||||
mail:
|
||||
server: ''
|
||||
|
||||
8
backend/entity/doc.go
Normal file
8
backend/entity/doc.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package entity
|
||||
|
||||
type DocItem struct {
|
||||
Title string `json:"title"`
|
||||
Url string `json:"url"`
|
||||
Path string `json:"path"`
|
||||
Children []DocItem `json:"children"`
|
||||
}
|
||||
@@ -135,6 +135,8 @@ func main() {
|
||||
// release版本
|
||||
anonymousGroup.GET("/version", routes.GetVersion) // 获取发布的版本
|
||||
anonymousGroup.GET("/releases/latest", routes.GetLatestRelease) // 获取最近发布的版本
|
||||
// 文档
|
||||
anonymousGroup.GET("/docs", routes.GetDocs) // 获取文档数据
|
||||
}
|
||||
authGroup := app.Group("/", middlewares.AuthorizationMiddleware())
|
||||
{
|
||||
@@ -259,7 +261,6 @@ func main() {
|
||||
authGroup.GET("/git/branches", routes.GetGitBranches) // 获取 Git 分支
|
||||
authGroup.GET("/git/public-key", routes.GetGitSshPublicKey) // 获取 SSH 公钥
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 路由ping
|
||||
|
||||
25
backend/routes/doc.go
Normal file
25
backend/routes/doc.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"crawlab/services"
|
||||
"github.com/apex/log"
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"runtime/debug"
|
||||
)
|
||||
|
||||
func GetDocs(c *gin.Context) {
|
||||
type ResData struct {
|
||||
String string `json:"string"`
|
||||
}
|
||||
data, err := services.GetDocs()
|
||||
if err != nil {
|
||||
log.Errorf(err.Error())
|
||||
debug.PrintStack()
|
||||
}
|
||||
c.JSON(http.StatusOK, Response{
|
||||
Status: "ok",
|
||||
Message: "success",
|
||||
Data: ResData{String:data},
|
||||
})
|
||||
}
|
||||
@@ -7,7 +7,8 @@ import (
|
||||
)
|
||||
|
||||
type SettingBody struct {
|
||||
AllowRegister string `json:"allow_register"`
|
||||
AllowRegister string `json:"allow_register"`
|
||||
EnableTutorial string `json:"enable_tutorial"`
|
||||
}
|
||||
|
||||
func GetVersion(c *gin.Context) {
|
||||
@@ -21,9 +22,10 @@ func GetVersion(c *gin.Context) {
|
||||
}
|
||||
|
||||
func GetSetting(c *gin.Context) {
|
||||
allowRegister := viper.GetString("setting.allowRegister")
|
||||
|
||||
body := SettingBody{AllowRegister: allowRegister}
|
||||
body := SettingBody{
|
||||
AllowRegister: viper.GetString("setting.allowRegister"),
|
||||
EnableTutorial: viper.GetString("setting.enableTutorial"),
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, Response{
|
||||
Status: "ok",
|
||||
|
||||
27
backend/services/doc.go
Normal file
27
backend/services/doc.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"github.com/apex/log"
|
||||
"github.com/imroc/req"
|
||||
"runtime/debug"
|
||||
)
|
||||
|
||||
func GetDocs() (data string, err error) {
|
||||
// 获取远端数据
|
||||
res, err := req.Get("https://docs.crawlab.cn/search_plus_index.json")
|
||||
if err != nil {
|
||||
log.Errorf(err.Error())
|
||||
debug.PrintStack()
|
||||
return data, err
|
||||
}
|
||||
|
||||
// 反序列化
|
||||
data, err = res.ToString()
|
||||
if err != nil {
|
||||
log.Errorf(err.Error())
|
||||
debug.PrintStack()
|
||||
return data, err
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
@@ -24,6 +24,7 @@ services:
|
||||
# CRAWLAB_TASK_WORKERS: 4 # number of task executors 任务执行器个数(并行执行任务数)
|
||||
# CRAWLAB_SERVER_LANG_NODE: "Y" # whether to pre-install Node.js 预安装 Node.js 语言环境
|
||||
# CRAWLAB_SETTING_ALLOWREGISTER: "N" # whether to allow user registration 是否允许用户注册
|
||||
# CRAWLAB_SETTING_ENABLETUTORIAL: "N" # whether to enable tutorial 是否启用教程
|
||||
# CRAWLAB_NOTIFICATION_MAIL_SERVER: smtp.exmaple.com # STMP server address STMP 服务器地址
|
||||
# CRAWLAB_NOTIFICATION_MAIL_PORT: 465 # STMP server port STMP 服务器端口
|
||||
# CRAWLAB_NOTIFICATION_MAIL_SENDEREMAIL: admin@exmaple.com # sender email 发送者邮箱
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
NODE_ENV='development'
|
||||
VUE_APP_BASE_URL=http://localhost:8000
|
||||
VUE_APP_CRAWLAB_BASE_URL=https://api.crawlab.cn
|
||||
VUE_APP_CRAWLAB_BASE_URL=https://api.crawlab.cn
|
||||
VUE_APP_DOC_URL=http://docs.crawlab.cn
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
NODE_ENV='production'
|
||||
VUE_APP_BASE_URL=/api
|
||||
VUE_APP_CRAWLAB_BASE_URL=https://api.crawlab.cn
|
||||
VUE_APP_DOC_URL=http://docs.crawlab.cn
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
NODE_ENV='test'
|
||||
VUE_APP_BASE_URL='http://localhost:8000'
|
||||
VUE_APP_CRAWLAB_BASE_URL=https://api.crawlab.cn
|
||||
VUE_APP_DOC_URL=http://docs.crawlab.cn
|
||||
|
||||
114
frontend/src/components/Documentation/Documentation.vue
Normal file
114
frontend/src/components/Documentation/Documentation.vue
Normal file
@@ -0,0 +1,114 @@
|
||||
<template>
|
||||
<el-tree
|
||||
:data="docData"
|
||||
ref="documentation-tree"
|
||||
node-key="fullUrl"
|
||||
>
|
||||
<span class="custom-tree-node" :class="[data.active ? 'active' : '', `level-${data.level}`]"
|
||||
slot-scope="{ node, data }">
|
||||
<template v-if="data.level === 1 && data.children && data.children.length">
|
||||
<span>{{node.label}}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>
|
||||
<a :href="data.fullUrl" target="_blank" style="display: block" @click="onClickDocumentationLink">
|
||||
{{node.label}}
|
||||
</a>
|
||||
</span>
|
||||
</template>
|
||||
</span>
|
||||
</el-tree>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState
|
||||
} from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'Documentation',
|
||||
data () {
|
||||
return {
|
||||
data: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState('doc', [
|
||||
'docData'
|
||||
]),
|
||||
pathLv1 () {
|
||||
if (this.$route.path === '/') return '/'
|
||||
const m = this.$route.path.match(/(^\/\w+)/)
|
||||
return m[1]
|
||||
},
|
||||
currentDoc () {
|
||||
// find current doc
|
||||
let currentDoc
|
||||
for (let i = 0; i < this.$utils.doc.docs.length; i++) {
|
||||
const doc = this.$utils.doc.docs[i]
|
||||
if (this.pathLv1 === doc.path) {
|
||||
currentDoc = doc
|
||||
break
|
||||
}
|
||||
}
|
||||
return currentDoc
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
pathLv1 () {
|
||||
this.update()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isActiveNode (d) {
|
||||
// check match
|
||||
if (!this.currentDoc) return false
|
||||
return !!d.url.match(this.currentDoc.pattern)
|
||||
},
|
||||
update () {
|
||||
// expand related documentation list
|
||||
setTimeout(() => {
|
||||
this.docData.forEach(d => {
|
||||
// parent node
|
||||
const isActive = this.isActiveNode(d)
|
||||
const node = this.$refs['documentation-tree'].getNode(d)
|
||||
node.expanded = isActive
|
||||
this.$set(d, 'active', isActive)
|
||||
|
||||
// child nodes
|
||||
d.children.forEach(c => {
|
||||
const node = this.$refs['documentation-tree'].getNode(c)
|
||||
const isActive = this.isActiveNode(c)
|
||||
if (!node.parent.expanded && isActive) {
|
||||
node.parent.expanded = true
|
||||
}
|
||||
this.$set(c, 'active', isActive)
|
||||
})
|
||||
})
|
||||
}, 100)
|
||||
},
|
||||
async getDocumentationData () {
|
||||
// fetch api data
|
||||
await this.$store.dispatch('doc/getDocData')
|
||||
},
|
||||
onClickDocumentationLink () {
|
||||
this.$st.sendEv('全局', '点击右侧文档链接')
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
},
|
||||
mounted () {
|
||||
this.update()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.el-tree >>> .custom-tree-node.active {
|
||||
color: #409eff;
|
||||
/*text-decoration: underline;*/
|
||||
}
|
||||
|
||||
.el-tree >>> .custom-tree-node.level-1 {
|
||||
font-weight: bolder;
|
||||
}
|
||||
</style>
|
||||
@@ -448,6 +448,11 @@ export default {
|
||||
'Key': '设置',
|
||||
'Allow Sending Statistics': '允许发送统计信息',
|
||||
'General': '通用',
|
||||
'Enable Tutorial': '启用教程',
|
||||
|
||||
// 全局
|
||||
'Related Documentation': '相关文档',
|
||||
'Click to view related Documentation': '点击查看相关文档',
|
||||
|
||||
// 其他
|
||||
tagsView: {
|
||||
|
||||
@@ -17,6 +17,7 @@ import setting from './modules/setting'
|
||||
import version from './modules/version'
|
||||
import tour from './modules/tour'
|
||||
import project from './modules/project'
|
||||
import doc from './modules/doc'
|
||||
import getters from './getters'
|
||||
|
||||
Vue.use(Vuex)
|
||||
@@ -39,6 +40,7 @@ const store = new Vuex.Store({
|
||||
version,
|
||||
tour,
|
||||
project,
|
||||
doc,
|
||||
// 统计
|
||||
stats
|
||||
},
|
||||
|
||||
61
frontend/src/store/modules/doc.js
Normal file
61
frontend/src/store/modules/doc.js
Normal file
@@ -0,0 +1,61 @@
|
||||
import request from '../../api/request'
|
||||
|
||||
const state = {
|
||||
docData: []
|
||||
}
|
||||
|
||||
const getters = {}
|
||||
|
||||
const mutations = {
|
||||
SET_DOC_DATA (state, value) {
|
||||
state.docData = value
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
async getDocData ({ commit }) {
|
||||
const res = await request.get('/docs')
|
||||
|
||||
const data = JSON.parse(res.data.data.string)
|
||||
|
||||
// init cache
|
||||
const cache = {}
|
||||
|
||||
// iterate paths
|
||||
for (let path in data) {
|
||||
if (data.hasOwnProperty(path)) {
|
||||
const d = data[path]
|
||||
if (path.match(/\/$/)) {
|
||||
cache[path] = d
|
||||
cache[path].children = []
|
||||
} else if (path.match(/\.html$/)) {
|
||||
const parentPath = path.split('/')[0] + '/'
|
||||
cache[parentPath].children.push(d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
commit('SET_DOC_DATA', Object.values(cache).map(d => {
|
||||
d.level = 1
|
||||
d.label = d.title
|
||||
d.fullUrl = process.env.VUE_APP_DOC_URL + '/' + d.url
|
||||
if (d.children) {
|
||||
d.children = d.children.map(c => {
|
||||
c.level = 2
|
||||
c.label = c.title
|
||||
c.fullUrl = process.env.VUE_APP_DOC_URL + '/' + c.url
|
||||
return c
|
||||
})
|
||||
}
|
||||
return d
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
getters,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
@@ -16,6 +16,12 @@ const actions = {
|
||||
async getSetting ({ commit }) {
|
||||
const res = await request.get('/setting')
|
||||
commit('SET_SETTING', res.data.data)
|
||||
|
||||
// set default enable_tutorial
|
||||
const enableTutorial = res.data.data.enable_tutorial
|
||||
if (!localStorage.getItem('enableTutorial')) {
|
||||
localStorage.setItem('enableTutorial', enableTutorial === 'Y' ? '1' : '0')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
28
frontend/src/utils/doc.js
Normal file
28
frontend/src/utils/doc.js
Normal file
@@ -0,0 +1,28 @@
|
||||
export default {
|
||||
docs: [
|
||||
{
|
||||
path: '/projects',
|
||||
pattern: '^Project'
|
||||
},
|
||||
{
|
||||
path: '/spiders',
|
||||
pattern: '^Spider|^SDK|^Integration|^CI/Git'
|
||||
},
|
||||
{
|
||||
path: '/tasks',
|
||||
pattern: '^Task|^Architecture/Task'
|
||||
},
|
||||
{
|
||||
path: '/schedules',
|
||||
pattern: '^Schedule'
|
||||
},
|
||||
{
|
||||
path: '/nodes',
|
||||
pattern: '^Node|^Architecture/Node'
|
||||
},
|
||||
{
|
||||
path: '/setting',
|
||||
pattern: '^Notification'
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3,11 +3,13 @@ import encrypt from './encrypt'
|
||||
import tour from './tour'
|
||||
import log from './log'
|
||||
import scrapy from './scrapy'
|
||||
import doc from './doc'
|
||||
|
||||
export default {
|
||||
stats,
|
||||
encrypt,
|
||||
tour,
|
||||
log,
|
||||
scrapy
|
||||
scrapy,
|
||||
doc
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ export default {
|
||||
}
|
||||
return !!data[tourName]
|
||||
},
|
||||
startTour: (vm, tourName) => {
|
||||
if (localStorage.getItem('enableTutorial') === '0') return
|
||||
vm.$tours[tourName].start()
|
||||
},
|
||||
finishTour: (tourName) => {
|
||||
let data
|
||||
try {
|
||||
|
||||
@@ -1,12 +1,36 @@
|
||||
<template>
|
||||
<div :class="classObj" class="app-wrapper">
|
||||
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"></div>
|
||||
|
||||
<!--sidebar-->
|
||||
<sidebar class="sidebar-container"/>
|
||||
<!--./sidebar-->
|
||||
|
||||
<!--main container-->
|
||||
<div class="main-container">
|
||||
<navbar/>
|
||||
<tags-view/>
|
||||
<app-main/>
|
||||
</div>
|
||||
<!--./main container-->
|
||||
|
||||
<!--documentation-->
|
||||
<div class="documentation">
|
||||
<el-tooltip
|
||||
:content="$t('Click to view related Documentation')"
|
||||
>
|
||||
<i class="el-icon-question" @click="onClickDocumentation"></i>
|
||||
</el-tooltip>
|
||||
<el-drawer
|
||||
:title="$t('Related Documentation')"
|
||||
:visible.sync="isShowDocumentation"
|
||||
:before-close="onCloseDocumentation"
|
||||
size="300px"
|
||||
>
|
||||
<documentation/>
|
||||
</el-drawer>
|
||||
</div>
|
||||
<!--./documentation-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -18,16 +42,23 @@ import {
|
||||
TagsView
|
||||
} from './components'
|
||||
import ResizeMixin from './mixin/ResizeHandler'
|
||||
import Documentation from '../../components/Documentation/Documentation'
|
||||
|
||||
export default {
|
||||
name: 'Layout',
|
||||
components: {
|
||||
Documentation,
|
||||
Navbar,
|
||||
Sidebar,
|
||||
TagsView,
|
||||
AppMain
|
||||
},
|
||||
mixins: [ResizeMixin],
|
||||
data () {
|
||||
return {
|
||||
isShowDocumentation: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
sidebar () {
|
||||
return this.$store.state.app.sidebar
|
||||
@@ -47,7 +78,18 @@ export default {
|
||||
methods: {
|
||||
handleClickOutside () {
|
||||
this.$store.dispatch('CloseSideBar', { withoutAnimation: false })
|
||||
},
|
||||
onClickDocumentation () {
|
||||
this.isShowDocumentation = true
|
||||
this.$st.sendEv('全局', '打开右侧文档')
|
||||
},
|
||||
onCloseDocumentation () {
|
||||
this.isShowDocumentation = false
|
||||
this.$st.sendEv('全局', '关闭右侧文档')
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
await this.$store.dispatch('doc/getDocData')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -77,4 +119,45 @@ export default {
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.documentation {
|
||||
z-index: 9999;
|
||||
position: fixed;
|
||||
right: 25px;
|
||||
bottom: 20px;
|
||||
font-size: 32px;
|
||||
cursor: pointer;
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
.documentation >>> .el-drawer__body {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.documentation >>> span[role="heading"]:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.documentation >>> .el-tree-node__content {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
.documentation >>> .custom-tree-node {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.documentation >>> .custom-tree-node a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.documentation >>> .custom-tree-node:hover a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -124,7 +124,7 @@ export default {
|
||||
},
|
||||
mounted () {
|
||||
if (!this.$utils.tour.isFinishedTour('node-detail')) {
|
||||
this.$tours['node-detail'].start()
|
||||
this.$utils.tour.startTour(this, 'node-detail')
|
||||
this.$st.sendEv('教程', '开始', 'node-detail')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -467,7 +467,7 @@ export default {
|
||||
|
||||
if (!this.$utils.tour.isFinishedTour('schedule-list-add')) {
|
||||
setTimeout(() => {
|
||||
this.$tours['schedule-list-add'].start()
|
||||
this.$utils.tour.startTour(this, 'schedule-list-add')
|
||||
this.$st.sendEv('教程', '开始', 'schedule-list-add')
|
||||
}, 500)
|
||||
}
|
||||
@@ -617,7 +617,7 @@ export default {
|
||||
mounted () {
|
||||
if (!this.isDisabledSpiderSchedule) {
|
||||
if (!this.$utils.tour.isFinishedTour('schedule-list')) {
|
||||
this.$tours['schedule-list'].start()
|
||||
this.$utils.tour.startTour(this, 'schedule-list')
|
||||
this.$st.sendEv('教程', '开始', 'schedule-list')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/>
|
||||
<!--./tour-->
|
||||
|
||||
<!-- 新增全局变量 -->
|
||||
<!--新增全局变量-->
|
||||
<el-dialog :title="$t('Add Global Variable')"
|
||||
:visible.sync="addDialogVisible">
|
||||
<el-form label-width="80px" ref="globalVariableForm">
|
||||
@@ -30,6 +30,7 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
<!--./新增全局变量-->
|
||||
|
||||
<el-tabs v-model="activeName" @tab-click="tabActiveHandle" type="border-card">
|
||||
<el-tab-pane :label="$t('General')" name="general">
|
||||
@@ -49,6 +50,14 @@
|
||||
inactive-color="#909399"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('Enable Tutorial')">
|
||||
<el-switch
|
||||
v-model="isEnableTutorial"
|
||||
@change="onEnableTutorialChange"
|
||||
active-color="#67C23A"
|
||||
inactive-color="#909399"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div style="text-align: right">
|
||||
<el-button type="success" size="small" @click="saveUserInfo">
|
||||
@@ -213,7 +222,8 @@ export default {
|
||||
this.$utils.tour.nextStep('setting', currentStep)
|
||||
}
|
||||
},
|
||||
isAllowSendingStatistics: localStorage.getItem('useStats') === '1'
|
||||
isAllowSendingStatistics: localStorage.getItem('useStats') === '1',
|
||||
isEnableTutorial: localStorage.getItem('enableTutorial') === '1'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -291,6 +301,10 @@ export default {
|
||||
}
|
||||
this.$message.success(this.$t('Saved successfully'))
|
||||
localStorage.setItem('useStats', value ? '1' : '0')
|
||||
},
|
||||
onEnableTutorialChange (value) {
|
||||
this.$message.success(this.$t('Saved successfully'))
|
||||
localStorage.setItem('enableTutorial', value ? '1' : '0')
|
||||
}
|
||||
},
|
||||
async created () {
|
||||
@@ -300,7 +314,7 @@ export default {
|
||||
},
|
||||
mounted () {
|
||||
if (!this.$utils.tour.isFinishedTour('setting')) {
|
||||
this.$tours['setting'].start()
|
||||
this.$utils.tour.startTour(this, 'setting')
|
||||
this.$st.sendEv('教程', '开始', 'setting')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ export default {
|
||||
|
||||
if (!this.$utils.tour.isFinishedTour('spider-detail-config')) {
|
||||
setTimeout(() => {
|
||||
this.$tours['spider-detail-config'].start()
|
||||
this.$utils.tour.startTour(this, 'spider-detail-config')
|
||||
this.$st.sendEv('教程', '开始', 'spider-detail-config')
|
||||
}, 100)
|
||||
}
|
||||
@@ -260,7 +260,7 @@ export default {
|
||||
},
|
||||
mounted () {
|
||||
if (!this.$utils.tour.isFinishedTour('spider-detail')) {
|
||||
this.$tours['spider-detail'].start()
|
||||
this.$utils.tour.startTour(this, 'spider-detail')
|
||||
this.$st.sendEv('教程', '开始', 'spider-detail')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -887,7 +887,7 @@ export default {
|
||||
|
||||
setTimeout(() => {
|
||||
if (!this.$utils.tour.isFinishedTour('spider-list-add')) {
|
||||
this.$tours['spider-list-add'].start()
|
||||
this.$utils.tour.startTour(this, 'spider-list-add')
|
||||
this.$st.sendEv('教程', '开始', 'spider-list-add')
|
||||
}
|
||||
}, 300)
|
||||
@@ -1241,7 +1241,7 @@ export default {
|
||||
})
|
||||
|
||||
if (!this.$utils.tour.isFinishedTour('spider-list')) {
|
||||
this.$tours['spider-list'].start()
|
||||
this.$utils.tour.startTour(this, 'spider-list')
|
||||
this.$st.sendEv('教程', '开始', 'spider-list')
|
||||
}
|
||||
},
|
||||
|
||||
@@ -202,7 +202,7 @@ export default {
|
||||
},
|
||||
mounted () {
|
||||
if (!this.$utils.tour.isFinishedTour('task-detail')) {
|
||||
this.$tours['task-detail'].start()
|
||||
this.$utils.tour.startTour(this, 'task-detail')
|
||||
this.$st.sendEv('教程', '开始', 'task-detail')
|
||||
}
|
||||
},
|
||||
|
||||
@@ -412,7 +412,7 @@ export default {
|
||||
}, 5000)
|
||||
|
||||
if (!this.$utils.tour.isFinishedTour('task-list')) {
|
||||
this.$tours['task-list'].start()
|
||||
this.$utils.tour.startTour(this, 'task-list')
|
||||
this.$st.sendEv('教程', '开始', 'task-list')
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user