feat 审计日志模块和开发管理模块

This commit is contained in:
xxm
2022-10-23 21:55:57 +08:00
parent e5b1b50011
commit 9c67d80644
18 changed files with 1563 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
import { defHttp } from '/@/utils/http/axios'
import { Result } from "/#/axios";
/**
* 获取文件预览地址
*/
export const getFilePreviewUrl = (id) => {
return defHttp.get<Result<string>>({
url: `/file/getFilePreviewUrl`,
params: { id },
})
}
/**
* 获取文件地址前缀
*/
export const getFilePreviewUrlPrefix = () => {
return defHttp.get<Result<string>>({
url: `/file/getFilePreviewUrlPrefix`,
})
}
/**
* 获取文件下载地址
*/
export const getFileDownloadUrl = (id) => {
return defHttp.get<Result<string>>({
url: `/file/getFileDownloadUrl`,
params: { id },
})
}

View File

@@ -0,0 +1,5 @@
<template> </template>
<script lang="ts" setup></script>
<style scoped></style>

View File

@@ -0,0 +1,93 @@
import { defHttp } from '/@/utils/http/axios'
import { PageResult, Result } from '/#/axios'
import { BaseEntity } from '/#/web'
/**
* 分页
*/
export const page = (params) => {
return defHttp.get<Result<PageResult<DynamicForm>>>({
url: '/dynamic/form/page',
params,
})
}
/**
* 获取单条
*/
export const get = (id) => {
return defHttp.get<Result<DynamicForm>>({
url: '/dynamic/form/findById',
params: { id },
})
}
/**
* 添加
*/
export const add = (obj: DynamicForm) => {
return defHttp.post({
url: '/dynamic/form/add',
data: obj,
})
}
/**
* 更新
*/
export const update = (obj: DynamicForm) => {
return defHttp.post({
url: '/dynamic/form/update',
data: obj,
})
}
/**
* 删除
*/
export const del = (id) => {
return defHttp.delete({
url: '/dynamic/form/delete',
params: { id },
})
}
/**
* 查询全部
*/
export const findAll = () => {
return defHttp.get<Result<Array<DynamicForm>>>({
url: '/dynamic/form/findAll',
})
}
/**
* 编码是否存在
*/
export function existsByCode(code) {
return defHttp.get<Result<boolean>>({
url: '/dynamic/form/existsByCode',
params: { code },
})
}
export function existsByCodeNotId(code, id) {
return defHttp.get<Result<boolean>>({
url: '/dynamic/form/existsByCodeNotId',
params: { code, id },
})
}
/**
* 动态表单
*/
export interface DynamicForm extends BaseEntity {
// 表单名称
name: string
// 表单键名
code: string
// 表单内容
value?: string
// 备注
remark: string
}

View File

