提交
This commit is contained in:
1 parent
493f8d6756
commit
d84f4b944c
406 files changed
+58954
-10376
No files matched your search
@@ -126,7 +126,7 @@
|
||||
<el-dropdown-item command="edit">
|
||||
<el-icon><Edit /></el-icon>编辑
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="delete" divided>
|
||||
<el-dropdown-item command="delete" divided :disabled="!canDeleteByCreator(row)">
|
||||
<el-icon><Delete /></el-icon>删除
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
@@ -256,6 +256,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
|
||||
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
Plus,
|
||||
@@ -702,7 +703,12 @@ const dictStore = useDictStore()
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDelete(row: Api.Dept.DeptItem) {
|
||||
async function handleDelete(row: Api.Dept.DeptItem)
|
||||
if (!canDeleteByCreator(row)) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
{
|
||||
try {
|
||||
const childCount = row.children?.length || 0
|
||||
const confirmText = childCount
|
||||
|
||||
@@ -39,7 +39,8 @@
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
type="danger"
|
||||
:disabled="selectedRows.length === 0"
|
||||
:disabled="selectedRows.length === 0 || !allRowsDeletableByCreator(selectedRows)"
|
||||
:title="allRowsDeletableByCreator(selectedRows) ? '' : CREATOR_DELETE_TIP"
|
||||
@click="handleBatchDelete"
|
||||
>
|
||||
批量删除
|
||||
@@ -118,7 +119,7 @@
|
||||
<el-dropdown-item command="edit">
|
||||
<el-icon><Edit /></el-icon>编辑
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="delete" divided>
|
||||
<el-dropdown-item command="delete" divided :disabled="!canDeleteByCreator(row)">
|
||||
<el-icon><Delete /></el-icon>删除
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
@@ -346,7 +347,14 @@
|
||||
<el-button class="btn-op-item primary" @click="handleEditDictData(row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button class="btn-op-item" @click="handleDeleteDictData(row)"> 删除 </el-button>
|
||||
<el-button
|
||||
class="btn-op-item"
|
||||
:disabled="!canDeleteByCreator(row)"
|
||||
:title="canDeleteByCreator(row) ? '' : CREATOR_DELETE_TIP"
|
||||
@click="handleDeleteDictData(row)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -449,6 +457,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
Plus,
|
||||
@@ -635,7 +644,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDelete(row: Api.Dict.DictTypeItem) {
|
||||
async function handleDelete(row: Api.Dict.DictTypeItem)
|
||||
if (!canDeleteByCreator(row)) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
{
|
||||
await ElMessageBox.confirm(`确定删除字典类型「${row.dictName}」吗?`, '提示', {
|
||||
type: 'warning'
|
||||
})
|
||||
@@ -644,7 +658,16 @@
|
||||
}
|
||||
|
||||
async function handleBatchDelete() {
|
||||
const ids = selectedRows.value.map((r) => r.id)
|
||||
const deletable = filterDeletableByCreator(selectedRows.value)
|
||||
if (!deletable.length) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
if (deletable.length < selectedRows.value.length) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
const ids = deletable.map((r) => r.id)
|
||||
if (!ids.length) {
|
||||
ElMessage.warning('请选择要删除的字典类型')
|
||||
return
|
||||
@@ -767,6 +790,10 @@
|
||||
}
|
||||
|
||||
async function handleDeleteDictData(row: Api.Dict.DictDataItem) {
|
||||
if (!canDeleteByCreator(row)) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
await ElMessageBox.confirm(`确定删除字典数据「${row.dictLabel}」吗?`, '提示', {
|
||||
type: 'warning'
|
||||
})
|
||||
|
||||
@@ -123,7 +123,12 @@
|
||||
<el-button type="success" link size="small" @click="handleSubmit(row.id)"
|
||||
>提交审批</el-button
|
||||
>
|
||||
<el-button type="danger" link size="small" @click="handleDelete(row.id)"
|
||||
<el-button
|
||||
v-if="canDeleteByCreator(row)"
|
||||
type="danger"
|
||||
link
|
||||
size="small"
|
||||
@click="handleDelete(row)"
|
||||
>删除</el-button
|
||||
>
|
||||
</template>
|
||||
@@ -237,6 +242,7 @@
|
||||
<script setup lang="ts">
|
||||
import { Close, Check, RefreshLeft, Search } from '@element-plus/icons-vue'
|
||||
import { useDictStore } from '@/store/modules/dict'
|
||||
import { canDeleteByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
||||
import {
|
||||
fetchLeaveList,
|
||||
fetchCreateLeave,
|
||||
@@ -365,10 +371,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDelete(id: string) {
|
||||
async function handleDelete(row: { id: string }) {
|
||||
if (!canDeleteByCreator(row)) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
try {
|
||||
await ElMessageBox.confirm('确定删除此请假申请?', '提示', { type: 'warning' })
|
||||
await fetchDeleteLeave(id)
|
||||
await fetchDeleteLeave(row.id)
|
||||
loadData()
|
||||
} catch {
|
||||
// cancelled or error
|
||||
|
||||
@@ -161,7 +161,7 @@
|
||||
<el-dropdown-item command="edit">
|
||||
<el-icon><Edit /></el-icon>编辑
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="delete" divided>
|
||||
<el-dropdown-item command="delete" divided :disabled="!canDeleteByCreator(row)">
|
||||
<el-icon><Delete /></el-icon>删除
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
@@ -267,6 +267,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
|
||||
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
Plus,
|
||||
@@ -536,7 +537,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDelete(row: Api.Menu.MenuItem) {
|
||||
async function handleDelete(row: Api.Menu.MenuItem)
|
||||
if (!canDeleteByCreator(row)) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
{
|
||||
try {
|
||||
const childCount = row.children?.length || 0
|
||||
const confirmText = childCount
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
<!-- 操作日志 -->
|
||||
<template>
|
||||
<div class="page-container">
|
||||
<section class="panel">
|
||||
<div class="panel-top">
|
||||
<h2 class="title-bar-heading">操作日志</h2>
|
||||
</div>
|
||||
|
||||
<div class="filter-block">
|
||||
<el-form :model="searchForm" class="filter-form" @submit.prevent>
|
||||
<div class="filter-grid">
|
||||
<el-form-item label="操作模块">
|
||||
<el-input v-model="searchForm.title" placeholder="模块名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="操作类型">
|
||||
<el-select v-model="searchForm.businessType" placeholder="全部" clearable>
|
||||
<el-option
|
||||
v-for="opt in OPER_LOG_BUSINESS_TYPE_OPTIONS"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作人员">
|
||||
<el-input v-model="searchForm.operName" placeholder="姓名或账号" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="searchForm.status" placeholder="全部" clearable>
|
||||
<el-option label="成功" :value="0" />
|
||||
<el-option label="失败" :value="1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="filter-actions-row">
|
||||
<span class="filter-hint">按模块、类型、操作人筛选操作日志。</span>
|
||||
<div class="filter-actions-end">
|
||||
<el-button class="btn-ghost" :loading="loading" @click="handleReset">
|
||||
<el-icon><RefreshLeft /></el-icon>重置
|
||||
</el-button>
|
||||
<el-button class="btn-main" type="primary" :loading="loading" @click="handleSearch">
|
||||
<el-icon><Search /></el-icon>搜索
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="list-body list-wrap">
|
||||
<el-table class="list-table" :data="tableData" stripe v-loading="loading" row-key="id">
|
||||
<el-table-column
|
||||
type="index"
|
||||
label="序号"
|
||||
min-width="68"
|
||||
align="center"
|
||||
header-align="center"
|
||||
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
|
||||
/>
|
||||
<el-table-column prop="title" label="操作模块" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column label="操作类型" min-width="100" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getOperLogBusinessTypeTagType(row.businessType)" size="small">
|
||||
{{ getOperLogBusinessTypeLabel(row.businessType) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="operSummary"
|
||||
label="操作摘要"
|
||||
min-width="180"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column prop="operName" label="操作人员" min-width="120" align="center" />
|
||||
<el-table-column prop="operTime" label="操作时间" min-width="170" align="center" />
|
||||
<el-table-column label="状态" min-width="90" align="center" header-align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="row.status === 0 ? 'success' : 'danger'" size="small">
|
||||
{{ row.status === 0 ? '成功' : '失败' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="costTime" label="耗时(ms)" min-width="100" align="center" />
|
||||
<el-table-column
|
||||
label="操作"
|
||||
fixed="right"
|
||||
min-width="120"
|
||||
align="center"
|
||||
header-align="center"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<el-button type="primary" link size="small" @click="openDetail(row)">
|
||||
<el-icon><View /></el-icon>详情
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="pagination list-pager-bar">
|
||||
<el-pagination
|
||||
v-model:current-page="pagination.page"
|
||||
v-model:page-size="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
:page-sizes="[10, 20, 50]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@size-change="fetchList"
|
||||
@current-change="fetchList"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<el-dialog
|
||||
v-model="detailVisible"
|
||||
title="操作日志详情"
|
||||
width="720px"
|
||||
align-center
|
||||
class="dialog-form-layout operlog-detail-dialog"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<div v-if="detailRow" class="operlog-detail-body">
|
||||
<div class="detail-kv-grid">
|
||||
<div class="detail-kv-item"><span class="label">操作模块</span><span>{{ detailRow.title }}</span></div>
|
||||
<div class="detail-kv-item">
|
||||
<span class="label">操作类型</span>
|
||||
<el-tag :type="getOperLogBusinessTypeTagType(detailRow.businessType)" size="small">
|
||||
{{ getOperLogBusinessTypeLabel(detailRow.businessType) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="detail-kv-item"><span class="label">操作人员</span><span>{{ detailRow.operName || '—' }}</span></div>
|
||||
<div class="detail-kv-item"><span class="label">操作时间</span><span>{{ detailRow.operTime || '—' }}</span></div>
|
||||
<div class="detail-kv-item full"><span class="label">操作摘要</span><span>{{ detailRow.operSummary || '—' }}</span></div>
|
||||
<div class="detail-kv-item full"><span class="label">请求地址</span><span>{{ detailRow.operUrl || '—' }}</span></div>
|
||||
<div class="detail-kv-item"><span class="label">操作 IP</span><span>{{ detailRow.operIp || '—' }}</span></div>
|
||||
<div class="detail-kv-item"><span class="label">耗时</span><span>{{ detailRow.costTime ?? '—' }} ms</span></div>
|
||||
</div>
|
||||
<div class="detail-block">
|
||||
<div class="detail-block-title">请求参数</div>
|
||||
<pre class="detail-pre">{{ detailRow.operParam || '无' }}</pre>
|
||||
</div>
|
||||
<div class="detail-block">
|
||||
<div class="detail-block-title">返回参数</div>
|
||||
<pre class="detail-pre">{{ detailRow.jsonResult || '无' }}</pre>
|
||||
</div>
|
||||
<div v-if="detailRow.status === 1" class="detail-block">
|
||||
<div class="detail-block-title">错误信息</div>
|
||||
<pre class="detail-pre error">{{ detailRow.errorMsg || '—' }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="detailVisible = false">
|
||||
<el-icon><Close /></el-icon>关闭
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Close, RefreshLeft, Search, View } from '@element-plus/icons-vue'
|
||||
import { list as listOperLog, detail as getOperLogDetail } from '@/api/monitor/operlog'
|
||||
import type { OperLogVO, OperLogQuery } from '@/api/monitor/operlog/types'
|
||||
import {
|
||||
OPER_LOG_BUSINESS_TYPE_OPTIONS,
|
||||
getOperLogBusinessTypeLabel,
|
||||
getOperLogBusinessTypeTagType
|
||||
} from '@/api/monitor/operlog/types'
|
||||
|
||||
const loading = ref(false)
|
||||
const tableData = ref<OperLogVO[]>([])
|
||||
const pagination = reactive({ page: 1, pageSize: 10, total: 0 })
|
||||
const searchForm = reactive({
|
||||
title: '',
|
||||
businessType: undefined as number | undefined,
|
||||
operName: '',
|
||||
status: undefined as number | undefined
|
||||
})
|
||||
|
||||
const detailVisible = ref(false)
|
||||
const detailRow = ref<OperLogVO | null>(null)
|
||||
|
||||
function buildQuery(): OperLogQuery {
|
||||
return {
|
||||
pageNum: pagination.page,
|
||||
pageSize: pagination.pageSize,
|
||||
title: searchForm.title || undefined,
|
||||
businessType: searchForm.businessType,
|
||||
operName: searchForm.operName || undefined,
|
||||
status: searchForm.status
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchList() {
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await listOperLog(buildQuery())
|
||||
const payload = res as { rows?: OperLogVO[]; list?: OperLogVO[]; total?: number }
|
||||
tableData.value = payload?.rows || payload?.list || []
|
||||
pagination.total = payload?.total ?? tableData.value.length
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
tableData.value = []
|
||||
pagination.total = 0
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function handleSearch() {
|
||||
pagination.page = 1
|
||||
fetchList()
|
||||
}
|
||||
|
||||
function handleReset() {
|
||||
searchForm.title = ''
|
||||
searchForm.businessType = undefined
|
||||
searchForm.operName = ''
|
||||
searchForm.status = undefined
|
||||
handleSearch()
|
||||
}
|
||||
|
||||
async function openDetail(row: OperLogVO) {
|
||||
try {
|
||||
const res = await getOperLogDetail({ id: String(row.id) })
|
||||
detailRow.value = (res as OperLogVO) || row
|
||||
} catch {
|
||||
detailRow.value = row
|
||||
}
|
||||
detailVisible.value = true
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.detail-kv-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px 16px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.detail-kv-item {
|
||||
font-size: 14px;
|
||||
color: var(--text, #1e293b);
|
||||
|
||||
.label {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted, #64748b);
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
&.full {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-block {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.detail-block-title {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.detail-pre {
|
||||
background: #f8fafc;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
max-height: 240px;
|
||||
overflow: auto;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
|
||||
&.error {
|
||||
color: #dc2626;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -40,7 +40,8 @@
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
type="danger"
|
||||
:disabled="selectedRows.length === 0"
|
||||
:disabled="selectedRows.length === 0 || !allRowsDeletableByCreator(selectedRows)"
|
||||
:title="allRowsDeletableByCreator(selectedRows) ? '' : CREATOR_DELETE_TIP"
|
||||
@click="handleBatchDelete"
|
||||
>
|
||||
批量删除
|
||||
@@ -126,7 +127,7 @@
|
||||
<el-dropdown-item command="edit">
|
||||
<el-icon><Edit /></el-icon>编辑
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="delete" divided>
|
||||
<el-dropdown-item command="delete" divided :disabled="!canDeleteByCreator(row)">
|
||||
<el-icon><Delete /></el-icon>删除
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
@@ -317,6 +318,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
|
||||
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
Plus,
|
||||
@@ -708,7 +710,12 @@ const dictStore = useDictStore()
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDelete(row: Api.Post.PostItem) {
|
||||
async function handleDelete(row: Api.Post.PostItem)
|
||||
if (!canDeleteByCreator(row)) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
{
|
||||
await ElMessageBox.confirm(`确定删除职位「${row.postName}」吗?`, '提示', { type: 'warning' })
|
||||
await fetchDeletePost(row.id)
|
||||
ElMessage.success('删除成功')
|
||||
@@ -716,7 +723,16 @@ const dictStore = useDictStore()
|
||||
}
|
||||
|
||||
async function handleBatchDelete() {
|
||||
const ids = selectedRows.value.map((r) => r.id)
|
||||
const deletable = filterDeletableByCreator(selectedRows.value)
|
||||
if (!deletable.length) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
if (deletable.length < selectedRows.value.length) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
const ids = deletable.map((r) => r.id)
|
||||
if (!ids.length) return
|
||||
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个职位吗?`, '提示', {
|
||||
type: 'warning'
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
type="danger"
|
||||
:disabled="selectedRows.length === 0"
|
||||
:disabled="selectedRows.length === 0 || !allRowsDeletableByCreator(selectedRows)"
|
||||
:title="allRowsDeletableByCreator(selectedRows) ? '' : CREATOR_DELETE_TIP"
|
||||
@click="handleBatchDelete"
|
||||
>
|
||||
批量删除
|
||||
@@ -132,7 +133,7 @@
|
||||
<el-dropdown-item command="edit">
|
||||
<el-icon><Edit /></el-icon>编辑
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="delete" divided>
|
||||
<el-dropdown-item command="delete" divided :disabled="!canDeleteByCreator(row)">
|
||||
<el-icon><Delete /></el-icon>删除
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
@@ -422,6 +423,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted, nextTick, watch } from 'vue'
|
||||
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
Plus,
|
||||
@@ -753,14 +755,28 @@ const dictStore = useDictStore()
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDelete(row: Api.Role.RoleItem) {
|
||||
async function handleDelete(row: Api.Role.RoleItem)
|
||||
if (!canDeleteByCreator(row)) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
{
|
||||
await ElMessageBox.confirm(`确定删除角色「${row.roleName}」吗?`, '提示', { type: 'warning' })
|
||||
await fetchDeleteRole(row.id)
|
||||
await loadData()
|
||||
}
|
||||
|
||||
async function handleBatchDelete() {
|
||||
const ids = selectedRows.value.map((r) => r.id)
|
||||
const deletable = filterDeletableByCreator(selectedRows.value)
|
||||
if (!deletable.length) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
if (deletable.length < selectedRows.value.length) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
const ids = deletable.map((r) => r.id)
|
||||
if (!ids.length) {
|
||||
ElMessage.warning('请至少选择一项')
|
||||
return
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
type="danger"
|
||||
:disabled="selectedRows.length === 0"
|
||||
:disabled="selectedRows.length === 0 || !allRowsDeletableByCreator(selectedRows)"
|
||||
:title="allRowsDeletableByCreator(selectedRows) ? '' : CREATOR_DELETE_TIP"
|
||||
@click="handleBatchDelete"
|
||||
>
|
||||
批量删除
|
||||
@@ -155,7 +156,7 @@
|
||||
<el-dropdown-item command="edit">
|
||||
<el-icon><Edit /></el-icon>编辑
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="delete" divided>
|
||||
<el-dropdown-item command="delete" divided :disabled="!canDeleteByCreator(row)">
|
||||
<el-icon><Delete /></el-icon>删除
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
@@ -299,6 +300,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
|
||||
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Plus, Close, Check, View, Edit, Delete, More, Location, RefreshLeft, Search } from '@element-plus/icons-vue'
|
||||
import { withFullscreenLoading, fullscreenLoadingText } from '@/utils/fullscreen-loading'
|
||||
@@ -648,7 +650,12 @@ const dictStore = useDictStore()
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDelete(row: Api.Site.SiteItem) {
|
||||
async function handleDelete(row: Api.Site.SiteItem)
|
||||
if (!canDeleteByCreator(row)) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
{
|
||||
await ElMessageBox.confirm(`确定删除站点「${row.siteName}」吗?`, '提示', { type: 'warning' })
|
||||
await fetchDeleteSite(row.id)
|
||||
ElMessage.success('删除成功')
|
||||
@@ -656,7 +663,16 @@ const dictStore = useDictStore()
|
||||
}
|
||||
|
||||
async function handleBatchDelete() {
|
||||
const ids = selectedRows.value.map((r) => r.id)
|
||||
const deletable = filterDeletableByCreator(selectedRows.value)
|
||||
if (!deletable.length) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
if (deletable.length < selectedRows.value.length) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
const ids = deletable.map((r) => r.id)
|
||||
if (!ids.length) return
|
||||
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个站点吗?`, '提示', {
|
||||
type: 'warning'
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
type="danger"
|
||||
:disabled="deletableSelection.length === 0"
|
||||
:disabled="deletableSelection.length === 0 || !allRowsDeletableByCreator(deletableSelection)"
|
||||
:title="allRowsDeletableByCreator(deletableSelection) ? '' : CREATOR_DELETE_TIP"
|
||||
@click="handleBatchDelete"
|
||||
>
|
||||
批量删除
|
||||
@@ -141,7 +142,7 @@
|
||||
<el-dropdown-item command="edit">
|
||||
<el-icon><Edit /></el-icon>编辑
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="delete" divided :disabled="isDefaultTenantRow(row)">
|
||||
<el-dropdown-item command="delete" divided :disabled="isDefaultTenantRow(row) || !canDeleteByCreator(row)">
|
||||
<el-icon><Delete /></el-icon>删除
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
@@ -229,6 +230,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, computed } from 'vue'
|
||||
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
Plus,
|
||||
@@ -424,6 +426,10 @@
|
||||
}
|
||||
|
||||
async function handleDelete(row: Api.Tenant.TenantItem) {
|
||||
if (!canDeleteByCreator(row)) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
if (isDefaultTenantRow(row)) {
|
||||
ElMessage.warning('默认租户不可删除')
|
||||
return
|
||||
@@ -434,7 +440,16 @@
|
||||
}
|
||||
|
||||
async function handleBatchDelete() {
|
||||
const ids = deletableSelection.value.map((r) => r.id)
|
||||
const rows = filterDeletableByCreator(deletableSelection.value)
|
||||
if (!rows.length) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
if (rows.length < deletableSelection.value.length) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
const ids = rows.map((r) => r.id)
|
||||
if (!ids.length) {
|
||||
ElMessage.warning('所选中含默认租户或无可删项,请重新选择')
|
||||
return
|
||||
|
||||
@@ -93,7 +93,8 @@
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
type="danger"
|
||||
:disabled="selectedRows.length === 0"
|
||||
:disabled="selectedRows.length === 0 || !allRowsDeletableByCreator(selectedRows)"
|
||||
:title="allRowsDeletableByCreator(selectedRows) ? '' : CREATOR_DELETE_TIP"
|
||||
@click="handleBatchDelete"
|
||||
>
|
||||
<el-icon><Delete /></el-icon>
|
||||
@@ -294,6 +295,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, onMounted, watch } from 'vue'
|
||||
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
Plus,
|
||||
@@ -569,7 +571,16 @@ const dictStore = useDictStore()
|
||||
}
|
||||
|
||||
async function handleBatchDelete() {
|
||||
const rows = selectedRows.value
|
||||
const deletable = filterDeletableByCreator(selectedRows.value)
|
||||
if (!deletable.length) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
if (deletable.length < selectedRows.value.length) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
const rows = deletable
|
||||
if (!rows.length) {
|
||||
ElMessage.warning('请至少选择一项')
|
||||
return
|
||||
|
||||
@@ -45,7 +45,8 @@
|
||||
<el-button
|
||||
class="btn-ghost"
|
||||
type="danger"
|
||||
:disabled="selectedRows.length === 0"
|
||||
:disabled="selectedRows.length === 0 || !allRowsDeletableByCreator(selectedRows)"
|
||||
:title="allRowsDeletableByCreator(selectedRows) ? '' : CREATOR_DELETE_TIP"
|
||||
@click="handleBatchDelete"
|
||||
>
|
||||
<el-icon><Delete /></el-icon>
|
||||
@@ -129,7 +130,7 @@
|
||||
<el-dropdown-item command="edit">
|
||||
<el-icon><Edit /></el-icon>编辑
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item command="delete" divided>
|
||||
<el-dropdown-item command="delete" divided :disabled="!canDeleteByCreator(row)">
|
||||
<el-icon><Delete /></el-icon>删除
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
@@ -208,6 +209,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
import { canDeleteByCreator, filterDeletableByCreator, allRowsDeletableByCreator, CREATOR_DELETE_TIP } from '@/utils/creator-delete'
|
||||
Plus,
|
||||
Close,
|
||||
Check,
|
||||
@@ -358,14 +360,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDelete(row: Api.Workflow.ProcessDefItem) {
|
||||
async function handleDelete(row: Api.Workflow.ProcessDefItem)
|
||||
if (!canDeleteByCreator(row)) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
{
|
||||
await ElMessageBox.confirm('确定要删除该流程吗?', '提示', { type: 'warning' })
|
||||
await fetchDeleteProcessDef(row.id)
|
||||
await loadData()
|
||||
}
|
||||
|
||||
async function handleBatchDelete() {
|
||||
const ids = selectedRows.value.map((r) => r.id)
|
||||
const deletable = filterDeletableByCreator(selectedRows.value)
|
||||
if (!deletable.length) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
if (deletable.length < selectedRows.value.length) {
|
||||
ElMessage.warning(CREATOR_DELETE_TIP)
|
||||
return
|
||||
}
|
||||
const ids = deletable.map((r) => r.id)
|
||||
if (!ids.length) return
|
||||
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个流程吗?`, '提示', {
|
||||
type: 'warning'
|
||||
|
||||
Reference in new issue
Block a user