feat(frontend): 重构前端架构并添加新功能
- 移除七牛云存储相关代码 - 新增 Minio 存储支持 - 添加字典管理功能 - 实现通用的表单对话框组件 - 开发可复用的表格组件 - 添加日期格式化工具 - 更新 README 文档
This commit is contained in:
@@ -24,4 +24,12 @@ export function edit(data) {
|
||||
})
|
||||
}
|
||||
|
||||
export default { add, edit, del }
|
||||
export function queryPageDict(data) {
|
||||
return request({
|
||||
url: 'api/dict',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export default { add, edit, del, queryPageDict }
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function queryQiniuConfig() {
|
||||
return request({
|
||||
url: 'api/qiNiuContent/queryQiniuConfig',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function modifyQiniuConfig(data) {
|
||||
return request({
|
||||
url: 'api/qiNiuContent/modifyQiniuConfig',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
export function createFilePreviewUrl(id) {
|
||||
return request({
|
||||
url: 'api/qiNiuContent/createFilePreviewUrl/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export function sync() {
|
||||
return request({
|
||||
url: 'api/qiNiuContent/synchronize',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function del(ids) {
|
||||
return request({
|
||||
url: 'api/qiNiuContent/removeFileByIds',
|
||||
method: 'post',
|
||||
data: ids
|
||||
})
|
||||
}
|
||||
export default { del, createFilePreviewUrl, sync }
|
||||
@@ -75,9 +75,49 @@ const LabelUtil = {
|
||||
}
|
||||
}
|
||||
|
||||
const DateUtil = {
|
||||
formatDate: function(originVal) {
|
||||
if (originVal === undefined) {
|
||||
return ''
|
||||
}
|
||||
const dt = new Date(originVal)
|
||||
const y = dt.getFullYear()
|
||||
const m = (dt.getMonth() + 1 + '').padStart(2, '0')
|
||||
const d = (dt.getDate() + '').padStart(2, '0')
|
||||
return `${y}-${m}-${d}`
|
||||
},
|
||||
formatDateTime: function(originVal) {
|
||||
if (originVal === undefined) {
|
||||
return ''
|
||||
}
|
||||
const dt = new Date(originVal)
|
||||
const y = dt.getFullYear()
|
||||
const m = (dt.getMonth() + 1 + '').padStart(2, '0')
|
||||
const d = (dt.getDate() + '').padStart(2, '0')
|
||||
const hh = (dt.getHours() + '').padStart(2, '0')
|
||||
const mm = (dt.getMinutes() + '').padStart(2, '0')
|
||||
const ss = (dt.getSeconds() + '').padStart(2, '0')
|
||||
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
|
||||
},
|
||||
formatRowDateTime: function(row, column, cellValue, index) {
|
||||
if (cellValue === undefined) {
|
||||
return ''
|
||||
}
|
||||
const dt = new Date(cellValue)
|
||||
const y = dt.getFullYear()
|
||||
const m = (dt.getMonth() + 1 + '').padStart(2, '0')
|
||||
const d = (dt.getDate() + '').padStart(2, '0')
|
||||
const hh = (dt.getHours() + '').padStart(2, '0')
|
||||
const mm = (dt.getMinutes() + '').padStart(2, '0')
|
||||
const ss = (dt.getSeconds() + '').padStart(2, '0')
|
||||
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
PermissionUtil,
|
||||
StringUtil,
|
||||
ObjectUtil,
|
||||
LabelUtil
|
||||
LabelUtil,
|
||||
DateUtil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<el-dialog :title="title" :visible.sync="visible" :width="width" :fullscreen="fullscreen" :before-close="beforeClose">
|
||||
<el-form ref="form" :model="form.model" :rules="form.rules">
|
||||
<!-- 这里是插槽,用于渲染传入的 el-form-item -->
|
||||
<slot />
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="danger" @click="hidden">取 消</el-button>
|
||||
<!--<el-button @click="resetForm('form')">重 置</el-button>-->
|
||||
<el-button type="primary" @click="submitForm('form')">提 交</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'CuteFormDialog',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: '默认标题'
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '40%'
|
||||
},
|
||||
fullscreen: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
form: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
show() {
|
||||
this.visible = true
|
||||
},
|
||||
hidden() {
|
||||
this.resetForm('form')
|
||||
this.visible = false
|
||||
},
|
||||
submitForm(formName) {
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$emit('submit', this.form.model)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
resetForm(formName) {
|
||||
this.$refs[formName].resetFields()
|
||||
},
|
||||
beforeClose() {
|
||||
this.hidden()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-table
|
||||
ref="table"
|
||||
v-loading="crud.loading"
|
||||
stripe
|
||||
empty-text="暂无数据"
|
||||
:row-key="crud.primaryKey"
|
||||
fit
|
||||
:data="crud.dataSource"
|
||||
style="width: 100%;"
|
||||
height="450"
|
||||
max-height="450"
|
||||
@selection-change="onTableSelectionChange"
|
||||
>
|
||||
<el-table-column v-if="mode === 'multi'" type="selection" width="55" />
|
||||
<el-table-column v-for="(column, index) in crud.columns" :key="index" :label="column.label" :prop="column.prop" :formatter="column.formatter ? column.formatter : null" />
|
||||
<el-table-column v-if="crud.operateColumn" :width="crud.operateColumn.width" label="操作" :formatter="crud.operateColumn.formatter" :fixed="crud.operateColumn.fixed" />
|
||||
</el-table>
|
||||
<el-pagination
|
||||
:current-page="crud.pageProps.current"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
:page-size="crud.pageProps.pageSize"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
:total="crud.pageProps.total"
|
||||
@size-change="(size) => crud.onPageChange(crud.pageProps.current, size, crud.pageProps.total)"
|
||||
@current-change="(current) => crud.onPageChange(current, crud.pageProps.pageSize, crud.pageProps.total)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'CuteTable',
|
||||
props: {
|
||||
primaryKey: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: null
|
||||
},
|
||||
columns: {
|
||||
type: Array,
|
||||
required: true,
|
||||
default: null
|
||||
},
|
||||
operateColumn: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: null
|
||||
},
|
||||
dataSource: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
fetch: {
|
||||
type: Function,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
paramsTransform: {
|
||||
type: Function,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
responseTransform: {
|
||||
type: Function,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'none'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
crud: {
|
||||
loading: false,
|
||||
primaryKey: this.primaryKey ? this.primaryKey : 'id',
|
||||
columns: this.columns && this.columns.length > 0 ? this.columns : [],
|
||||
operateColumn: this.operateColumn,
|
||||
fetchUrl: null,
|
||||
dataSource: this.dataSource && this.dataSource.length > 0 ? this.dataSource : [],
|
||||
pageProps: {
|
||||
current: 1,
|
||||
pageSize: 10,
|
||||
total: 0
|
||||
},
|
||||
onPageChange: (currentPage, pageSize) => {
|
||||
this.crud.pageProps.current = currentPage
|
||||
this.crud.pageProps.pageSize = pageSize
|
||||
console.log('on-page-change', currentPage, pageSize)
|
||||
// this.$emit('onPageChange', currentPage, pageSize, total)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initData()
|
||||
},
|
||||
methods: {
|
||||
refresh() {
|
||||
this.initData()
|
||||
},
|
||||
async initData() {
|
||||
// 以dataSource属性为准
|
||||
if (this.dataSource) {
|
||||
this.crud.dataSource = this.dataSource
|
||||
return
|
||||
}
|
||||
let params = {}
|
||||
// 自定义请求参数
|
||||
if (this.paramsTransform) {
|
||||
params = this.paramsTransform(this.crud.pageProps)
|
||||
}
|
||||
if (this.fetch) {
|
||||
try {
|
||||
this.crud.loading = true
|
||||
// 请求远程数据
|
||||
const response = await this.fetch(params)
|
||||
// console.error('response', response)
|
||||
// { content: [], totalElements: 0 }
|
||||
// 转换为表格所需要的数据
|
||||
if (this.responseTransform) {
|
||||
return this.responseTransform(response)
|
||||
}
|
||||
if (response && response.totalElements && response.content) {
|
||||
this.crud.pageProps.total = response.totalElements
|
||||
this.crud.dataSource = response.content
|
||||
}
|
||||
return response
|
||||
} finally {
|
||||
this.crud.loading = false
|
||||
}
|
||||
}
|
||||
},
|
||||
onTableSelectionChange(selection) {
|
||||
this.$emit('selection-change', selection)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 工具栏 -->
|
||||
<div class="head-container">
|
||||
<el-form
|
||||
ref="searchForm"
|
||||
:inline="true"
|
||||
:model="form.model"
|
||||
label-position="right"
|
||||
label-width="80px"
|
||||
:rules="form.rules"
|
||||
>
|
||||
<el-form-item label="模糊查询" prop="blurry">
|
||||
<el-input v-model="form.model.blurry" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onFormSubmit('searchForm')">查询</el-button>
|
||||
<el-button @click="onFormReset('searchForm')">重置</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onCreateClick">创建XXX</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<!-- 表格渲染 -->
|
||||
<!-- fetch: 获取远程数据 -->
|
||||
<!-- params-transform: 组装查询参数 -->
|
||||
<!-- responseTransform: 组装表格对象。对响应结果做处理 -->
|
||||
<!-- primary-key: 主键 -->
|
||||
<!-- columns: 表格列 -->
|
||||
<!-- operate-column: 表格操作列 -->
|
||||
<!-- data-source: 数据源。当data-source不为空时,以data-source的数据为主 -->
|
||||
<!-- mode: 模式。不传默认,传multi为多选 -->
|
||||
<!-- @selection-change: 当且仅当mode为multi时启用 -->
|
||||
<cute-table
|
||||
ref="instance"
|
||||
:fetch="curd.fetch"
|
||||
:params-transform="curd.paramsTransform"
|
||||
primary-key="id"
|
||||
:columns="curd.columns"
|
||||
:operate-column="curd.operateColumn"
|
||||
:data-source="curd.dataSource"
|
||||
/>
|
||||
<cute-form-dialog ref="createForm" :form="createForm" title="创建XXX" @submit="onCreateFormSubmit">
|
||||
<el-form-item label="活动名称" prop="name" label-width="100px">
|
||||
<el-input v-model="createForm.model.name" placeholder="请输入" style="width: 100%" />
|
||||
</el-form-item>
|
||||
<el-form-item label="活动区域" prop="region" label-width="100px">
|
||||
<el-select v-model="createForm.model.region" placeholder="请选择" style="width: 100%">
|
||||
<el-option label="区域一" value="shanghai" />
|
||||
<el-option label="区域二" value="beijing" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</cute-form-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CuteTable from '@/views/components/dev/CuteTable'
|
||||
import { DateUtil } from '@/utils/myUtil'
|
||||
import DictService from '@/api/system/dict'
|
||||
import CuteFormDialog from '@/views/components/dev/CuteFormDialog.vue'
|
||||
|
||||
export default {
|
||||
name: 'ListDemo',
|
||||
components: { CuteFormDialog, CuteTable },
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
model: {
|
||||
blurry: ''
|
||||
},
|
||||
rules: {}
|
||||
},
|
||||
curd: {
|
||||
paramsTransform: (pageProps) => {
|
||||
const values = this.form.model
|
||||
return {
|
||||
page: pageProps.current,
|
||||
size: pageProps.pageSize,
|
||||
args: {
|
||||
...values
|
||||
}
|
||||
}
|
||||
},
|
||||
fetch: async(queryParams) => {
|
||||
return await DictService.queryPageDict(queryParams)
|
||||
},
|
||||
columns: [
|
||||
{ prop: 'name', label: '名称' },
|
||||
{ prop: 'description', label: '描述' },
|
||||
{ prop: 'createTime', label: '创建时间', formatter: DateUtil.formatRowDateTime },
|
||||
{ prop: 'createBy', label: '创建人' }
|
||||
],
|
||||
operateColumn: {
|
||||
width: '150',
|
||||
fixed: 'right',
|
||||
formatter: (row, column, cellValue, index) => {
|
||||
return (<div>
|
||||
<el-button type='text' onClick={() => {
|
||||
console.log('编辑')
|
||||
}}>编辑
|
||||
</el-button>
|
||||
<el-button type='text' onClick={() => {
|
||||
console.log('删除')
|
||||
}}>删除
|
||||
</el-button>
|
||||
</div>)
|
||||
}
|
||||
}
|
||||
},
|
||||
createForm: {
|
||||
model: {
|
||||
name: '',
|
||||
region: ''
|
||||
},
|
||||
rules: {
|
||||
name: [
|
||||
{ required: true, message: '请输入活动名称', trigger: 'blur' },
|
||||
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
|
||||
],
|
||||
region: [
|
||||
{ required: true, message: '请选择活动区域', trigger: 'change' }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initData()
|
||||
},
|
||||
methods: {
|
||||
initData() {
|
||||
this.$refs.instance.refresh()
|
||||
},
|
||||
onFormSubmit(formName) {
|
||||
const that = this
|
||||
that.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
that.$refs.instance.refresh()
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
},
|
||||
onFormReset(formName) {
|
||||
try {
|
||||
this.$refs[formName].resetFields()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
},
|
||||
onCreateClick() {
|
||||
this.$refs.createForm.show()
|
||||
},
|
||||
onCreateFormSubmit(values) {
|
||||
console.error('formValues', values)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="18" />
|
||||
<el-col :span="6" />
|
||||
</el-row></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'DemoTemplate',
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initData()
|
||||
},
|
||||
methods: {
|
||||
initData() {
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user