@@ -0,0 +1,127 @@
<template>
<basic-modal
v-bind="$attrs"
:loading="confirmLoading"
:width="modalWidth"
:title="title"
:visible="visible"
:mask-closable="showable"
@cancel="handleCancel"
>
<a-form class="small-from-item" ref="formRef" :model="form" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-form-item label="主键" :hidden="true">
<a-input v-model:value="form.id" :disabled="showable" />
</a-form-item>
<a-form-item label="表单名称" name="name">
<a-input v-model:value="form.name" :disabled="showable" placeholder="请输入表单名称" />
</a-form-item>
<a-form-item label="表单编码" name="code">
<a-input v-model:value="form.code" :disabled="showable" placeholder="请输入表单键名" />
</a-form-item>
<a-form-item label="备注" name="remark">
<a-textarea v-model:value="form.remark" :disabled="showable" placeholder="请输入备注" />
</a-form-item>
</a-form>
<template #footer>
<a-space>
<a-button key="cancel" @click="handleCancel">取消</a-button>
<a-button v-if="!showable" key="forward" :loading="confirmLoading" type="primary" @click="handleOk">保存</a-button>
</a-space>
</template>
</basic-modal>
</template>
<script lang="ts" setup>
import { nextTick, reactive } from 'vue'
import { $ref } from 'vue/macros'
import useFormEdit from '/@/hooks/bootx/useFormEdit'
import { add, get, update, existsByCode, existsByCodeNotId, DynamicForm } from './DynamicForm.api'
import { FormInstance, Rule } from 'ant-design-vue/lib/form'
import { FormEditType } from '/@/enums/formTypeEnum'
import { BasicModal } from '/@/components/Modal'
import { useValidate } from '/@/hooks/bootx/useValidate'
const {
initFormModel,
handleCancel,
search,
labelCol,
wrapperCol,
modalWidth,
title,
confirmLoading,
visible,
editable,
showable,
formEditType,
} = useFormEdit()
const { existsByServer } = useValidate()
// 表单
const formRef = $ref<FormInstance>()
let form = $ref({
id: null,
code: '',
name: '',
remark: '',
} as DynamicForm)
// 校验
const rules = reactive({
code: [
{ required: true, message: '请输入表单编码', trigger: ['blur', 'change'] },
{ required: true, validator: validateCode, trigger: 'blur' },
],
name: [{ required: true, message: '请输入表单名称', trigger: ['blur', 'change'] }],
} as Record<string, Rule[]>)
// 事件
const emits = defineEmits(['ok'])
// 入口
function init(id, editType: FormEditType) {
initFormModel(id, editType)
resetForm()
getInfo(id, editType)
}
// 获取信息
function getInfo(id, editType: FormEditType) {
if ([FormEditType.Edit, FormEditType.Show].includes(editType)) {
confirmLoading.value = true
get(id).then(({ data }) => {
form = data
confirmLoading.value = false
})
} else {
confirmLoading.value = false
}
}
// 保存
function handleOk() {
formRef.validate().then(async () => {
confirmLoading.value = true
if (formEditType.value === FormEditType.Add) {
await add(form)
} else if (formEditType.value === FormEditType.Edit) {
await update(form)
}
confirmLoading.value = false
handleCancel()
emits('ok')
})
}
// 重置表单的校验
function resetForm() {
nextTick(() => {
formRef.resetFields()
})
}
// 校验编码重复
async function validateCode() {
const { code, id } = form
return existsByServer(code, id, formEditType, existsByCode, existsByCodeNotId)
}
defineExpose({
init,
})
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,151 @@
<template>
<div>
<div class="m-3 p-3 pt-5 bg-white">
<b-query :query-params="model.queryParam" :fields="fields" @query="queryPage" @reset="resetQueryParams" />
</div>
<div class="m-3 p-3 bg-white">
<vxe-toolbar ref="xToolbar" custom :refresh="{ query: queryPage }">
<template #buttons>
<a-space>
<a-button type="primary" @click="add">新建</a-button>
</a-space>
</template>
</vxe-toolbar>
<vxe-table row-id="id" ref="xTable" :data="pagination.records" :loading="loading">
<vxe-column type="seq" width="60" />
<vxe-column field="name" title="表单名称" />
<vxe-column field="code" title="表单编码" />
<vxe-column field="remark" title="备注" />
<vxe-column field="createTime" title="创建时间" />
<vxe-column fixed="right" width="240" :showOverflow="false" title="操作">
<template #default="{ row }">
<span>
<a href="javascript:" @click="show(row)">查看</a>
</span>
<a-divider type="vertical" />
<span>
<a href="javascript:" @click="edit(row)">编辑</a>
</span>
<a-divider type="vertical" />
<span>
<a href="javascript:" @click="design(row.id)">表单设计</a>
</span>
<a-divider type="vertical" />
<a-dropdown>
<a> 更多 <Icon icon="ant-design:down-outlined" :size="12" /> </a>
<template #overlay>
<a-menu>
<a-menu-item>
<a href="javascript:" @click="preview(row.id)">预览表单</a>
</a-menu-item>
<a-menu-item>
<a href="javascript:">配置地址</a>
</a-menu-item>
<a-menu-item>
<a href="javascript:" @click="remove(row)" style="color: red">删除</a>
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</template>
</vxe-column>
</vxe-table>
<vxe-pager
size="medium"
:loading="loading"
:current-page="pagination.current"
:page-size="pagination.size"
:total="pagination.total"
@page-change="handleTableChange"
/>
<dynamic-form-edit ref="dynamicFormEdit" @ok="queryPage" />
<dynamic-design ref="dynamicDesign" />
<dynamic-preview ref="dynamicPreview" />
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import { $ref } from 'vue/macros'
import { del, page } from './DynamicForm.api'
import useTablePage from '/@/hooks/bootx/useTablePage'
import DynamicFormEdit from './DynamicFormEdit.vue'
import { VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
import { FormEditType } from '/@/enums/formTypeEnum'
import { useMessage } from '/@/hooks/web/useMessage'
import { QueryField } from '/@/components/Bootx/Query/Query'
import DynamicDesign from '/@/views/modules/develop/dynamicform/DynamicDesign.vue'
import DynamicPreview from '/@/views/modules/develop/dynamicform/DynamicPreview.vue'
import Icon from '/@/components/Icon/src/Icon.vue'
// 使用hooks
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, pages, model, loading } = useTablePage(queryPage)
const { notification, createConfirm } = useMessage()
// 查询条件
const fields = [
{ field: 'code', type: 'string', name: '编码', placeholder: '请输入编码' },
{ field: 'name', type: 'string', name: '名称', placeholder: '请输入名称' },
] as QueryField[]
const xTable = $ref<VxeTableInstance>()
const xToolbar = $ref<VxeToolbarInstance>()
const dynamicFormEdit = $ref<any>()
const dynamicDesign = $ref<any>()
const dynamicPreview = $ref<any>()
onMounted(() => {
vxeBind()
queryPage()
})
function vxeBind() {
xTable.connect(xToolbar)
}
// 分页查询
function queryPage() {
loading.value = true
page({
...model.queryParam,
...pages,
}).then(({ data }) => {
pageQueryResHandel(data)
})
}
// 新增
function add() {
dynamicFormEdit.init(null, FormEditType.Add)
}
// 编辑
function edit(record) {
dynamicFormEdit.init(record.id, FormEditType.Edit)
}
// 查看
function show(record) {
dynamicFormEdit.init(record.id, FormEditType.Show)
}
// 设计
function design(record) {}
// 设计
function preview(record) {}
// 删除
function remove(record) {
createConfirm({
iconType: 'warning',
title: '警告',
content: '是否删除该表单',
onOk: () => {
del(record.id).then(() => {
notification.success({ message: '删除成功' })
queryPage()
})
},
})
}
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,5 @@
<template> </template>
<script lang="ts" setup></script>
<style scoped></style>

