mirror of
https://gitee.com/wonderful-code/buildadmin
synced 2024-11-21 22:55:36 +00:00
feat:数据回收规则管理
This commit is contained in:
parent
a6dc2a031e
commit
d78cebf5c3
@ -1 +1,36 @@
|
||||
<?php
|
||||
if (!function_exists('get_controller_list')) {
|
||||
function get_controller_list()
|
||||
{
|
||||
$controllerDir = app_path() . 'controller' . DIRECTORY_SEPARATOR;
|
||||
|
||||
$files = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($controllerDir), \RecursiveIteratorIterator::LEAVES_ONLY
|
||||
);
|
||||
|
||||
$controllerList = [];
|
||||
foreach ($files as $file) {
|
||||
if (!$file->isDir() && $file->getExtension() == 'php') {
|
||||
$filePath = $file->getRealPath();
|
||||
$name = str_replace($controllerDir, '', $filePath);
|
||||
$name = str_replace(DIRECTORY_SEPARATOR, "/", $name);
|
||||
$controllerList[$name] = $name;
|
||||
}
|
||||
}
|
||||
return $controllerList;
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('get_table_list')) {
|
||||
function get_table_list()
|
||||
{
|
||||
$tableList = [];
|
||||
$tables = \think\facade\Db::query("SHOW TABLES");
|
||||
|
||||
foreach ($tables as $table) {
|
||||
$tableList[reset($table)] = reset($table);
|
||||
}
|
||||
|
||||
return $tableList;
|
||||
}
|
||||
}
|
89
app/admin/controller/security/DataRecycle.php
Normal file
89
app/admin/controller/security/DataRecycle.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\controller\security;
|
||||
|
||||
use app\common\controller\Backend;
|
||||
use app\admin\model\DataRecycle as DataRecycleModel;
|
||||
use think\facade\Db;
|
||||
|
||||
class DataRecycle extends Backend
|
||||
{
|
||||
protected $model = null;
|
||||
|
||||
// 排除字段
|
||||
protected $preExcludeFields = ['updatetime', 'createtime'];
|
||||
|
||||
protected $quickSearchField = 'name';
|
||||
|
||||
public function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
$this->model = new DataRecycleModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
parent::add();
|
||||
}
|
||||
|
||||
// 放在add方法内,就不需要额外添加权限节点了
|
||||
$this->success('', [
|
||||
'tables' => $this->getTableList(),
|
||||
'controllers' => $this->getControllerList(),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getControllerList()
|
||||
{
|
||||
$outExcludeController = [
|
||||
'Addon.php',
|
||||
'Ajax.php',
|
||||
'Dashboard.php',
|
||||
'Index.php',
|
||||
'routine/AdminInfo.php',
|
||||
'user/MoneyLog.php',
|
||||
'user/ScoreLog.php',
|
||||
];
|
||||
$outControllers = [];
|
||||
$controllers = get_controller_list();
|
||||
foreach ($controllers as $key => $controller) {
|
||||
if (!in_array($controller, $outExcludeController)) {
|
||||
$outControllers[$key] = $controller;
|
||||
}
|
||||
}
|
||||
return $outControllers;
|
||||
}
|
||||
|
||||
protected function getTableList()
|
||||
{
|
||||
$tablePrefix = config('database.connections.mysql.prefix');
|
||||
$outExcludeTable = [
|
||||
// 功能表
|
||||
$tablePrefix . 'token',
|
||||
$tablePrefix . 'captcha',
|
||||
$tablePrefix . 'admin_group_access',
|
||||
// 无删除功能
|
||||
$tablePrefix . 'user_money_log',
|
||||
$tablePrefix . 'user_score_log',
|
||||
];
|
||||
|
||||
$outTables = [];
|
||||
$tables = get_table_list();
|
||||
foreach ($tables as $key => $table) {
|
||||
if (!in_array($table, $outExcludeTable)) {
|
||||
$outTables[$key] = $table;
|
||||
}
|
||||
}
|
||||
return $outTables;
|
||||
}
|
||||
|
||||
public function getPk($table = null)
|
||||
{
|
||||
$tablePk = Db::table($table)->getPk();
|
||||
$this->success('ok', ['pk' => $tablePk]);
|
||||
}
|
||||
}
|
14
app/admin/model/DataRecycle.php
Normal file
14
app/admin/model/DataRecycle.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class DataRecycle extends Model
|
||||
{
|
||||
protected $name = 'security_data_recycle';
|
||||
|
||||
protected $autoWriteTimestamp = 'int';
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = 'updatetime';
|
||||
}
|
14
app/admin/model/DataRecycleLog.php
Normal file
14
app/admin/model/DataRecycleLog.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace app\admin\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class DataRecycleLog extends Model
|
||||
{
|
||||
protected $name = 'security_data_recycle_log';
|
||||
|
||||
protected $autoWriteTimestamp = 'int';
|
||||
protected $createTime = 'createtime';
|
||||
protected $updateTime = false;
|
||||
}
|
@ -36,6 +36,11 @@ class UserMoneyLog extends model
|
||||
$user->save();
|
||||
}
|
||||
|
||||
public static function onBeforeDelete()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
|
@ -36,6 +36,11 @@ class UserScoreLog extends model
|
||||
$user->save();
|
||||
}
|
||||
|
||||
public static function onBeforeDelete()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
|
19
web/src/api/backend/security/dataRecycle.ts
Normal file
19
web/src/api/backend/security/dataRecycle.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import createAxios from '/@/utils/axios'
|
||||
import { securityDataRecycle } from '/@/api/controllerUrls'
|
||||
|
||||
export function add() {
|
||||
return createAxios({
|
||||
url: securityDataRecycle + 'add',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
export function getPk(table: string) {
|
||||
return createAxios({
|
||||
url: securityDataRecycle + 'getPk',
|
||||
method: 'get',
|
||||
params: {
|
||||
table: table,
|
||||
},
|
||||
})
|
||||
}
|
@ -12,3 +12,7 @@ export const userGroup = '/index.php/admin/user.group/'
|
||||
export const userRule = '/index.php/admin/user.rule/'
|
||||
export const userScoreLog = '/index.php/admin/user.scoreLog/'
|
||||
export const userMoneyLog = '/index.php/admin/user.moneyLog/'
|
||||
export const securityDataRecycle = '/index.php/admin/security.DataRecycle/'
|
||||
export const securityDataRecycleLog = '/index.php/admin/security.DataRecycleLog/'
|
||||
export const securitySensitiveData = '/index.php/admin/security.SensitiveData/'
|
||||
export const securitySensitiveDataLog = '/index.php/admin/security.SensitiveDataLog/'
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { createVNode, resolveComponent, defineComponent, PropType, VNode } from 'vue'
|
||||
import { inputTypes, modelValuePropsTypes, modelValueTypes } from '/@/components/baInput'
|
||||
import { inputTypes, modelValueTypes } from '/@/components/baInput'
|
||||
import Array from '/@/components/baInput/array.vue'
|
||||
|
||||
export default defineComponent({
|
||||
@ -16,7 +16,6 @@ export default defineComponent({
|
||||
},
|
||||
// 双向绑定值
|
||||
modelValue: {
|
||||
type: modelValuePropsTypes,
|
||||
required: true,
|
||||
},
|
||||
// 输入框的附加属性
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { createVNode, defineComponent, resolveComponent, PropType } from 'vue'
|
||||
import { inputTypes, modelValuePropsTypes, modelValueTypes } from '/@/components/baInput'
|
||||
import { inputTypes, modelValueTypes } from '/@/components/baInput'
|
||||
import BaInput from '/@/components/baInput/index.vue'
|
||||
|
||||
export default defineComponent({
|
||||
@ -20,7 +20,6 @@ export default defineComponent({
|
||||
},
|
||||
// 双向绑定值
|
||||
modelValue: {
|
||||
type: modelValuePropsTypes,
|
||||
required: true,
|
||||
},
|
||||
// 输入框的附加属性
|
||||
@ -118,9 +117,7 @@ export default defineComponent({
|
||||
display: flex;
|
||||
}
|
||||
.ba-form-item-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
.ba-form-item-label-tip {
|
||||
padding-left: 6px;
|
||||
font-size: 12px;
|
||||
|
@ -59,6 +59,8 @@ export default class baTable {
|
||||
submitLoading: false,
|
||||
// 默认表单数据(添加)
|
||||
defaultItems: {},
|
||||
// 表单字段加载状态
|
||||
loading: false,
|
||||
})
|
||||
/* 表单状态-e */
|
||||
|
||||
@ -126,12 +128,14 @@ export default class baTable {
|
||||
// 编辑
|
||||
requestEdit = (id: string) => {
|
||||
this.runBefore('requestEdit', { id })
|
||||
this.form.loading = true
|
||||
this.form.items = {}
|
||||
return this.api
|
||||
.edit({
|
||||
id: id,
|
||||
})
|
||||
.then((res) => {
|
||||
this.form.loading = false
|
||||
this.form.items = res.data.row
|
||||
this.runAfter('requestEdit', { res })
|
||||
})
|
||||
|
@ -12,6 +12,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-loading="baTable.form.loading"
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
|
@ -13,6 +13,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-loading="baTable.form.loading"
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
|
@ -13,6 +13,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-loading="baTable.form.loading"
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
|
@ -12,6 +12,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-loading="baTable.form.loading"
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
|
120
web/src/views/backend/security/dataRecycle/form.vue
Normal file
120
web/src/views/backend/security/dataRecycle/form.vue
Normal file
@ -0,0 +1,120 @@
|
||||
<template>
|
||||
<!-- 对话框表单 -->
|
||||
<el-dialog
|
||||
custom-class="ba-operate-dialog"
|
||||
:close-on-click-modal="false"
|
||||
:model-value="baTable.form.operate ? true : false"
|
||||
@close="baTable.toggleForm"
|
||||
>
|
||||
<template #title>
|
||||
<div class="title" v-drag="['.ba-operate-dialog', '.el-dialog__header']" v-zoom="'.ba-operate-dialog'">
|
||||
{{ baTable.form.operate ? t(baTable.form.operate) : '' }}
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-loading="baTable.form.loading"
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
>
|
||||
<el-form
|
||||
v-if="!baTable.form.loading"
|
||||
ref="formRef"
|
||||
@keyup.enter="baTable.onSubmit(formRef)"
|
||||
:model="baTable.form.items"
|
||||
label-position="right"
|
||||
:label-width="baTable.form.labelWidth + 'px'"
|
||||
:rules="rules"
|
||||
>
|
||||
<FormItem
|
||||
label="规则名称"
|
||||
type="string"
|
||||
v-model="baTable.form.items!.name"
|
||||
:attr="{ prop: 'name' }"
|
||||
:input-attr="{ placeholder: '规则名称有助于后续识别被删数据' }"
|
||||
/>
|
||||
<FormItem
|
||||
label="控制器"
|
||||
type="select"
|
||||
v-model="baTable.form.items!.controller"
|
||||
:attr="{ prop: 'controller' }"
|
||||
:data="{ content: formData.controllerList }"
|
||||
:input-attr="{ placeholder: '数据回收机制将监控此控制器下的删除操作' }"
|
||||
/>
|
||||
<FormItem
|
||||
label="对应数据表"
|
||||
type="select"
|
||||
v-model="baTable.form.items!.data_table"
|
||||
:attr="{ prop: 'data_table' }"
|
||||
:data="{ content: formData.tableList }"
|
||||
:input-attr="{ onChange: onTableChange }"
|
||||
/>
|
||||
<FormItem label="数据表主键" type="string" v-model="baTable.form.items!.primary_key" :attr="{ prop: 'primary_key' }" />
|
||||
<FormItem
|
||||
label="状态"
|
||||
type="radio"
|
||||
v-model="baTable.form.items!.status"
|
||||
:attr="{ prop: 'status' }"
|
||||
:data="{ content: { '0': '禁用', '1': '启用' } }"
|
||||
/>
|
||||
</el-form>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div :style="'width: calc(100% - ' + baTable.form.labelWidth! / 1.8 + 'px)'">
|
||||
<el-button @click="baTable.toggleForm('')">取消</el-button>
|
||||
<el-button v-blur :loading="baTable.form.submitLoading" @click="baTable.onSubmit(formRef)" type="primary">
|
||||
{{ baTable.form.operateIds && baTable.form.operateIds.length > 1 ? '保存并编辑下一项' : '保存' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref, inject } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type baTableClass from '/@/utils/baTable'
|
||||
import FormItem from '/@/components/formItem/index.vue'
|
||||
import { FormItemRule } from 'element-plus/es/components/form/src/form.type'
|
||||
import type { ElForm } from 'element-plus'
|
||||
import { buildValidatorData } from '/@/utils/validate'
|
||||
import { getPk } from '/@/api/backend/security/dataRecycle'
|
||||
|
||||
interface Props {
|
||||
formData: {
|
||||
tableList?: anyObj
|
||||
controllerList?: anyObj
|
||||
}
|
||||
}
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
formData: () => {
|
||||
return {}
|
||||
},
|
||||
})
|
||||
|
||||
const formRef = ref<InstanceType<typeof ElForm>>()
|
||||
const baTable = inject('baTable') as baTableClass
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const rules: Partial<Record<string, FormItemRule[]>> = reactive({
|
||||
name: [buildValidatorData('required', '规则名称')],
|
||||
controller: [buildValidatorData('required', '', 'change', '请选择控制器')],
|
||||
data_table: [buildValidatorData('required', '', 'change', '请选择数据表')],
|
||||
primary_key: [buildValidatorData('required', '数据表主键', 'change')],
|
||||
status: [buildValidatorData('required', '数据表主键')],
|
||||
})
|
||||
|
||||
const onTableChange = (val: string) => {
|
||||
getPk(val).then((res) => {
|
||||
baTable.form.items!.primary_key = res.data.pk
|
||||
baTable.form.defaultItems!.primary_key = res.data.pk
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.ba-el-radio {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
106
web/src/views/backend/security/dataRecycle/index.vue
Normal file
106
web/src/views/backend/security/dataRecycle/index.vue
Normal file
@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<div class="default-main ba-table-box">
|
||||
<el-alert class="ba-table-alert" v-if="baTable.table.remark" :title="baTable.table.remark" type="info" show-icon />
|
||||
|
||||
<!-- 表格顶部菜单 -->
|
||||
<TableHeader
|
||||
:buttons="['refresh', 'add', 'edit', 'delete', 'comSearch']"
|
||||
:quick-search-placeholder="'通过规则名模糊搜索'"
|
||||
@action="baTable.onTableHeaderAction"
|
||||
/>
|
||||
|
||||
<!-- 表格 -->
|
||||
<!-- 要使用`el-table`组件原有的属性,直接加在Table标签上即可 -->
|
||||
<Table ref="tableRef" @action="baTable.onTableAction" />
|
||||
|
||||
<!-- 表单 -->
|
||||
<Form ref="formRef" :form-data="addFormData" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, reactive, provide } from 'vue'
|
||||
import baTableClass from '/@/utils/baTable'
|
||||
import { securityDataRecycle } from '/@/api/controllerUrls'
|
||||
import { add } from '/@/api/backend/security/dataRecycle'
|
||||
import Form from './form.vue'
|
||||
import Table from '/@/components/table/index.vue'
|
||||
import TableHeader from '/@/components/table/header/index.vue'
|
||||
import { defaultOptButtons } from '/@/components/table'
|
||||
import { baTableApi } from '/@/api/common'
|
||||
|
||||
const tableRef = ref()
|
||||
const formRef = ref()
|
||||
const baTable = new baTableClass(
|
||||
new baTableApi(securityDataRecycle),
|
||||
{
|
||||
column: [
|
||||
{ type: 'selection', align: 'center', operator: false },
|
||||
{ label: 'ID', prop: 'id', align: 'center', operator: 'LIKE', operatorPlaceholder: '模糊查询', width: 70 },
|
||||
{ label: '规则名称', prop: 'name', align: 'center', operator: 'LIKE', operatorPlaceholder: '模糊查询' },
|
||||
{ label: '控制器', prop: 'controller', align: 'center', operator: 'LIKE', operatorPlaceholder: '模糊查询' },
|
||||
{ label: '数据表', prop: 'data_table', align: 'center', operator: 'LIKE', operatorPlaceholder: '模糊查询' },
|
||||
{ label: '数据表主键', prop: 'primary_key', align: 'center', operator: 'LIKE', operatorPlaceholder: '模糊查询' },
|
||||
{
|
||||
label: '状态',
|
||||
prop: 'status',
|
||||
align: 'center',
|
||||
render: 'tag',
|
||||
custom: { '0': 'danger', '1': 'success' },
|
||||
replaceValue: { '0': '禁用', '1': '删除监控中' },
|
||||
},
|
||||
{ label: '更新时间', prop: 'updatetime', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 },
|
||||
{ label: '创建时间', prop: 'createtime', align: 'center', render: 'datetime', sortable: 'custom', operator: 'RANGE', width: 160 },
|
||||
{
|
||||
label: '操作',
|
||||
align: 'center',
|
||||
width: '130',
|
||||
render: 'buttons',
|
||||
buttons: defaultOptButtons(['edit', 'delete']),
|
||||
operator: false,
|
||||
},
|
||||
],
|
||||
dblClickNotEditColumn: [undefined, 'status'],
|
||||
},
|
||||
{
|
||||
defaultItems: {
|
||||
status: '1',
|
||||
},
|
||||
},
|
||||
{
|
||||
// 添加前获取控制器和数据表
|
||||
toggleForm: ({ operate }: { operate: string }) => {
|
||||
if (operate == 'add' || operate == 'edit') {
|
||||
baTable.form.loading = true
|
||||
add().then((res) => {
|
||||
addFormData.tableList = res.data.tables
|
||||
addFormData.controllerList = res.data.controllers
|
||||
baTable.form.loading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
const addFormData = reactive({
|
||||
tableList: {},
|
||||
controllerList: {},
|
||||
})
|
||||
|
||||
provide('baTable', baTable)
|
||||
|
||||
onMounted(() => {
|
||||
baTable.table.ref = tableRef.value
|
||||
baTable.mount()
|
||||
baTable.getIndex()
|
||||
})
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
export default defineComponent({
|
||||
name: 'security/dataRecycle',
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
@ -13,6 +13,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-loading="baTable.form.loading"
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
|
@ -13,6 +13,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-loading="baTable.form.loading"
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
|
@ -13,6 +13,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-loading="baTable.form.loading"
|
||||
class="ba-operate-form"
|
||||
:class="'ba-' + baTable.form.operate + '-form'"
|
||||
:style="'width: calc(100% - ' + baTable.form.labelWidth! / 2 + 'px)'"
|
||||
|
1
web/types/table.d.ts
vendored
1
web/types/table.d.ts
vendored
@ -28,6 +28,7 @@ declare global {
|
||||
items?: anyObj
|
||||
submitLoading?: boolean
|
||||
defaultItems?: anyObj
|
||||
loading?: boolean
|
||||
}
|
||||
|
||||
/* BaTable前置处理函数(前置埋点) */
|
||||
|
Loading…
Reference in New Issue
Block a user