parent
7f3b3f72e7
commit
3ca17c62b4
@ -0,0 +1,35 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function index(params) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/api/article/index',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function show(params) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/api/article/show',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function save(data, isLoading = true) {
|
||||
return request({
|
||||
method: 'post',
|
||||
url: '/api/article/save',
|
||||
data,
|
||||
isLoading
|
||||
})
|
||||
}
|
||||
|
||||
export function destroy(params, isLoading = true) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/api/article/destroy',
|
||||
params,
|
||||
isLoading
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function index(params) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/api/article-type/index',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function show(params) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/api/article-type/show',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function save(data, isLoading = true) {
|
||||
return request({
|
||||
method: 'post',
|
||||
url: '/api/article-type/save',
|
||||
data,
|
||||
isLoading
|
||||
})
|
||||
}
|
||||
|
||||
export function destroy(params, isLoading = true) {
|
||||
return request({
|
||||
method: 'get',
|
||||
url: '/api/article-type/destroy',
|
||||
params,
|
||||
isLoading
|
||||
})
|
||||
}
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,170 @@
|
||||
<template>
|
||||
<el-card id="address-book" class="box-card" shadow="hover">
|
||||
<div slot="header" class="clearfix">
|
||||
<SvgIcon style="color: var(--theme-color);width: 22px;height: 22px;" icon-class="address-book" />
|
||||
<span
|
||||
style=" padding-left: 15px"
|
||||
>通讯录</span>
|
||||
|
||||
<el-autocomplete
|
||||
v-model="keyword"
|
||||
value-key="name"
|
||||
:fetch-suggestions="querySearch"
|
||||
placeholder="关键词"
|
||||
clearable
|
||||
size="small"
|
||||
:trigger-on-focus="false"
|
||||
style="float: right; width: 46%;"
|
||||
@change="filterList"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="body" :style="{ 'height': tableHeight + 'px' }">
|
||||
<ul>
|
||||
<li v-for="item in lists" :key="item.id">
|
||||
<div class="top">
|
||||
<span>{{ item.name }}</span>
|
||||
<el-tag v-if="item.department" style="margin-left: 6px;" effect="dark" size="small" type="primary">{{ item.department.name }}</el-tag>
|
||||
</div>
|
||||
<div v-if="item.mobile" class="bottom" @click="copy2(item.mobile)">
|
||||
<i class="el-icon-phone" />
|
||||
<span style="color: var(--theme-color)">{{ item.mobile }}</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { copy2, debounce } from '@/utils'
|
||||
import { index } from '@/api/user'
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue'
|
||||
import ElementResize from 'element-resize-detector'
|
||||
export default {
|
||||
name: 'AddressBook',
|
||||
components: {
|
||||
SvgIcon
|
||||
},
|
||||
layout: {
|
||||
x: 0,
|
||||
y: 5,
|
||||
w: 8,
|
||||
h: 5,
|
||||
i: 'AddressBook',
|
||||
name: '通讯录'
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
keyword: '',
|
||||
users: [],
|
||||
lists: [],
|
||||
tableHeight: 200
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
mounted() {
|
||||
this.init()
|
||||
},
|
||||
created() {
|
||||
this.getUsers()
|
||||
},
|
||||
methods: {
|
||||
async getUsers() {
|
||||
try {
|
||||
const res = await index({
|
||||
page: 1,
|
||||
rows: 999
|
||||
})
|
||||
this.users = res.data
|
||||
this.lists = res.data
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
},
|
||||
|
||||
copy2,
|
||||
filterList(e) {
|
||||
if (!e) {
|
||||
this.lists = this.users
|
||||
return
|
||||
}
|
||||
this.lists = this.users.filter(this.createFilter(e))
|
||||
},
|
||||
createFilter(queryString) {
|
||||
return (user) => {
|
||||
return (user.name.toLowerCase().indexOf(queryString.toLowerCase()) === 0)
|
||||
}
|
||||
},
|
||||
querySearch(queryString, cb) {
|
||||
const users = this.users
|
||||
const results = queryString ? users.filter(this.createFilter(queryString)) : users
|
||||
// 调用 callback 返回建议列表的数据
|
||||
cb(results)
|
||||
},
|
||||
init() {
|
||||
const cardDom = document.getElementById('address-book')
|
||||
const cardTitleH = 60
|
||||
const elementResize = ElementResize({
|
||||
strategy: 'scroll'
|
||||
})
|
||||
elementResize.listenTo(cardDom, (ele) => {
|
||||
this.tableHeight =
|
||||
cardDom.getBoundingClientRect().height -
|
||||
40 -
|
||||
cardTitleH
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.body {
|
||||
overflow: scroll;
|
||||
|
||||
&::-webkit-scrollbar-track-piece {
|
||||
background: #d3dce6;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #99a9bf;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
margin: 0;
|
||||
|
||||
li {
|
||||
line-height: 2;
|
||||
padding: 8px 10px;
|
||||
position: relative;
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.bottom {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&::before {
|
||||
background: repeating-linear-gradient(-45deg,#ff976a 0%,#ff976a 20%,transparent 0,transparent 25%,var(--theme-color)0,var(--theme-color)45%,transparent 0,transparent 50%);
|
||||
content: "";
|
||||
background-size: 80px;
|
||||
height: 2px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<el-card id="article-card" class="box-card" shadow="hover">
|
||||
<div slot="header" class="clearfix">
|
||||
<SvgIcon style="color: var(--theme-color);width: 22px;height: 22px;" icon-class="address-book" />
|
||||
<span
|
||||
style=" padding-left: 15px"
|
||||
>文件、新闻</span>
|
||||
</div>
|
||||
|
||||
<div class="body" :style="{ 'height': tableHeight + 'px' }">
|
||||
<ul>
|
||||
<li v-for="item in article" :key="item.id">
|
||||
<div class="top">
|
||||
<div>{{ item.title }}</div>
|
||||
<p style="color: #666;font-size: 13px;">{{ item.sub_title }}</p>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { index } from '@/api/article'
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue'
|
||||
import ElementResize from 'element-resize-detector'
|
||||
export default {
|
||||
name: 'Articles',
|
||||
components: {
|
||||
SvgIcon
|
||||
},
|
||||
layout: {
|
||||
x: 0,
|
||||
y: 5,
|
||||
w: 8,
|
||||
h: 5,
|
||||
i: 'Articles',
|
||||
name: '文件、新闻'
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
article: [],
|
||||
tableHeight: 200
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
mounted() {
|
||||
this.init()
|
||||
},
|
||||
created() {
|
||||
this.getArticles()
|
||||
},
|
||||
methods: {
|
||||
async getArticles() {
|
||||
try {
|
||||
const res = await index({
|
||||
page: 1,
|
||||
page_size: 999
|
||||
})
|
||||
this.article = res.data
|
||||
this.lists = res.data
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
},
|
||||
init() {
|
||||
const cardDom = document.getElementById('article-card')
|
||||
const cardTitleH = 60
|
||||
const elementResize = ElementResize({
|
||||
strategy: 'scroll'
|
||||
})
|
||||
elementResize.listenTo(cardDom, (ele) => {
|
||||
this.tableHeight =
|
||||
cardDom.getBoundingClientRect().height -
|
||||
40 -
|
||||
cardTitleH
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.body {
|
||||
overflow: scroll;
|
||||
|
||||
&::-webkit-scrollbar-track-piece {
|
||||
background: #d3dce6;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #99a9bf;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
margin: 0;
|
||||
|
||||
li {
|
||||
line-height: 1.5;
|
||||
padding: 8px 10px;
|
||||
position: relative;
|
||||
|
||||
.top {
|
||||
}
|
||||
.bottom {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&::before {
|
||||
background: repeating-linear-gradient(-45deg,#ff976a 0%,#ff976a 20%,transparent 0,transparent 25%,var(--theme-color)0,var(--theme-color)45%,transparent 0,transparent 50%);
|
||||
content: "";
|
||||
background-size: 80px;
|
||||
height: 2px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,196 @@
|
||||
<template>
|
||||
<div>
|
||||
<card-container>
|
||||
<vxe-toolbar>
|
||||
<template #buttons>
|
||||
<el-button icon="el-icon-menu" type="primary" size="small" @click="isShowDraw = true">文章分类</el-button>
|
||||
<el-button icon="el-icon-plus" type="primary" size="small" @click="isShowAdd = true">新增</el-button>
|
||||
<el-button icon="el-icon-search" type="primary" plain size="small" @click="getList">搜索</el-button>
|
||||
</template>
|
||||
</vxe-toolbar>
|
||||
<vxe-table
|
||||
ref="table"
|
||||
stripe
|
||||
style="margin-top: 10px;"
|
||||
:loading="loading"
|
||||
keep-source
|
||||
show-overflow
|
||||
:column-config="{ resizable: true }"
|
||||
:edit-rules="validRules"
|
||||
:edit-config="{ trigger: 'manual', mode: 'row', showStatus: true, isHover: true, autoClear: false }"
|
||||
:align="allAlign"
|
||||
:data="tableData"
|
||||
>
|
||||
<vxe-column type="seq" width="58" align="center" />
|
||||
<vxe-column field="title" width="170" title="标题" />
|
||||
<vxe-column field="sub_title" width="150" title="简介" />
|
||||
<vxe-column field="content" min-width="180" title="内容" />
|
||||
<vxe-column field="operate" title="操作" min-width="220">
|
||||
<template #default="{ row }">
|
||||
<template>
|
||||
<el-button size="small" type="warning" @click="editRowEvent(row)">编辑</el-button>
|
||||
<el-button size="small" type="danger" @click="destroyRowEvent(row)">删除</el-button>
|
||||
</template>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
|
||||
<el-pagination
|
||||
style="margin-top: 10px;"
|
||||
:current-page="select.page"
|
||||
:page-sizes="[20, 30, 40, 50]"
|
||||
:page-size="select.page_size"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="total"
|
||||
@size-change="e => {
|
||||
select.page_size = e;
|
||||
select.page = 1;
|
||||
getList();
|
||||
}"
|
||||
@current-change="e => {
|
||||
select.page = e;
|
||||
getList();
|
||||
}"
|
||||
/>
|
||||
</card-container>
|
||||
<add-article ref="AddArticle" :is-show.sync="isShowAdd" @refresh="getList" />
|
||||
<article-type ref="ArticleType" :is-show.sync="isShowDraw" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { deepCopy } from '@/utils'
|
||||
import { index, save, destroy } from '@/api/article'
|
||||
import AddArticle from './components/AddArticle.vue'
|
||||
import ArticleType from './components/ArticleType.vue'
|
||||
export default {
|
||||
components: {
|
||||
AddArticle,
|
||||
ArticleType
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isShowDraw: false,
|
||||
isShowAdd: false,
|
||||
|
||||
loading: false,
|
||||
select: {
|
||||
page: 1,
|
||||
page_size: 20
|
||||
},
|
||||
total: 0,
|
||||
allAlign: null,
|
||||
tableData: [],
|
||||
validRules: {},
|
||||
form: {
|
||||
id: '',
|
||||
name: '',
|
||||
key: '',
|
||||
value: '',
|
||||
mysort: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isActiveStatus() {
|
||||
return function(row) {
|
||||
if (this.$refs['table']) {
|
||||
return this.$refs['table'].isEditByRow(row)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
editRowEvent(row) {
|
||||
this.$refs['AddArticle'].form.id = row.id
|
||||
this.isShowAdd = true
|
||||
// if (this.$refs['table']) {
|
||||
// this.$refs['table'].setEditRow(row)
|
||||
// }
|
||||
},
|
||||
cancelRowEvent(row) {
|
||||
if (this.$refs['table']) {
|
||||
this.$refs['table'].clearEdit().then(() => {
|
||||
// 还原行数据
|
||||
this.$refs['table'].revertData(row)
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
async getList() {
|
||||
this.loading = true
|
||||
try {
|
||||
const res = await index(this.select)
|
||||
this.tableData = res.data
|
||||
this.total = res.total
|
||||
this.loading = false
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
async saveRowEvent(row) {
|
||||
try {
|
||||
const errMap = await this.$refs['table'].validate()
|
||||
if (errMap) {
|
||||
throw new Error(errMap)
|
||||
}
|
||||
await this.$confirm('确认保存?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消'
|
||||
})
|
||||
await this.$refs['table'].clearEdit()
|
||||
const form = deepCopy(this.form)
|
||||
for (const key in form) {
|
||||
form[key] = row[key]
|
||||
}
|
||||
if (!form.password) {
|
||||
delete form.password
|
||||
}
|
||||
this.loading = true
|
||||
await save(form)
|
||||
await this.getList()
|
||||
this.loading = false
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async destroyRowEvent(row) {
|
||||
try {
|
||||
await this.$confirm('确认删除?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消'
|
||||
})
|
||||
this.loading = true
|
||||
if (row.id) {
|
||||
await destroy({
|
||||
id: row.id
|
||||
})
|
||||
await this.getList()
|
||||
} else {
|
||||
console.log(row)
|
||||
this.tableData.splice(this.tableData.findIndex(i => i._X_ROW_KEY === row._X_ROW_KEY), 1)
|
||||
}
|
||||
this.loading = false
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.total {
|
||||
color: #666;
|
||||
text-align: right;
|
||||
line-height: 3;
|
||||
}
|
||||
::v-deep .el-tag + .el-tag {
|
||||
margin-left: 4px;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<div>
|
||||
<vxe-modal
|
||||
:value="isShow"
|
||||
show-footer
|
||||
title="文章管理"
|
||||
show-confirm-button
|
||||
:width="820"
|
||||
:height="600"
|
||||
esc-closable
|
||||
:fullscreen="$store.getters.device === 'mobile'"
|
||||
@input="e => $emit('update:isShow',e)"
|
||||
>
|
||||
<el-form ref="elForm" :model="form" :rules="rules" label-position="top" label-width="100">
|
||||
<el-form-item label="名字" prop="title">
|
||||
<el-input v-model="form.title" />
|
||||
</el-form-item>
|
||||
<el-form-item label="简介" prop="sub_title">
|
||||
<el-input v-model="form.sub_title" />
|
||||
</el-form-item>
|
||||
<el-form-item label="内容" prop="content">
|
||||
<el-input v-model="form.content" type="textarea" :autosize="{ minRows: 2 }" />
|
||||
</el-form-item>
|
||||
<el-form-item label="分类" prop="article_type_id">
|
||||
<Treeselect
|
||||
v-model="form.article_type_id"
|
||||
:options="types"
|
||||
:multiple="false"
|
||||
no-children-text="无子分类"
|
||||
:normalizer="node => ({
|
||||
id: node.id,
|
||||
key: node.id,
|
||||
label: node.name,
|
||||
children: node.children,
|
||||
isDefaultExpanded: true
|
||||
})"
|
||||
/> </el-form-item>
|
||||
<el-form-item label="附件上传">
|
||||
<el-upload
|
||||
:action="action"
|
||||
:headers="{
|
||||
Authorization: `Bearer ${getToken()}`,
|
||||
}"
|
||||
:before-upload="beforeUpload"
|
||||
:on-success="uploadSuccess"
|
||||
:on-remove="removeHandle"
|
||||
multiple
|
||||
:file-list="fileList"
|
||||
>
|
||||
<el-button size="small" type="primary">点击上传</el-button>
|
||||
<div slot="tip" class="el-upload__tip">上传文件不超过10Mb</div>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button type="primary" :loading="loading" @click="submit">确认</el-button>
|
||||
</template>
|
||||
</vxe-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { index } from '@/api/articleType'
|
||||
import { save, show } from '@/api/article'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { deepCopy } from '@/utils'
|
||||
export default {
|
||||
props: {
|
||||
isShow: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fileList: [],
|
||||
action: process.env.VUE_APP_UPLOAD_API,
|
||||
types: [],
|
||||
|
||||
loading: false,
|
||||
form: {
|
||||
id: '',
|
||||
title: '',
|
||||
content: '',
|
||||
sub_title: '',
|
||||
article_type_id: '',
|
||||
file_ids: []
|
||||
},
|
||||
cForm: {
|
||||
id: '',
|
||||
title: '',
|
||||
content: '',
|
||||
sub_title: '',
|
||||
article_type_id: '',
|
||||
file_ids: []
|
||||
},
|
||||
rules: {}
|
||||
}
|
||||
},
|
||||
computed: {},
|
||||
watch: {
|
||||
isShow(newVal) {
|
||||
if (newVal) {
|
||||
this.getType()
|
||||
if (this.form.id) {
|
||||
this.getDetail()
|
||||
}
|
||||
} else {
|
||||
this.fileList = []
|
||||
this.form = deepCopy(this.cForm)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getToken,
|
||||
beforeUpload(file) {
|
||||
const isLt10M = file.size / 1024 / 1024 < 10
|
||||
if (!isLt10M) {
|
||||
this.$message.error('上传文件大小不能超过 10MB!')
|
||||
}
|
||||
return isLt10M
|
||||
},
|
||||
uploadSuccess(response, file, fileList) {
|
||||
this.fileList = fileList
|
||||
},
|
||||
removeHandle(file, fileList) {
|
||||
this.fileList = fileList
|
||||
},
|
||||
|
||||
submit() {
|
||||
this.$refs['elForm'].validate(async valid => {
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
try {
|
||||
this.form.file_ids = this.fileList.map(i => i.response?.data?.id)
|
||||
await save(this.form)
|
||||
this.$message.success('新增成功')
|
||||
this.$emit('refresh')
|
||||
this.$emit('update:isShow', false)
|
||||
this.loading = false
|
||||
this.$refs['elForm'].resetFields()
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
async getDetail() {
|
||||
try {
|
||||
const res = await show({ id: this.form.id }, true)
|
||||
console.log(res)
|
||||
for (const key in this.form) {
|
||||
this.form[key] = res[key]
|
||||
}
|
||||
this.fileList = res.files.map(i => ({
|
||||
response: {
|
||||
data: i
|
||||
},
|
||||
url: i.url,
|
||||
name: i.original_name
|
||||
}))
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
},
|
||||
async getType() {
|
||||
try {
|
||||
const res = await index({
|
||||
is_tree: 1
|
||||
})
|
||||
this.types = res
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
this.types = []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
@ -0,0 +1,204 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-drawer
|
||||
:size="$store.getters.device === 'desktop' ? '64%' : '100%'"
|
||||
title="文章分类"
|
||||
:visible="isShow"
|
||||
direction="rtl"
|
||||
@close="$emit('update:isShow', false)"
|
||||
>
|
||||
<div style="padding: 0 10px;">
|
||||
<vxe-toolbar>
|
||||
<template #buttons>
|
||||
<el-button icon="el-icon-plus" type="primary" size="small" @click="insertRow()">新增</el-button>
|
||||
<el-button icon="el-icon-search" type="primary" plain size="small" @click="getList">搜索</el-button>
|
||||
</template>
|
||||
</vxe-toolbar>
|
||||
<vxe-table
|
||||
ref="table"
|
||||
style="margin-top: 10px;"
|
||||
:loading="loading"
|
||||
keep-source
|
||||
show-overflow
|
||||
:row-config="{ keyField: 'rid' }"
|
||||
:column-config="{ resizable: true }"
|
||||
:edit-rules="validRules"
|
||||
:tree-config="{ transform: true, rowField: 'id', parentField: 'pid' }"
|
||||
:edit-config="{ trigger: 'manual', mode: 'row', showStatus: true, isHover: true, autoClear: false }"
|
||||
:align="allAlign"
|
||||
:data="tableData"
|
||||
>
|
||||
<vxe-column type="seq" width="58" align="center" />
|
||||
<vxe-column tree-node field="name" width="170" title="名称" :edit-render="{ name: 'input', attrs: { type: 'text' } }" />
|
||||
<!-- <vxe-column field="sub_title" width="150" title="简介" :edit-render="{ name: 'input', attrs: { type: 'text' } }" />-->
|
||||
<vxe-column field="operate" title="操作" min-width="220">
|
||||
<template #default="{ row }">
|
||||
<template v-if="isActiveStatus(row)">
|
||||
<el-button size="small" type="primary" @click="saveRowEvent(row)">保存</el-button>
|
||||
<el-button size="small" type="primary" plain @click="cancelRowEvent(row)">取消</el-button>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-button size="small" type="primary" @click="insertRow(row)">下一级</el-button>
|
||||
<el-button size="small" type="warning" @click="editRowEvent(row)">编辑</el-button>
|
||||
<el-button size="small" type="danger" @click="destroyRowEvent(row)">删除</el-button>
|
||||
</template>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { destroy, index, save } from '@/api/articleType'
|
||||
import { deepCopy } from '@/utils'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
isShow: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
select: {
|
||||
page: 1,
|
||||
page_size: 9999,
|
||||
is_tree: 0
|
||||
},
|
||||
total: 0,
|
||||
allAlign: null,
|
||||
tableData: [],
|
||||
validRules: {},
|
||||
form: {
|
||||
id: '',
|
||||
pid: 0,
|
||||
name: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isActiveStatus() {
|
||||
return function(row) {
|
||||
if (this.$refs['table']) {
|
||||
return this.$refs['table'].isEditByRow(row)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
async insertRow(row) {
|
||||
if (this.$refs['table']) {
|
||||
const cForm = deepCopy(this.form)
|
||||
cForm.pid = row ? row.id : 0
|
||||
let newRow
|
||||
if (row) {
|
||||
await this.$refs['table'].setTreeExpand(row, true)
|
||||
const temp = await this.$refs['table'].insert(cForm)
|
||||
newRow = temp.row
|
||||
} else {
|
||||
const temp = await this.$refs['table'].insertAt(cForm, row)
|
||||
newRow = temp.row
|
||||
}
|
||||
await this.$refs['table'].setEditRow(newRow)
|
||||
}
|
||||
},
|
||||
editRowEvent(row) {
|
||||
if (this.$refs['table']) {
|
||||
this.$refs['table'].setEditRow(row)
|
||||
}
|
||||
},
|
||||
cancelRowEvent(row) {
|
||||
if (this.$refs['table']) {
|
||||
this.$refs['table'].clearEdit().then(() => {
|
||||
// 还原行数据
|
||||
if (row.id) {
|
||||
this.$refs['table'].revertData(row)
|
||||
} else {
|
||||
this.$refs['table'].remove(row)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
async getList() {
|
||||
this.loading = true
|
||||
try {
|
||||
const res = await index(this.select)
|
||||
this.tableData = res.data
|
||||
this.loading = false
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs['table']) {
|
||||
this.$refs['table'].setAllTreeExpand(true)
|
||||
}
|
||||
})
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
async saveRowEvent(row) {
|
||||
try {
|
||||
const errMap = await this.$refs['table'].validate()
|
||||
if (errMap) {
|
||||
throw new Error(errMap)
|
||||
}
|
||||
await this.$confirm('确认保存?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消'
|
||||
})
|
||||
await this.$refs['table'].clearEdit()
|
||||
const form = deepCopy(this.form)
|
||||
for (const key in form) {
|
||||
form[key] = row[key]
|
||||
}
|
||||
if (!form.password) {
|
||||
delete form.password
|
||||
}
|
||||
this.loading = true
|
||||
await save(form)
|
||||
await this.getList()
|
||||
this.loading = false
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async destroyRowEvent(row) {
|
||||
if (!row.id) {
|
||||
this.$refs['table'].remove(row)
|
||||
return
|
||||
}
|
||||
try {
|
||||
await this.$confirm('确认删除?', '提示', {
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消'
|
||||
})
|
||||
this.loading = true
|
||||
if (row.id) {
|
||||
await destroy({
|
||||
id: row.id
|
||||
})
|
||||
await this.getList()
|
||||
} else {
|
||||
console.log(row)
|
||||
this.tableData.splice(this.tableData.findIndex(i => i._X_ROW_KEY === row._X_ROW_KEY), 1)
|
||||
}
|
||||
this.loading = false
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
Loading…
Reference in new issue