View File

@@ -0,0 +1,86 @@
import { defHttp } from '/@/utils/http/axios'
import { PageResult, Result } from '/#/axios'
import { BaseEntity } from '/#/web'
/**
* 分页
*/
export const page = (params) => {
return defHttp.get<Result<PageResult<DynamicDataSource>>>({
url: '/dynamic/source/page',
params,
})
}
/**
* 获取单条
*/
export const get = (id) => {
return defHttp.get<Result<DynamicDataSource>>({
url: '/dynamic/source/findById',
params: { id },
})
}
/**
* 添加
*/
export const add = (obj: DynamicDataSource) => {
return defHttp.post({
url: '/dynamic/source/add',
data: obj,
})
}
/**
* 更新
*/
export const update = (obj: DynamicDataSource) => {
return defHttp.post({
url: '/dynamic/source/update',
data: obj,
})
}
/**
* 删除
*/
export const del = (id) => {
return defHttp.delete({
url: '/dynamic/source/delete',
params: { id },
})
}
/**
* 查询全部
*/
export const findAll = () => {
return defHttp.get<Result<Array<DynamicDataSource>>>({
url: '/dynamic/source/findAll',
})
}
/**
* 动态数据源管理
*/
export interface DynamicDataSource extends BaseEntity {
// 数据源编码
code: string
// 数据源名称
name: string
// 数据库类型
databaseType: string
// 驱动类
dbDriver: string
// 数据库地址
dbUrl: string
// 数据库名称
dbName: string
// 用户名
dbUsername: string
// 密码
dbPassword: string
// 备注
remark: string
}

View File

