pref: optimize menus page, categories page, tags page, etc. (halo-dev/console#212)

pull/3445/head
Ryan Wang 2020-07-11 18:48:22 +08:00 committed by GitHub
parent ba1cb7f8e8
commit d42f819907
6 changed files with 544 additions and 393 deletions

View File

@ -13,86 +13,105 @@
:title="title" :title="title"
:bodyStyle="{ padding: '16px' }" :bodyStyle="{ padding: '16px' }"
> >
<a-form layout="horizontal"> <a-form-model
<a-form-item ref="menuForm"
:model="form.model"
:rules="form.rules"
layout="horizontal"
>
<a-form-model-item
label="名称:" label="名称:"
help="* 页面上所显示的名称" help="* 页面上所显示的名称"
prop="name"
> >
<a-input v-model="menuToCreate.name" /> <a-input v-model="form.model.name" />
</a-form-item> </a-form-model-item>
<a-form-item <a-form-model-item
label="地址:" label="地址:"
help="* 菜单的地址" help="* 菜单的地址"
prop="url"
>
<a-input v-model="form.model.url" />
</a-form-model-item>
<a-form-model-item
label="上级菜单:"
prop="parentId"
> >
<a-input v-model="menuToCreate.url" />
</a-form-item>
<a-form-item label="上级菜单:">
<menu-select-tree <menu-select-tree
:menus="menus" :menus="table.data"
v-model="menuToCreate.parentId" v-model="form.model.parentId"
/> />
</a-form-item> </a-form-model-item>
<a-form-item label="排序编号:"> <a-form-model-item
<a-input label="排序编号:"
type="number" prop="priority"
v-model="menuToCreate.priority" >
<a-input-number
v-model="form.model.priority"
:min="0"
style="width:100%"
/> />
</a-form-item> </a-form-model-item>
<a-form-item <a-form-model-item
v-show="form.moreField"
label="图标:" label="图标:"
help="* 请根据主题的支持选填" help="* 请根据主题的支持选填"
:style="{ display: fieldExpand ? 'block' : 'none' }" prop="icon"
> >
<a-input v-model="menuToCreate.icon" /> <a-input v-model="form.model.icon" />
</a-form-item> </a-form-model-item>
<a-form-item <a-form-model-item
v-show="form.moreField"
label="分组:" label="分组:"
:style="{ display: fieldExpand ? 'block' : 'none' }" prop="team"
> >
<a-auto-complete <a-auto-complete
:dataSource="teams" :dataSource="teams.data"
v-model="menuToCreate.team" v-model="form.model.team"
allowClear allowClear
/> />
</a-form-item> </a-form-model-item>
<a-form-item <a-form-model-item
v-show="form.moreField"
label="打开方式:" label="打开方式:"
:style="{ display: fieldExpand ? 'block' : 'none' }" prop="target"
> >
<a-select <a-select
defaultValue="_self" defaultValue="_self"
v-model="menuToCreate.target" v-model="form.model.target"
> >
<a-select-option value="_self">当前窗口</a-select-option> <a-select-option value="_self">当前窗口</a-select-option>
<a-select-option value="_blank">新窗口</a-select-option> <a-select-option value="_blank">新窗口</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-model-item>
<a-form-item> <a-form-model-item>
<a-button <a-button
type="primary" type="primary"
@click="handleSaveClick" @click="handleCreateOrUpdateMenu"
v-if="formType==='create'" v-if="!isUpdateMode"
:loading="form.saving"
>保存</a-button> >保存</a-button>
<a-button-group v-else> <a-button-group v-else>
<a-button <a-button
type="primary" type="primary"
@click="handleSaveClick" @click="handleCreateOrUpdateMenu"
:loading="form.saving"
>更新</a-button> >更新</a-button>
<a-button <a-button
type="dashed" type="dashed"
@click="handleAddMenu" @click="form.model = {}"
v-if="formType==='update'" v-if="isUpdateMode"
>返回添加</a-button> >返回添加</a-button>
</a-button-group> </a-button-group>
<a <a
:style="{ marginLeft: '8px'}" :style="{ marginLeft: '8px'}"
@click="toggleExpand" @click="form.moreField = !form.moreField"
> >
更多选项 更多选项
<a-icon :type="fieldExpand ? 'up' : 'down'" /> <a-icon :type="form.moreField ? 'up' : 'down'" />
</a> </a>
</a-form-item> </a-form-model-item>
</a-form> </a-form-model>
</a-card> </a-card>
</a-col> </a-col>
<a-col <a-col
@ -113,8 +132,8 @@
itemLayout="vertical" itemLayout="vertical"
size="large" size="large"
:pagination="false" :pagination="false"
:dataSource="menus" :dataSource="table.data"
:loading="loading" :loading="table.loading"
> >
<a-list-item <a-list-item
slot="renderItem" slot="renderItem"
@ -133,7 +152,7 @@
<a-menu-item> <a-menu-item>
<a <a
href="javascript:;" href="javascript:;"
@click="handleEditMenu(item)" @click="form.model = item"
>编辑</a> >编辑</a>
</a-menu-item> </a-menu-item>
<a-menu-item> <a-menu-item>
@ -146,7 +165,6 @@
<a href="javascript:;">删除</a> <a href="javascript:;">删除</a>
</a-popconfirm> </a-popconfirm>
</a-menu-item> </a-menu-item>
</a-menu> </a-menu>
</a-dropdown> </a-dropdown>
</template> </template>
@ -171,9 +189,9 @@
<!-- Desktop --> <!-- Desktop -->
<a-table <a-table
v-else v-else
:columns="columns" :columns="table.columns"
:dataSource="menus" :dataSource="table.data"
:loading="loading" :loading="table.loading"
:rowKey="menu => menu.id" :rowKey="menu => menu.id"
:scrollToFirstRowOnChange="true" :scrollToFirstRowOnChange="true"
> >
@ -183,7 +201,7 @@
> >
<a <a
href="javascript:;" href="javascript:;"
@click="handleEditMenu(record)" @click="form.model = record"
>编辑</a> >编辑</a>
<a-divider type="vertical" /> <a-divider type="vertical" />
<a-popconfirm <a-popconfirm
@ -238,92 +256,116 @@ export default {
mixins: [mixin, mixinDevice], mixins: [mixin, mixinDevice],
data() { data() {
return { return {
formType: 'create', table: {
loading: false, columns,
columns, data: [],
menus: [], loading: false
menuToCreate: {
target: '_self'
}, },
fieldExpand: false, form: {
teams: [] model: {
target: '_self'
},
saving: false,
rules: {
name: [
{ required: true, message: '* 菜单名称不能为空', trigger: ['change', 'blur'] },
{ max: 50, message: '* 菜单名称的字符长度不能超过 50', trigger: ['change', 'blur'] }
],
url: [
{ required: true, message: '* 菜单地址不能为空', trigger: ['change', 'blur'] },
{ max: 1023, message: '* 菜单地址的字符长度不能超过 1023', trigger: ['change', 'blur'] }
],
icon: [{ max: 50, message: '* 菜单图标的字符长度不能超过 50', trigger: ['change', 'blur'] }],
team: [{ max: 255, message: '* 菜单分组的字符长度不能超过 255', trigger: ['change', 'blur'] }]
},
moreField: false
},
teams: {
data: []
}
} }
}, },
computed: { computed: {
title() { title() {
if (this.menuToCreate.id) { if (this.isUpdateMode) {
return '修改菜单' return '修改菜单'
} }
return '添加菜单' return '添加菜单'
},
isUpdateMode() {
return !!this.form.model.id
} }
}, },
created() { created() {
this.loadMenus() this.handleListMenus()
this.loadTeams() this.handleListTeams()
}, },
methods: { methods: {
loadMenus() { handleListMenus() {
this.loading = true this.table.loading = true
menuApi.listTree().then(response => { menuApi
this.menus = response.data.data .listTree()
this.loading = false .then(response => {
}) this.table.data = response.data.data
})
.finally(() => {
setTimeout(() => {
this.table.loading = false
}, 200)
})
}, },
loadTeams() { handleListTeams() {
menuApi.listTeams().then(response => { menuApi.listTeams().then(response => {
this.teams = response.data.data this.teams.data = response.data.data
}) })
}, },
handleSaveClick() {
this.createOrUpdateMenu()
},
handleAddMenu() {
this.formType = 'create'
this.menuToCreate = {}
},
handleEditMenu(menu) {
this.menuToCreate = menu
this.formType = 'update'
},
handleDeleteMenu(id) { handleDeleteMenu(id) {
menuApi.delete(id).then(response => { menuApi
this.$message.success('删除成功!') .delete(id)
this.loadMenus() .then(response => {
this.loadTeams() this.$message.success('删除成功!')
})
.finally(() => {
this.handleListMenus()
this.handleListTeams()
})
},
handleCreateOrUpdateMenu() {
const _this = this
_this.$refs.menuForm.validate(valid => {
if (valid) {
_this.form.saving = true
if (_this.isUpdateMode) {
menuApi
.update(_this.form.model.id, _this.form.model)
.then(response => {
_this.$message.success('更新成功!')
_this.form.model = { target: '_self' }
})
.finally(() => {
setTimeout(() => {
_this.form.saving = false
}, 200)
_this.handleListMenus()
_this.handleListTeams()
})
} else {
menuApi
.create(_this.form.model)
.then(response => {
_this.$message.success('保存成功!')
_this.form.model = { target: '_self' }
})
.finally(() => {
setTimeout(() => {
_this.form.saving = false
}, 200)
_this.handleListMenus()
_this.handleListTeams()
})
}
}
}) })
},
createOrUpdateMenu() {
if (!this.menuToCreate.name) {
this.$notification['error']({
message: '提示',
description: '菜单名称不能为空!'
})
return
}
if (!this.menuToCreate.url) {
this.$notification['error']({
message: '提示',
description: '菜单地址不能为空!'
})
return
}
if (this.menuToCreate.id) {
menuApi.update(this.menuToCreate.id, this.menuToCreate).then(response => {
this.$message.success('更新成功!')
this.loadMenus()
this.loadTeams()
})
} else {
menuApi.create(this.menuToCreate).then(response => {
this.$message.success('保存成功!')
this.loadMenus()
this.loadTeams()
})
}
this.handleAddMenu()
},
toggleExpand() {
this.fieldExpand = !this.fieldExpand
} }
} }
} }