@@ -0,0 +1,137 @@
<template>
<basic-modal
v-bind="$attrs"
:loading="confirmLoading"
:width="modalWidth"
:title="title"
:visible="visible"
:mask-closable="showable"
@cancel="handleCancel"
>
<a-form class="small-from-item" ref="formRef" :model="form" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-form-item label="主键" :hidden="true">
<a-input v-model:value="form.id" :disabled="showable" />
</a-form-item>
<a-form-item label="数据源编码" name="code">
<a-input v-model:value="form.code" :disabled="showable" placeholder="请输入数据源编码" />
</a-form-item>
<a-form-item label="数据源名称" name="name">
<a-input v-model:value="form.name" :disabled="showable" placeholder="请输入数据源名称" />
</a-form-item>
<a-form-item label="数据库类型" name="databaseType">
<a-input v-model:value="form.databaseType" :disabled="showable" placeholder="请输入数据库类型" />
</a-form-item>
<a-form-item label="驱动类" name="dbDriver">
<a-input v-model:value="form.dbDriver" :disabled="showable" placeholder="请输入驱动类" />
</a-form-item>
<a-form-item label="数据库地址" name="dbUrl">
<a-input v-model:value="form.dbUrl" :disabled="showable" placeholder="请输入数据库地址" />
</a-form-item>
<a-form-item label="数据库名称" name="dbName">
<a-input v-model:value="form.dbName" :disabled="showable" placeholder="请输入数据库名称" />
</a-form-item>
<a-form-item label="用户名" name="dbUsername">
<a-input v-model:value="form.dbUsername" :disabled="showable" placeholder="请输入用户名" />
</a-form-item>
<a-form-item label="密码" name="dbPassword">
<a-input v-model:value="form.dbPassword" :disabled="showable" placeholder="请输入密码" />
</a-form-item>
<a-form-item label="备注" name="remark">
<a-input v-model:value="form.remark" :disabled="showable" placeholder="请输入备注" />
</a-form-item>
</a-form>
<template #footer>
<a-space>
<a-button key="cancel" @click="handleCancel">取消</a-button>
<a-button v-if="!showable" key="forward" :loading="confirmLoading" type="primary" @click="handleOk">保存</a-button>
</a-space>
</template>
</basic-modal>
</template>
<script lang="ts" setup>
import { nextTick, reactive } from 'vue'
import { $ref } from 'vue/macros'
import useFormEdit from '/@/hooks/bootx/useFormEdit'
import { add, get, update, DynamicDataSource } from './DynamicDataSource.api'
import { FormInstance, Rule } from 'ant-design-vue/lib/form'
import { FormEditType } from '/@/enums/formTypeEnum'
import { BasicModal } from '/@/components/Modal'
const {
initFormModel,
handleCancel,
search,
labelCol,
wrapperCol,
modalWidth,
title,
confirmLoading,
visible,
editable,
showable,
formEditType,
} = useFormEdit()
// 表单
const formRef = $ref<FormInstance>()
let form = $ref({
id: null,
code: null,
name: null,
databaseType: null,
dbDriver: null,
dbUrl: null,
dbName: null,
dbUsername: null,
dbPassword: null,
remark: null,
} as DynamicDataSource)
// 校验
const rules = reactive({} as Record<string, Rule[]>)
// 事件
const emits = defineEmits(['ok'])
// 入口
function init(id, editType: FormEditType) {
initFormModel(id, editType)
resetForm()
getInfo(id, editType)
}
// 获取信息
function getInfo(id, editType: FormEditType) {
if ([FormEditType.Edit, FormEditType.Show].includes(editType)) {
confirmLoading.value = true
get(id).then(({ data }) => {
form = data
confirmLoading.value = false
})
} else {
confirmLoading.value = false
}
}
// 保存
function handleOk() {
formRef.validate().then(async () => {
confirmLoading.value = true
if (formEditType.value === FormEditType.Add) {
await add(form)
} else if (formEditType.value === FormEditType.Edit) {
await update(form)
}
confirmLoading.value = false
handleCancel()
emits('ok')
})
}
// 重置表单的校验
function resetForm() {
nextTick(() => {
formRef.resetFields()
})
}
defineExpose({
init,
})
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,118 @@
<template>
<div>
<div class="m-3 p-3 pt-5 bg-white">
<b-query :query-params="model.queryParam" :fields="fields" @query="queryPage" @reset="resetQueryParams" />
</div>
<div class="m-3 p-3 bg-white">
<vxe-toolbar ref="xToolbar" custom :refresh="{ query: queryPage }">
<template #buttons>
<a-space>
<a-button type="primary" @click="add">新建</a-button>
</a-space>
</template>
</vxe-toolbar>
<vxe-table row-id="id" ref="xTable" :data="pagination.records" :loading="loading">
<vxe-column type="seq" width="60" />
<vxe-column field="code" title="编码" />
<vxe-column field="name" title="名称" />
<vxe-column field="databaseType" title="类型" />
<vxe-column field="dbDriver" title="驱动类" />
<vxe-column field="dbName" title="数据库名称" />
<vxe-column field="remark" title="备注" />
<vxe-column field="createTime" title="创建时间" />
<vxe-column fixed="right" width="150" :showOverflow="false" title="操作">
<template #default="{ row }">
<span>
<a href="javascript:" @click="show(row)">查看</a>
</span>
<a-divider type="vertical" />
<span>
<a href="javascript:" @click="edit(row)">编辑</a>
</span>
<a-divider type="vertical" />
<a-popconfirm title="是否删除" @confirm="remove(row)" okText="是" cancelText="否">
<a href="javascript:" style="color: red">删除</a>
</a-popconfirm>
</template>
</vxe-column>
</vxe-table>
<vxe-pager
size="medium"
:loading="loading"
:current-page="pagination.current"
:page-size="pagination.size"
:total="pagination.total"
@page-change="handleTableChange"
/>
<dynamic-data-source-edit ref="dynamicDataSourceEdit" @ok="queryPage" />
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import { $ref } from 'vue/macros'
import { del, page } from './DynamicDataSource.api'
import useTablePage from '/@/hooks/bootx/useTablePage'
import DynamicDataSourceEdit from './DynamicDataSourceEdit.vue'
import { VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
import { FormEditType } from '/@/enums/formTypeEnum'
import { useMessage } from '/@/hooks/web/useMessage'
import { QueryField } from '/@/components/Bootx/Query/Query'
// 使用hooks
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, pages, model, loading } = useTablePage(queryPage)
const { notification, createMessage, createConfirm } = useMessage()
// 查询条件
const fields = [
{ field: 'code', type: 'string', name: '编码', placeholder: '请输入编码' },
{ field: 'name', type: 'string', name: '名称', placeholder: '请输入名称' },
] as QueryField[]
const xTable = $ref<VxeTableInstance>()
const xToolbar = $ref<VxeToolbarInstance>()
const dynamicDataSourceEdit = $ref<any>()
onMounted(() => {
vxeBind()
queryPage()
})
function vxeBind() {
xTable.connect(xToolbar)
}
// 分页查询
function queryPage() {
loading.value = true
page({
...model.queryParam,
...pages,
}).then(({ data }) => {
pageQueryResHandel(data)
})
}
// 新增
function add() {
dynamicDataSourceEdit.init(null, FormEditType.Add)
}
// 编辑
function edit(record) {
dynamicDataSourceEdit.init(record.id, FormEditType.Edit)
}
// 查看
function show(record) {
dynamicDataSourceEdit.init(record.id, FormEditType.Show)
}
// 删除
function remove(record) {
del(record.id).then(() => {
createMessage.success('删除成功')
})
queryPage()
}
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,80 @@
import { defHttp } from '/@/utils/http/axios'
import { PageResult, Result } from '/#/axios'
import { BaseEntity } from '/#/web'
/**
* 分页
*/
export const page = (params) => {
return defHttp.get<Result<PageResult<FileUpload>>>({
url: '/file/page',
params,
})
}
/**
* 获取单条
*/
export const get = (id) => {
return defHttp.get<Result<FileUpload>>({
url: '/file/findById',
params: { id },
})
}
/**
* 添加
*/
export const add = (obj: FileUpload) => {
return defHttp.post({
url: '/file/add',
data: obj,
})
}
/**
* 更新
*/
export const update = (obj: FileUpload) => {
return defHttp.post({
url: '/file/update',
data: obj,
})
}
/**
* 删除
*/
export const del = (id) => {
return defHttp.delete({
url: '/file/delete',
params: { id },
})
}
/**
* 查询全部
*/
export const findAll = () => {
return defHttp.get<Result<Array<FileUpload>>>({
url: '/file/findAll',
})
}
/**
* 上传文件信息
*/
export interface FileUpload extends BaseEntity {
// 存储位置
filePath: string
// 文件名称
fileName: string
// 文件类型
fileType: string
// 文件后缀
fileSuffix: string
// 文件大小
fileSize: number
// 外部关联id
externalStorageId: string
}

View File

@@ -0,0 +1,125 @@
<template>
<basic-modal
v-bind="$attrs"
:loading="confirmLoading"
:width="modalWidth"
:title="title"
:visible="visible"
:mask-closable="showable"
@cancel="handleCancel"
>
<a-form class="small-from-item" ref="formRef" :model="form" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-form-item label="主键" :hidden="true">
<a-input v-model:value="form.id" :disabled="showable" />
</a-form-item>
<a-form-item label="存储位置" name="filePath">
<a-input v-model:value="form.filePath" :disabled="showable" placeholder="请输入存储位置" />
</a-form-item>
<a-form-item label="文件名称" name="fileName">
<a-input v-model:value="form.fileName" :disabled="showable" placeholder="请输入文件名称" />
</a-form-item>
<a-form-item label="文件类型" name="fileType">
<a-input v-model:value="form.fileType" :disabled="showable" placeholder="请输入文件类型" />
</a-form-item>
<a-form-item label="文件后缀" name="fileSuffix">
<a-input v-model:value="form.fileSuffix" :disabled="showable" placeholder="请输入文件后缀" />
</a-form-item>
<a-form-item label="文件大小" name="fileSize">
<a-input v-model:value="form.fileSize" :disabled="showable" placeholder="请输入文件大小" />
</a-form-item>
<a-form-item label="外部关联id" name="externalStorageId">
<a-input v-model:value="form.externalStorageId" :disabled="showable" placeholder="请输入外部关联id" />
</a-form-item>
</a-form>
<template #footer>
<a-space>
<a-button key="cancel" @click="handleCancel">取消</a-button>
<a-button v-if="!showable" key="forward" :loading="confirmLoading" type="primary" @click="handleOk">保存</a-button>
</a-space>
</template>
</basic-modal>
</template>
<script lang="ts" setup>
import { nextTick, reactive } from 'vue'
import { $ref } from 'vue/macros'
import useFormEdit from '/@/hooks/bootx/useFormEdit'
import { add, get, update, FileUpload } from './FileUpload.api'
import { FormInstance, Rule } from 'ant-design-vue/lib/form'
import { FormEditType } from '/@/enums/formTypeEnum'
import { BasicModal } from '/@/components/Modal'
const {
initFormModel,
handleCancel,
search,
labelCol,
wrapperCol,
modalWidth,
title,
confirmLoading,
visible,
editable,
showable,
formEditType,
} = useFormEdit()
// 表单
const formRef = $ref<FormInstance>()
let form = $ref({
id: null,
filePath: null,
fileName: null,
fileType: null,
fileSuffix: null,
fileSize: null,
externalStorageId: null,
} as FileUpload)
// 校验
const rules = reactive({} as Record<string, Rule[]>)
// 事件
const emits = defineEmits(['ok'])
// 入口
function init(id, editType: FormEditType) {
initFormModel(id, editType)
resetForm()
getInfo(id, editType)
}
// 获取信息
function getInfo(id, editType: FormEditType) {
if ([FormEditType.Edit, FormEditType.Show].includes(editType)) {
confirmLoading.value = true
get(id).then(({ data }) => {
form = data
confirmLoading.value = false
})
} else {
confirmLoading.value = false
}
}
// 保存
function handleOk() {
formRef.validate().then(async () => {
confirmLoading.value = true
if (formEditType.value === FormEditType.Add) {
await add(form)
} else if (formEditType.value === FormEditType.Edit) {
await update(form)
}
confirmLoading.value = false
handleCancel()
emits('ok')
})
}
// 重置表单的校验
function resetForm() {
nextTick(() => {
formRef.resetFields()
})
}
defineExpose({
init,
})
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,98 @@
<template>
<div>
<div class="m-3 p-3 pt-5 bg-white">
<b-query :query-params="model.queryParam" :fields="fields" @query="queryPage" @reset="resetQueryParams" />
</div>
<div class="m-3 p-3 bg-white">
<vxe-toolbar ref="xToolbar" custom :refresh="{ query: queryPage }">
<template #buttons>
<a-space>
<a-button type="primary" preIcon="ant-design:upload-outlined" @click="add">上传</a-button>
</a-space>
</template>
</vxe-toolbar>
<vxe-table row-id="id" ref="xTable" :data="pagination.records" :loading="loading">
<vxe-column type="seq" width="60" />
<vxe-column field="fileName" title="文件名称" />
<vxe-column field="fileSuffix" title="文件后缀" />
<vxe-column field="fileType" title="文件类型" />
<vxe-column field="fileSize" title="文件大小" />
<vxe-column field="createTime" title="创建时间" />
<vxe-column fixed="right" width="150" :showOverflow="false" title="操作">
<template #default="{ row }">
<a href="javascript:" @click="show(row)">查看</a>
<a-divider type="vertical" />
<a href="javascript:" @click="down(row)">下载</a>
</template>
</vxe-column>
</vxe-table>
<vxe-pager
size="medium"
:loading="loading"
:current-page="pagination.current"
:page-size="pagination.size"
:total="pagination.total"
@page-change="handleTableChange"
/>
<file-upload-edit ref="fileUploadEdit" @ok="queryPage" />
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import { $ref } from 'vue/macros'
import { del, page } from './FileUpload.api'
import useTablePage from '/@/hooks/bootx/useTablePage'
import FileUploadEdit from './FileUploadEdit.vue'
import { VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
import { FormEditType } from '/@/enums/formTypeEnum'
import { useMessage } from '/@/hooks/web/useMessage'
import { QueryField } from '/@/components/Bootx/Query/Query'
import { getFileDownloadUrl, getFilePreviewUrl } from '/@/api/common/fileUpload'
// 使用hooks
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, pages, model, loading } = useTablePage(queryPage)
const { notification, createMessage } = useMessage()
// 查询条件
const fields = [] as QueryField[]
const xTable = $ref<VxeTableInstance>()
const xToolbar = $ref<VxeToolbarInstance>()
const fileUploadEdit = $ref<any>()
onMounted(() => {
vxeBind()
queryPage()
})
function vxeBind() {
xTable.connect(xToolbar)
}
// 分页查询
function queryPage() {
loading.value = true
page({
...model.queryParam,
...pages,
}).then(({ data }) => {
pageQueryResHandel(data)
})
}
// 查看
function show(record) {
getFilePreviewUrl(record.id).then((res) => {
window.open(res.data)
})
}
// 下载
function down(record) {
getFileDownloadUrl(record.id).then((res) => {
window.open(res.data)
})
}
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,74 @@
import { defHttp } from '/@/utils/http/axios'
import { PageResult, Result } from '/#/axios'
import { BaseEntity } from '/#/web'
/**
* 分页
*/
export const page = (params) => {
return defHttp.get<Result<PageResult<DataVersionLog>>>({
url: '/log/dataVersion/page',
params,
})
}
/**
* 获取单条
*/
export const get = (id) => {
return defHttp.get<Result<DataVersionLog>>({
url: '/log/dataVersion/findById',
params: { id },
})
}
/**
* 添加
*/
export const add = (obj: DataVersionLog) => {
return defHttp.post({
url: '/log/dataVersion/add',
data: obj,
})
}
/**
* 更新
*/
export const update = (obj: DataVersionLog) => {
return defHttp.post({
url: '/log/dataVersion/update',
data: obj,
})
}
/**
* 删除
*/
export const del = (id) => {
return defHttp.delete({
url: '/log/dataVersion/delete',
params: { id },
})
}
/**
* 查询全部
*/
export const findAll = () => {
return defHttp.get<Result<Array<DataVersionLog>>>({
url: '/log/dataVersion/findAll',
})
}
/**
* 数据版本日志
*/
export interface DataVersionLog extends BaseEntity {
// 数据名称
dataName: string
// 数据主键
dataId: string
// 数据内容
dataContent: string
}