View File

@ -22,6 +22,7 @@
type="primary" type="primary"
@click="handlerSaveContent" @click="handlerSaveContent"
:disabled="buttonDisabled" :disabled="buttonDisabled"
:loading="saving"
>保存</a-button> >保存</a-button>
</a-form-item> </a-form-item>
</a-form> </a-form>
@ -88,7 +89,8 @@ export default {
file: {}, file: {},
content: '', content: '',
themes: [], themes: [],
selectedTheme: {} selectedTheme: {},
saving: false
} }
}, },
created() { created() {
@ -150,9 +152,17 @@ export default {
}) })
}, },
handlerSaveContent() { handlerSaveContent() {
themeApi.saveContent(this.selectedTheme.id, this.file.path, this.content).then(response => { this.saving = true
this.$message.success('保存成功!') themeApi
}) .saveContent(this.selectedTheme.id, this.file.path, this.content)
.then(response => {
this.$message.success('保存成功!')
})
.finally(() => {
setTimeout(() => {
this.saving = false
}, 200)
})
} }
} }
} }

View File

@ -15,8 +15,8 @@
> >
<a-form-model <a-form-model
ref="categoryForm" ref="categoryForm"
:model="categoryToCreate" :model="form.model"
:rules="categoryRules" :rules="form.rules"
layout="horizontal" layout="horizontal"
> >
<a-form-model-item <a-form-model-item
@ -24,22 +24,22 @@
help="* 页面上所显示的名称" help="* 页面上所显示的名称"
prop="name" prop="name"
> >
<a-input v-model="categoryToCreate.name" /> <a-input v-model="form.model.name" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item <a-form-model-item
label="别名:" label="别名:"
help="* 一般为单个分类页面的标识,最好为英文" help="* 一般为单个分类页面的标识,最好为英文"
prop="slug" prop="slug"
> >
<a-input v-model="categoryToCreate.slug" /> <a-input v-model="form.model.slug" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item <a-form-model-item
label="上级目录:" label="上级目录:"
prop="parentId" prop="parentId"
> >
<category-select-tree <category-select-tree
:categories="categories" :categories="table.data"
v-model="categoryToCreate.parentId" v-model="form.model.parentId"
/> />
</a-form-model-item> </a-form-model-item>
<a-form-model-item <a-form-model-item
@ -47,11 +47,11 @@
help="* 在分类页面可展示,需要主题支持" help="* 在分类页面可展示,需要主题支持"
prop="thumbnail" prop="thumbnail"
> >
<a-input v-model="categoryToCreate.thumbnail"> <a-input v-model="form.model.thumbnail">
<a <a
href="javascript:void(0);" href="javascript:void(0);"
slot="addonAfter" slot="addonAfter"
@click="thumbnailDrawerVisible = true" @click="thumbnailDrawer.visible = true"
> >
<a-icon type="picture" /> <a-icon type="picture" />
</a> </a>
@ -59,29 +59,31 @@
</a-form-model-item> </a-form-model-item>
<a-form-model-item <a-form-model-item
label="描述:" label="描述:"
help="* 分类描述,部分主题可显示" help="* 分类描述,需要主题支持"
prop="description" prop="description"
> >
<a-input <a-input
type="textarea" type="textarea"
v-model="categoryToCreate.description" v-model="form.model.description"
:autoSize="{ minRows: 3 }" :autoSize="{ minRows: 3 }"
/> />
</a-form-model-item> </a-form-model-item>
<a-form-model-item> <a-form-model-item>
<a-button <a-button
type="primary" type="primary"
@click="handleSaveClick" @click="handleCreateOrUpdateCategory"
v-if="!isUpdateForm" v-if="!isUpdateMode"
:loading="form.saving"
>保存</a-button> >保存</a-button>
<a-button-group v-else> <a-button-group v-else>
<a-button <a-button
type="primary" type="primary"
@click="handleSaveClick" @click="handleCreateOrUpdateCategory"
:loading="form.saving"
>更新</a-button> >更新</a-button>
<a-button <a-button
type="dashed" type="dashed"
@click="categoryToCreate = {}" @click="form.model = {}"
>返回添加</a-button> >返回添加</a-button>
</a-button-group> </a-button-group>
</a-form-model-item> </a-form-model-item>
@ -106,8 +108,8 @@
itemLayout="vertical" itemLayout="vertical"
size="large" size="large"
:pagination="false" :pagination="false"
:dataSource="categories" :dataSource="table.data"
:loading="loading" :loading="table.loading"
> >
<a-list-item <a-list-item
slot="renderItem" slot="renderItem"
@ -130,13 +132,13 @@
<a-menu-item> <a-menu-item>
<a <a
href="javascript:void(0);" href="javascript:void(0);"
@click="handleEditCategory(item)" @click="form.model = item"
>编辑</a> >编辑</a>
</a-menu-item> </a-menu-item>
<a-menu-item> <a-menu-item>
<a-popconfirm <a-popconfirm
:title="'你确定要添加【' + item.name + '】到菜单?'" :title="'你确定要添加【' + item.name + '】到菜单?'"
@confirm="handleCategoryToMenu(item)" @confirm="handleCreateMenuByCategory(item)"
okText="确定" okText="确定"
cancelText="取消" cancelText="取消"
> >
@ -176,10 +178,10 @@
<!-- Desktop --> <!-- Desktop -->
<a-table <a-table
v-else v-else
:columns="columns" :columns="table.columns"
:dataSource="categories" :dataSource="table.data"
:rowKey="record => record.id" :rowKey="record => record.id"
:loading="loading" :loading="table.loading"
:scrollToFirstRowOnChange="true" :scrollToFirstRowOnChange="true"
> >
<span <span
@ -200,8 +202,8 @@
slot-scope="text, record" slot-scope="text, record"
> >
<a <a
href="javascript:;" href="javascript:void(0);"
@click="handleEditCategory(record)" @click="form.model = record"
>编辑</a> >编辑</a>
<a-divider type="vertical" /> <a-divider type="vertical" />
<a-dropdown :trigger="['click']"> <a-dropdown :trigger="['click']">
@ -213,7 +215,7 @@
<a-menu-item key="1"> <a-menu-item key="1">
<a-popconfirm <a-popconfirm
:title="'你确定要添加【' + record.name + '】到菜单?'" :title="'你确定要添加【' + record.name + '】到菜单?'"
@confirm="handleCategoryToMenu(record)" @confirm="handleCreateMenuByCategory(record)"
okText="确定" okText="确定"
cancelText="取消" cancelText="取消"
> >
@ -239,7 +241,7 @@
</a-row> </a-row>
<AttachmentSelectDrawer <AttachmentSelectDrawer
v-model="thumbnailDrawerVisible" v-model="thumbnailDrawer.visible"
@listenToSelect="handleSelectThumbnail" @listenToSelect="handleSelectThumbnail"
title="选择封面图" title="选择封面图"
/> />
@ -279,100 +281,114 @@ const columns = [
scopedSlots: { customRender: 'action' } scopedSlots: { customRender: 'action' }
} }
] ]
export default { export default {
components: { CategorySelectTree }, components: { CategorySelectTree },
mixins: [mixin, mixinDevice], mixins: [mixin, mixinDevice],
data() { data() {
return { return {
categories: [], table: {
categoryToCreate: {}, columns,
thumbnailDrawerVisible: false, data: [],
loading: false, loading: false
columns, },
categoryRules: { form: {
name: [ model: {},
{ required: true, message: '* 分类名称不能为空', trigger: ['change', 'blur'] }, saving: false,
{ max: 255, message: '* 分类名称的字符长度不能超过 255', trigger: ['change', 'blur'] } rules: {
], name: [
slug: [{ max: 255, message: '* 分类别名的字符长度不能超过 255', trigger: ['change', 'blur'] }], { required: true, message: '* 分类名称不能为空', trigger: ['change', 'blur'] },
thumbnail: [{ max: 1023, message: '* 封面图链接的字符长度不能超过 1023', trigger: ['change', 'blur'] }], { max: 255, message: '* 分类名称的字符长度不能超过 255', trigger: ['change', 'blur'] }
description: [{ max: 100, message: '* 分类描述的字符长度不能超过 100', trigger: ['change', 'blur'] }] ],
slug: [{ max: 255, message: '* 分类别名的字符长度不能超过 255', trigger: ['change', 'blur'] }],
thumbnail: [{ max: 1023, message: '* 封面图链接的字符长度不能超过 1023', trigger: ['change', 'blur'] }],
description: [{ max: 100, message: '* 分类描述的字符长度不能超过 100', trigger: ['change', 'blur'] }]
}
},
thumbnailDrawer: {
visible: false
} }
} }
}, },
computed: { computed: {
title() { title() {
if (this.categoryToCreate.id) { if (this.isUpdateMode) {
return '修改分类' return '修改分类'
} }
return '添加分类' return '添加分类'
}, },
isUpdateForm() { isUpdateMode() {
return this.categoryToCreate.id return !!this.form.model.id
} }
}, },
created() { created() {
this.loadCategories() this.handleListCategories()
}, },
methods: { methods: {
loadCategories() { handleListCategories() {
this.loading = true this.table.loading = true
categoryApi categoryApi
.listAll(true) .listAll(true)
.then(response => { .then(response => {
this.categories = response.data.data this.table.data = response.data.data
}) })
.finally(() => { .finally(() => {
setTimeout(() => { setTimeout(() => {
this.loading = false this.table.loading = false
}, 200) }, 200)
}) })
}, },
handleSaveClick() {
this.createOrUpdateCategory()
},
handleEditCategory(category) {
this.categoryToCreate = category
},
handleDeleteCategory(id) { handleDeleteCategory(id) {
categoryApi categoryApi
.delete(id) .delete(id)
.then(response => { .then(response => {
this.$message.success('删除成功!') this.$message.success('删除成功!')
this.categoryToCreate = {} this.form.model = {}
}) })
.finally(() => { .finally(() => {
this.loadCategories() this.handleListCategories()
}) })
}, },
createOrUpdateCategory() {
this.$refs.categoryForm.validate(valid => { /**
* Create or update a category.
*/
handleCreateOrUpdateCategory() {
const _this = this
_this.$refs.categoryForm.validate(valid => {
if (valid) { if (valid) {
if (this.categoryToCreate.id) { _this.form.saving = true
if (_this.isUpdateMode) {
categoryApi categoryApi
.update(this.categoryToCreate.id, this.categoryToCreate) .update(_this.form.model.id, _this.form.model)
.then(response => { .then(response => {
this.$message.success('更新成功!') _this.$message.success('更新成功!')
this.categoryToCreate = {} _this.form.model = {}
}) })
.finally(() => { .finally(() => {
this.loadCategories() setTimeout(() => {
_this.form.saving = false
}, 200)
_this.handleListCategories()
}) })
} else { } else {
categoryApi categoryApi
.create(this.categoryToCreate) .create(this.form.model)
.then(response => { .then(response => {
this.$message.success('保存成功!') _this.$message.success('保存成功!')
this.categoryToCreate = {} _this.form.model = {}
}) })
.finally(() => { .finally(() => {
this.loadCategories() setTimeout(() => {
_this.form.saving = false
}, 200)
_this.handleListCategories()
}) })
} }
} }
}) })
}, },
handleCategoryToMenu(category) { handleCreateMenuByCategory(category) {
const menu = { const menu = {
name: category.name, name: category.name,
url: `${category.fullPath}` url: `${category.fullPath}`
@ -382,8 +398,8 @@ export default {
}) })
}, },
handleSelectThumbnail(data) { handleSelectThumbnail(data) {
this.$set(this.categoryToCreate, 'thumbnail', encodeURI(data.path)) this.$set(this.form.model, 'thumbnail', encodeURI(data.path))
this.thumbnailDrawerVisible = false this.thumbnailDrawer.visible = false
}, },
handleQueryCategoryPosts(category) { handleQueryCategoryPosts(category) {
this.$router.push({ name: 'PostList', query: { categoryId: category.id } }) this.$router.push({ name: 'PostList', query: { categoryId: category.id } })

View File

@ -15,8 +15,8 @@
> >
<a-form-model <a-form-model
ref="tagForm" ref="tagForm"
:model="tagToCreate" :model="form.model"
:rules="tagRules" :rules="form.rules"
layout="horizontal" layout="horizontal"
> >
<a-form-model-item <a-form-model-item
@ -24,25 +24,25 @@
help="* 页面上所显示的名称" help="* 页面上所显示的名称"
prop="name" prop="name"
> >
<a-input v-model="tagToCreate.name" /> <a-input v-model="form.model.name" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item <a-form-model-item
label="别名:" label="别名:"
help="* 一般为单个标签页面的标识,最好为英文" help="* 一般为单个标签页面的标识,最好为英文"
prop="slug" prop="slug"
> >
<a-input v-model="tagToCreate.slug" /> <a-input v-model="form.model.slug" />
</a-form-model-item> </a-form-model-item>
<a-form-model-item <a-form-model-item
label="封面图:" label="封面图:"
help="* 在标签页面可展示,需要主题支持" help="* 在标签页面可展示,需要主题支持"
prop="thumbnail" prop="thumbnail"
> >
<a-input v-model="tagToCreate.thumbnail"> <a-input v-model="form.model.thumbnail">
<a <a
href="javascript:void(0);" href="javascript:void(0);"
slot="addonAfter" slot="addonAfter"
@click="thumbnailDrawerVisible = true" @click="thumbnailDrawer.visible = true"
> >
<a-icon type="picture" /> <a-icon type="picture" />
</a> </a>
@ -51,25 +51,27 @@
<a-form-model-item> <a-form-model-item>
<a-button <a-button
type="primary" type="primary"
@click="handleSaveClick" @click="handleCreateOrUpdateTag"
v-if="!isUpdateForm" v-if="!isUpdateMode"
:loading="form.saving"
>保存</a-button> >保存</a-button>
<a-button-group v-else> <a-button-group v-else>
<a-button <a-button
type="primary" type="primary"
@click="handleSaveClick" @click="handleCreateOrUpdateTag"
:loading="form.saving"
>更新</a-button> >更新</a-button>
<a-button <a-button
type="dashed" type="dashed"
@click="tagToCreate = {}" @click="form.model = {}"
>返回添加</a-button> >返回添加</a-button>
</a-button-group> </a-button-group>
<a-popconfirm <a-popconfirm
:title="'你确定要删除【' + tagToCreate.name + '】标签?'" :title="'你确定要删除【' + form.model.name + '】标签?'"
@confirm="handleDeleteTag(tagToCreate.id)" @confirm="handleDeleteTag(form.model.id)"
okText="确定" okText="确定"
cancelText="取消" cancelText="取消"
v-if="isUpdateForm" v-if="isUpdateMode"
> >
<a-button <a-button
type="danger" type="danger"
@ -92,28 +94,30 @@
title="所有标签" title="所有标签"
:bodyStyle="{ padding: '16px' }" :bodyStyle="{ padding: '16px' }"
> >
<a-empty v-if="tags.length==0" /> <a-spin :spinning="list.loading">
<a-tooltip <a-empty v-if="list.data.length==0" />
placement="topLeft" <a-tooltip
v-for="tag in tags" placement="topLeft"
:key="tag.id" v-for="tag in list.data"
v-else :key="tag.id"
> v-else
<template slot="title"> >
<span>{{ tag.postCount }} 篇文章</span> <template slot="title">
</template> <span>{{ tag.postCount }} 篇文章</span>
<a-tag </template>
color="blue" <a-tag
style="margin-bottom: 8px;cursor:pointer;" color="blue"
@click="handleEditTag(tag)" style="margin-bottom: 8px;cursor:pointer;"
>{{ tag.name }}</a-tag> @click="form.model = tag"
</a-tooltip> >{{ tag.name }}</a-tag>
</a-tooltip>
</a-spin>
</a-card> </a-card>
</a-col> </a-col>
</a-row> </a-row>
<AttachmentSelectDrawer <AttachmentSelectDrawer
v-model="thumbnailDrawerVisible" v-model="thumbnailDrawer.visible"
@listenToSelect="handleSelectThumbnail" @listenToSelect="handleSelectThumbnail"
title="选择封面图" title="选择封面图"
/> />
@ -126,81 +130,104 @@ import tagApi from '@/api/tag'
export default { export default {
data() { data() {
return { return {
tags: [], list: {
tagToCreate: {}, data: [],
thumbnailDrawerVisible: false, loading: false
tagRules: { },
name: [ form: {
{ required: true, message: '* 标签名称不能为空', trigger: ['change', 'blur'] }, model: {},
{ max: 255, message: '* 标签名称的字符长度不能超过 255', trigger: ['change', 'blur'] } saving: false,
], rules: {
slug: [{ max: 255, message: '* 标签别名的字符长度不能超过 255', trigger: ['change', 'blur'] }], name: [
thumbnail: [{ max: 1023, message: '* 封面图链接的字符长度不能超过 1023', trigger: ['change', 'blur'] }] { required: true, message: '* 标签名称不能为空', trigger: ['change', 'blur'] },
{ max: 255, message: '* 标签名称的字符长度不能超过 255', trigger: ['change', 'blur'] }
],
slug: [{ max: 255, message: '* 标签别名的字符长度不能超过 255', trigger: ['change', 'blur'] }],
thumbnail: [{ max: 1023, message: '* 封面图链接的字符长度不能超过 1023', trigger: ['change', 'blur'] }]
}
},
thumbnailDrawer: {
visible: false
} }
} }
}, },
computed: { computed: {
title() { title() {
if (this.tagToCreate.id) { if (this.isUpdateMode) {
return '修改标签' return '修改标签'
} }
return '添加标签' return '添加标签'
}, },
isUpdateForm() { isUpdateMode() {
return this.tagToCreate.id return !!this.form.model.id
} }
}, },
created() { created() {
this.loadTags() this.handleListTags()
}, },
methods: { methods: {
loadTags() { handleListTags() {
tagApi.listAll(true).then(response => { this.list.loading = true
this.tags = response.data.data tagApi
}) .listAll(true)
}, .then(response => {
handleSaveClick() { this.list.data = response.data.data
this.createOrUpdateTag() })
}, .finally(() => {
handleEditTag(tag) { setTimeout(() => {
this.tagToCreate = tag this.list.loading = false
}, 200)
})
}, },
handleDeleteTag(tagId) { handleDeleteTag(tagId) {
tagApi tagApi
.delete(tagId) .delete(tagId)
.then(response => { .then(response => {
this.$message.success('删除成功!') this.$message.success('删除成功!')
this.tagToCreate = {} this.form.model = {}
}) })
.finally(() => { .finally(() => {
this.loadTags() this.handleListTags()
}) })
}, },
createOrUpdateTag() { handleCreateOrUpdateTag() {
this.$refs.tagForm.validate(valid => { const _this = this
_this.$refs.tagForm.validate(valid => {
if (valid) { if (valid) {
if (this.tagToCreate.id) { this.form.saving = true
tagApi.update(this.tagToCreate.id, this.tagToCreate).then(response => { if (_this.isUpdateMode) {
this.$message.success('更新成功!')
this.tagToCreate = {}
})
} else {
tagApi tagApi
.create(this.tagToCreate) .update(_this.form.model.id, _this.form.model)
.then(response => { .then(response => {
this.$message.success('保存成功!') _this.$message.success('更新成功!')
this.tagToCreate = {} _this.form.model = {}
}) })
.finally(() => { .finally(() => {
this.loadTags() setTimeout(() => {
_this.form.saving = false
}, 200)
_this.handleListTags()
})
} else {
tagApi
.create(_this.form.model)
.then(response => {
_this.$message.success('保存成功!')
_this.form.model = {}
})
.finally(() => {
setTimeout(() => {
_this.form.saving = false
}, 200)
_this.handleListTags()
}) })
} }
} }
}) })
}, },
handleSelectThumbnail(data) { handleSelectThumbnail(data) {
this.$set(this.tagToCreate, 'thumbnail', encodeURI(data.path)) this.$set(this.form.model, 'thumbnail', encodeURI(data.path))
this.thumbnailDrawerVisible = false this.thumbnailDrawer.visible = false
} }
} }
} }

View File

@ -65,7 +65,7 @@
</div> </div>
<a-divider /> <a-divider />
<div style="margin-top:15px"> <div style="margin-top:15px">
<a-empty v-if="journals.length==0" /> <a-empty v-if="!listLoading && journals.length==0" />
<a-list <a-list
v-else v-else
itemLayout="vertical" itemLayout="vertical"
@ -179,7 +179,10 @@
>保存</a-button> >保存</a-button>
</template> </template>
<a-form layout="vertical"> <a-form layout="vertical">
<a-form-item label="页面标题:" help="* 需要主题进行适配"> <a-form-item
label="页面标题:"
help="* 需要主题进行适配"
>
<a-input v-model="options.journals_title" /> <a-input v-model="options.journals_title" />
</a-form-item> </a-form-item>
<a-form-item label="每页显示条数:"> <a-form-item label="每页显示条数:">
@ -250,7 +253,6 @@ import AttachmentDrawer from '../../attachment/components/AttachmentDrawer'
import { mixin, mixinDevice } from '@/utils/mixin.js' import { mixin, mixinDevice } from '@/utils/mixin.js'
import { mapGetters, mapActions } from 'vuex' import { mapGetters, mapActions } from 'vuex'
import journalApi from '@/api/journal' import journalApi from '@/api/journal'
import journalCommentApi from '@/api/journalComment'
import optionApi from '@/api/option' import optionApi from '@/api/option'
export default { export default {
mixins: [mixin, mixinDevice], mixins: [mixin, mixinDevice],
@ -299,11 +301,17 @@ export default {
this.queryParam.page = this.pagination.page - 1 this.queryParam.page = this.pagination.page - 1
this.queryParam.size = this.pagination.size this.queryParam.size = this.pagination.size
this.queryParam.sort = this.pagination.sort this.queryParam.sort = this.pagination.sort
journalApi.query(this.queryParam).then(response => { journalApi
this.journals = response.data.data.content .query(this.queryParam)
this.pagination.total = response.data.data.total .then(response => {
this.listLoading = false this.journals = response.data.data.content
}) this.pagination.total = response.data.data.total
})
.finally(() => {
setTimeout(() => {
this.listLoading = false
}, 200)
})
}, },
loadFormOptions() { loadFormOptions() {
optionApi.listAll().then(response => { optionApi.listAll().then(response => {
@ -334,12 +342,6 @@ export default {
this.journal = journal this.journal = journal
this.journalCommentVisible = true this.journalCommentVisible = true
}, },
handleCommentDelete(comment) {
journalCommentApi.delete(comment.id).then(response => {
this.$message.success('删除成功!')
this.handleCommentShow(this.journal)
})
},
createOrUpdateJournal() { createOrUpdateJournal() {
this.journal.type = this.isPublic ? 'PUBLIC' : 'INTIMATE' this.journal.type = this.isPublic ? 'PUBLIC' : 'INTIMATE'

View File

@ -13,15 +13,24 @@
:title="title" :title="title"
:bodyStyle="{ padding: '16px' }" :bodyStyle="{ padding: '16px' }"
> >
<a-form layout="horizontal"> <a-form-model
<a-form-item label="网站名称:"> ref="linkForm"
<a-input v-model="link.name" /> :model="form.model"
</a-form-item> :rules="form.rules"
<a-form-item layout="horizontal"
>
<a-form-model-item
label="网站名称:"
prop="name"
>
<a-input v-model="form.model.name" />
</a-form-model-item>
<a-form-model-item
label="网站地址:" label="网站地址:"
help="* 需要加上 http://" help="* 需要加上 http://"
prop="url"
> >
<a-input v-model="link.url"> <a-input v-model="form.model.url">
<!-- <a <!-- <a
href="javascript:void(0);" href="javascript:void(0);"
slot="addonAfter" slot="addonAfter"
@ -30,49 +39,64 @@
<a-icon type="sync" /> <a-icon type="sync" />
</a> --> </a> -->
</a-input> </a-input>
</a-form-item> </a-form-model-item>
<a-form-item label="Logo"> <a-form-model-item
<a-input v-model="link.logo" /> label="Logo"
</a-form-item> prop="logo"
<a-form-item label="分组:"> >
<a-input v-model="form.model.logo" />
</a-form-model-item>
<a-form-model-item
label="分组:"
prop="team"
>
<a-auto-complete <a-auto-complete
:dataSource="teams" :dataSource="teams"
v-model="link.team" v-model="form.model.team"
allowClear allowClear
/> />
</a-form-item> </a-form-model-item>
<a-form-item label="排序编号:"> <a-form-model-item
<a-input label="排序编号:"
type="number" prop="priority"
v-model="link.priority" >
<a-input-number
:min="0"
v-model="form.model.priority"
style="width:100%"
/> />
</a-form-item> </a-form-model-item>
<a-form-item label="描述:"> <a-form-model-item
label="描述:"
prop="description"
>
<a-input <a-input
type="textarea" type="textarea"
:autoSize="{ minRows: 5 }" :autoSize="{ minRows: 5 }"
v-model="link.description" v-model="form.model.description"
/> />
</a-form-item> </a-form-model-item>
<a-form-item> <a-form-model-item>
<a-button <a-button
type="primary" type="primary"
@click="handleSaveClick" @click="handleCreateOrUpdateLink"
v-if="formType==='create'" v-if="!isUpdateMode"
:loading="form.saving"
>保存</a-button> >保存</a-button>
<a-button-group v-else> <a-button-group v-else>
<a-button <a-button
type="primary" type="primary"
@click="handleSaveClick" @click="handleCreateOrUpdateLink"
:loading="form.saving"
>更新</a-button> >更新</a-button>
<a-button <a-button
type="dashed" type="dashed"
@click="handleAddLink" @click="form.model = {}"
v-if="formType==='update'" v-if="isUpdateMode"
>返回添加</a-button> >返回添加</a-button>
</a-button-group> </a-button-group>
</a-form-item> </a-form-model-item>
</a-form> </a-form-model>
</a-card> </a-card>
</a-col> </a-col>
<a-col <a-col
@ -92,8 +116,8 @@
v-if="isMobile()" v-if="isMobile()"
itemLayout="vertical" itemLayout="vertical"
size="large" size="large"
:dataSource="links" :dataSource="table.data"
:loading="loading" :loading="table.loading"
> >
<a-list-item <a-list-item
slot="renderItem" slot="renderItem"
@ -111,8 +135,8 @@
<a-menu slot="overlay"> <a-menu slot="overlay">
<a-menu-item> <a-menu-item>
<a <a
href="javascript:;" href="javascript:void(0);"
@click="handleEditLink(item.id)" @click="form.model = item"
>编辑</a> >编辑</a>
</a-menu-item> </a-menu-item>
<a-menu-item> <a-menu-item>
@ -153,9 +177,9 @@
<!-- Desktop --> <!-- Desktop -->
<a-table <a-table
v-else v-else
:columns="columns" :columns="table.columns"
:dataSource="links" :dataSource="table.data"
:loading="loading" :loading="table.loading"
:rowKey="link => link.id" :rowKey="link => link.id"
:scrollToFirstRowOnChange="true" :scrollToFirstRowOnChange="true"
> >
@ -179,8 +203,8 @@
slot-scope="text, record" slot-scope="text, record"
> >
<a <a
href="javascript:;" href="javascript:void(0);"
@click="handleEditLink(record.id)" @click="form.model = record"
>编辑</a> >编辑</a>
<a-divider type="vertical" /> <a-divider type="vertical" />
<a-popconfirm <a-popconfirm
@ -202,13 +226,13 @@
shape="circle" shape="circle"
icon="setting" icon="setting"
size="large" size="large"
@click="optionFormVisible=true" @click="optionsModal.visible=true"
></a-button> ></a-button>
</div> </div>
<a-modal <a-modal
v-model="optionFormVisible" v-model="optionsModal.visible"
title="页面设置" title="页面设置"
:afterClose="onOptionFormClose" :afterClose="() => optionsModal.visible = false"
> >
<template slot="footer"> <template slot="footer">
<a-button <a-button
@ -218,8 +242,11 @@
>保存</a-button> >保存</a-button>
</template> </template>
<a-form layout="vertical"> <a-form layout="vertical">
<a-form-item label="页面标题:" help="* 需要主题进行适配"> <a-form-item
<a-input v-model="options.links_title" /> label="页面标题:"
help="* 需要主题进行适配"
>
<a-input v-model="optionsModal.data.links_title" />
</a-form-item> </a-form-item>
</a-form> </a-form>
</a-modal> </a-modal>
@ -263,114 +290,141 @@ export default {
mixins: [mixin, mixinDevice], mixins: [mixin, mixinDevice],
data() { data() {
return { return {
formType: 'create', table: {
optionFormVisible: false, columns,
data: [], data: [],
loading: false, loading: false
columns, },
links: [], form: {
link: {}, model: {},
teams: [], saving: false,
options: [] rules: {
name: [
{ required: true, message: '* 友情链接名称不能为空', trigger: ['change', 'blur'] },
{ max: 255, message: '* 友情链接名称的字符长度不能超过 255', trigger: ['change', 'blur'] }
],
url: [
{ required: true, message: '* 友情链接地址不能为空', trigger: ['change', 'blur'] },
{ max: 1023, message: '* 友情链接地址的字符长度不能超过 1023', trigger: ['change', 'blur'] },
{ type: 'url', message: '* 友情链接地址格式有误', trigger: ['change', 'blur'] }
],
logo: [{ max: 1023, message: '* 友情链接 Logo 的字符长度不能超过 1023', trigger: ['change', 'blur'] }],
description: [{ max: 255, message: '* 友情链接描述的字符长度不能超过 255', trigger: ['change', 'blur'] }],
team: [{ max: 255, message: '* 友情链接分组的字符长度 255', trigger: ['change', 'blur'] }]
}
},
optionsModal: {
visible: false,
data: []
},
teams: []
} }
}, },
computed: { computed: {
title() { title() {
if (this.link.id) { if (this.isUpdateMode) {
return '修改友情链接' return '修改友情链接'
} }
return '添加友情链接' return '添加友情链接'
},
isUpdateMode() {
return !!this.form.model.id
} }
}, },
created() { created() {
this.loadLinks() this.handleListLinks()
this.loadTeams() this.handleListLinkTeams()
this.loadFormOptions() this.handleListOptions()
}, },
methods: { methods: {
...mapActions(['loadOptions']), ...mapActions(['loadOptions']),
loadLinks() { handleListLinks() {
this.loading = true this.table.loading = true
linkApi.listAll().then(response => { linkApi
this.links = response.data.data .listAll()
this.loading = false .then(response => {
}) this.table.data = response.data.data
})
.finally(() => {
setTimeout(() => {
this.table.loading = false
}, 200)
})
}, },
loadTeams() { handleListLinkTeams() {
linkApi.listTeams().then(response => { linkApi.listTeams().then(response => {
this.teams = response.data.data this.teams = response.data.data
}) })
}, },
loadFormOptions() { handleListOptions() {
optionApi.listAll().then(response => { optionApi.listAll().then(response => {
this.options = response.data.data this.optionsModal.data = response.data.data
})
},
handleSaveClick() {
this.createOrUpdateLink()
},
handleAddLink() {
this.formType = 'create'
this.link = {}
},
handleEditLink(id) {
linkApi.get(id).then(response => {
this.link = response.data.data
this.formType = 'update'
}) })
}, },
handleDeleteLink(id) { handleDeleteLink(id) {
linkApi.delete(id).then(response => { linkApi
this.$message.success('删除成功!') .delete(id)
this.loadLinks() .then(response => {
this.loadTeams() this.$message.success('删除成功!')
}) })
.finally(() => {
this.handleListLinks()
this.handleListLinkTeams()
})
}, },
handleParseUrl() { handleParseUrl() {
linkApi.getByParse(this.link.url).then(response => { linkApi.getByParse(this.form.model.url).then(response => {
this.link = response.data.data this.form.model = response.data.data
}) })
}, },
createOrUpdateLink() { handleCreateOrUpdateLink() {
if (!this.link.name) { const _this = this
this.$notification['error']({ _this.$refs.linkForm.validate(valid => {
message: '提示', if (valid) {
description: '网站名称不能为空!' _this.form.saving = true
}) if (_this.isUpdateMode) {
return linkApi
} .update(_this.form.model.id, _this.form.model)
if (!this.link.url) { .then(response => {
this.$notification['error']({ _this.$message.success('更新成功!')
message: '提示', _this.form.model = {}
description: '网站地址不能为空!' })
}) .finally(() => {
return setTimeout(() => {
} _this.form.saving = false
if (this.link.id) { }, 200)
linkApi.update(this.link.id, this.link).then(response => { _this.handleListLinks()
this.$message.success('更新成功!') _this.handleListLinkTeams()
this.loadLinks() })
this.loadTeams() } else {
}) linkApi
} else { .create(_this.form.model)
linkApi.create(this.link).then(response => { .then(response => {
this.$message.success('保存成功!') _this.$message.success('保存成功!')
this.loadLinks() _this.form.model = {}
this.loadTeams() })
}) .finally(() => {
} setTimeout(() => {
this.handleAddLink() _this.form.saving = false
}, 200)
_this.handleListLinks()
_this.handleListLinkTeams()
})
}
}
})
}, },
handleSaveOptions() { handleSaveOptions() {
optionApi.save(this.options).then(response => { optionApi
this.loadFormOptions() .save(this.optionsModal.data)
this.loadOptions() .then(response => {
this.$message.success('保存成功!') this.$message.success('保存成功!')
this.optionFormVisible = false this.optionsModal.visible = false
}) })
}, .finally(() => {
onOptionFormClose() { this.handleListOptions()
this.optionFormVisible = false this.loadOptions()
})
} }
} }
} }