View File

@@ -0,0 +1,113 @@
<template>
<basic-modal
v-bind="$attrs"
:loading="confirmLoading"
:width="modalWidth"
:title="title"
:visible="visible"
:mask-closable="showable"
@cancel="handleCancel"
>
<a-form class="small-from-item" ref="formRef" :model="form" :rules="rules" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-form-item label="主键" :hidden="true">
<a-input v-model:value="form.id" :disabled="showable" />
</a-form-item>
<a-form-item label="数据名称" name="dataName">
<a-input v-model:value="form.dataName" :disabled="showable" placeholder="请输入数据名称" />
</a-form-item>
<a-form-item label="数据主键" name="dataId">
<a-input v-model:value="form.dataId" :disabled="showable" placeholder="请输入数据主键" />
</a-form-item>
<a-form-item label="数据内容" name="dataContent">
<a-input v-model:value="form.dataContent" :disabled="showable" placeholder="请输入数据内容" />
</a-form-item>
</a-form>
<template #footer>
<a-space>
<a-button key="cancel" @click="handleCancel">取消</a-button>
<a-button v-if="!showable" key="forward" :loading="confirmLoading" type="primary" @click="handleOk">保存</a-button>
</a-space>
</template>
</basic-modal>
</template>
<script lang="ts" setup>
import { nextTick, reactive } from 'vue'
import { $ref } from 'vue/macros'
import useFormEdit from '/@/hooks/bootx/useFormEdit'
import { add, get, update, DataVersionLog } from './DataVersionLog.api'
import { FormInstance, Rule } from 'ant-design-vue/lib/form'
import { FormEditType } from '/@/enums/formTypeEnum'
import { BasicModal } from '/@/components/Modal'
const {
initFormModel,
handleCancel,
search,
labelCol,
wrapperCol,
modalWidth,
title,
confirmLoading,
visible,
editable,
showable,
formEditType,
} = useFormEdit()
// 表单
const formRef = $ref<FormInstance>()
let form = $ref({
id: null,
dataName: null,
dataId: null,
dataContent: null,
} as DataVersionLog)
// 校验
const rules = reactive({} as Record<string, Rule[]>)
// 事件
const emits = defineEmits(['ok'])
// 入口
function init(id, editType: FormEditType) {
initFormModel(id, editType)
resetForm()
getInfo(id, editType)
}
// 获取信息
function getInfo(id, editType: FormEditType) {
if ([FormEditType.Edit, FormEditType.Show].includes(editType)) {
confirmLoading.value = true
get(id).then(({ data }) => {
form = data
confirmLoading.value = false
})
} else {
confirmLoading.value = false
}
}
// 保存
function handleOk() {
formRef.validate().then(async () => {
confirmLoading.value = true
if (formEditType.value === FormEditType.Add) {
await add(form)
} else if (formEditType.value === FormEditType.Edit) {
await update(form)
}
confirmLoading.value = false
handleCancel()
emits('ok')
})
}
// 重置表单的校验
function resetForm() {
nextTick(() => {
formRef.resetFields()
})
}
defineExpose({
init,
})
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,112 @@
<template>
<div>
<div class="m-3 p-3 pt-5 bg-white">
<b-query :query-params="model.queryParam" :fields="fields" @query="queryPage" @reset="resetQueryParams" />
</div>
<div class="m-3 p-3 bg-white">
<vxe-toolbar ref="xToolbar" custom :refresh="{ query: queryPage }">
<template #buttons>
<a-space>
<a-button type="primary" @click="add">新建</a-button>
</a-space>
</template>
</vxe-toolbar>
<vxe-table row-id="id" ref="xTable" :data="pagination.records" :loading="loading">
<vxe-column type="seq" width="60" />
<vxe-column field="dataName" title="数据名称" />
<vxe-column field="dataId" title="数据主键" />
<vxe-column field="dataContent" title="数据内容" />
<vxe-column field="createTime" title="创建时间" />
<vxe-column fixed="right" width="150" :showOverflow="false" title="操作">
<template #default="{ row }">
<span>
<a href="javascript:" @click="show(row)">查看</a>
</span>
<a-divider type="vertical" />
<span>
<a href="javascript:" @click="edit(row)">编辑</a>
</span>
<a-divider type="vertical" />
<a-popconfirm title="是否删除" @confirm="remove(row)" okText="是" cancelText="否">
<a href="javascript:" style="color: red">删除</a>
</a-popconfirm>
</template>
</vxe-column>
</vxe-table>
<vxe-pager
size="medium"
:loading="loading"
:current-page="pagination.current"
:page-size="pagination.size"
:total="pagination.total"
@page-change="handleTableChange"
/>
<data-version-log-edit ref="dataVersionLogEdit" @ok="queryPage" />
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import { $ref } from 'vue/macros'
import { del, page } from './DataVersionLog.api'
import useTablePage from '/@/hooks/bootx/useTablePage'
import DataVersionLogEdit from './DataVersionLogEdit.vue'
import { VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
import { FormEditType } from '/@/enums/formTypeEnum'
import { useMessage } from '/@/hooks/web/useMessage'
import { QueryField } from '/@/components/Bootx/Query/Query'
// 使用hooks
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, pages, model, loading } = useTablePage(queryPage)
const { notification, createMessage } = useMessage()
// 查询条件
const fields = [] as QueryField[]
const xTable = $ref<VxeTableInstance>()
const xToolbar = $ref<VxeToolbarInstance>()
const dataVersionLogEdit = $ref<any>()
onMounted(() => {
vxeBind()
queryPage()
})
function vxeBind() {
xTable.connect(xToolbar)
}
// 分页查询
function queryPage() {
loading.value = true
page({
...model.queryParam,
...pages,
}).then(({ data }) => {
pageQueryResHandel(data)
})
}
// 新增
function add() {
dataVersionLogEdit.init(null, FormEditType.Add)
}
// 查看
function edit(record) {
dataVersionLogEdit.init(record.id, FormEditType.Edit)
}
// 查看
function show(record) {
dataVersionLogEdit.init(record.id, FormEditType.Show)
}
// 删除
function remove(record) {
del(record.id).then(() => {
createMessage.success('删除成功')
})
queryPage()
}
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,57 @@
import { defHttp } from '/@/utils/http/axios'
import { PageResult, Result } from '/#/axios'
import { BaseEntity } from '/#/web'
/**
* 分页
*/
export const page = (params) => {
return defHttp.get<Result<PageResult<OperateLog>>>({
url: '/log/operate/page',
params,
})
}
/**
* 获取单条
*/
export const get = (id) => {
return defHttp.get<Result<OperateLog>>({
url: '/log/operate/findById',
params: { id },
})
}
/**
* 操作日志
*/
export interface OperateLog extends BaseEntity {
// 操作模块
title: string
// 操作人员id
operateId: number
// 操作人员账号
username: string
// 业务类型
businessType: string
// 请求方法
method: string
// 请求方式
requestMethod: string
// 请求url
operateUrl: string
// 操作ip
operateIp: string
// 操作地点
operateLocation: string
// 请求参数
operateParam: string
// 返回参数
operateReturn: string
// 是否成功
success: boolean
// 错误提示
errorMsg: string
// 操作时间
operateTime: string
}

View File

@@ -0,0 +1,52 @@
<template>
<basic-modal v-bind="$attrs" :loading="confirmLoading" width="50%" title="查看" :visible="visible" @cancel="visible = false">
<description :column="2" :data="data" :schema="schema" />
<template #footer>
<a-button key="cancel" @click="visible = false">取消</a-button>
</template>
</basic-modal>
</template>
<script lang="ts" setup>
import { $ref } from 'vue/macros'
import { get, OperateLog } from './OperateLog.api'
import { BasicModal } from '/@/components/Modal'
import Description from '/@/components/Description/src/Description.vue'
import { DescItem } from '/@/components/Description'
import { useDict } from '/@/hooks/bootx/useDict'
const { dictConvert } = useDict()
let data = $ref<OperateLog>()
let visible = $ref(false)
let confirmLoading = $ref(false)
let schema = [
{ field: 'id', label: '主键' },
{ field: 'username', label: '操作人员账号' },
{ field: 'title', label: '操作模块' },
{ field: 'client', label: '业务类型', render: (businessType) => dictConvert('LogBusinessType', businessType) },
{ field: 'requestMethod', label: '请求方式' },
{ field: 'operateUrl', label: '请求url' },
{ field: 'method', label: '操作方法' },
{ field: 'success', label: '操作状态', render: (success) => (success ? '成功' : '失败') },
{ field: 'errorMsg', label: '提示消息' },
{ field: 'operateParam', label: '请求参数' },
{ field: 'operateReturn', label: '响应参数' },
{ field: 'operateTime', label: '操作时间' },
] as DescItem[]
function show(id) {
visible = true
confirmLoading = true
get(id).then((res) => {
data = res.data
confirmLoading = false
})
}
defineExpose({
show,
})
</script>
<style lang="less" scoped></style>

View File

@@ -0,0 +1,99 @@
<template>
<div>
<div class="m-3 p-3 pt-5 bg-white">
<b-query :query-params="model.queryParam" :fields="fields" @query="queryPage" @reset="resetQueryParams" />
</div>
<div class="m-3 p-3 bg-white">
<vxe-toolbar ref="xToolbar" custom :refresh="{ query: queryPage }" />
<vxe-table row-id="id" ref="xTable" :data="pagination.records" :loading="loading">
<vxe-column type="seq" width="60" />
<vxe-column field="operateId" title="操作人员id" />
<vxe-column field="username" title="操作人员账号" />
<vxe-column field="title" title="操作模块" />
<vxe-column field="success" title="是否成功">
<template #default="{ row }">
<a-tag v-if="row.success" color="green">成功</a-tag>
<a-tag v-else color="red">失败</a-tag>
</template>
</vxe-column>
<vxe-column field="businessType" title="业务类型">
<template #default="{ row }">
{{ dictConvert('LogBusinessType', row.businessType) }}
</template>
</vxe-column>
<vxe-column field="operateIp" title="操作ip" />
<vxe-column field="errorMsg" title="错误提示" />
<vxe-column field="operateTime" title="操作时间" />
<vxe-column fixed="right" width="60" :showOverflow="false" title="操作">
<template #default="{ row }">
<span>
<a href="javascript:" @click="show(row)">查看</a>
</span>
</template>
</vxe-column>
</vxe-table>
<vxe-pager
size="medium"
:loading="loading"
:current-page="pagination.current"
:page-size="pagination.size"
:total="pagination.total"
@page-change="handleTableChange"
/>
<operate-log-edit ref="operateLogEdit" @ok="queryPage" />
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import { $ref } from 'vue/macros'
import { page } from './OperateLog.api'
import useTablePage from '/@/hooks/bootx/useTablePage'
import OperateLogEdit from './OperateLogInfo.vue'
import { VxeTableInstance, VxeToolbarInstance } from 'vxe-table'
import BQuery from '/@/components/Bootx/Query/BQuery.vue'
import { FormEditType } from '/@/enums/formTypeEnum'
import { useMessage } from '/@/hooks/web/useMessage'
import { QueryField } from '/@/components/Bootx/Query/Query'
import { useDict } from '/@/hooks/bootx/useDict'
// 使用hooks
const { handleTableChange, pageQueryResHandel, resetQueryParams, pagination, pages, model, loading } = useTablePage(queryPage)
const { notification, createMessage } = useMessage()
const { dictConvert } = useDict()
// 查询条件
const fields = [
{ field: 'title', type: 'string', name: '操作模块', placeholder: '请输入操作模块' },
{ field: 'username', type: 'string', name: '账号', placeholder: '请输入账号名称' },
] as QueryField[]
const xTable = $ref<VxeTableInstance>()
const xToolbar = $ref<VxeToolbarInstance>()
const operateLogEdit = $ref<any>()
onMounted(() => {
vxeBind()
queryPage()
})
function vxeBind() {
xTable.connect(xToolbar)
}
// 分页查询
function queryPage() {
loading.value = true
page({
...model.queryParam,
...pages,
}).then(({ data }) => {
pageQueryResHandel(data)
})
}
// 查看
function show(record) {
operateLogEdit.show(record.id)
}
</script>
<style lang="less" scoped></style>