This commit is contained in:
zlwu committed 2026-05-26 19:04:27 +08:00
1 parent 4a00f21bfb
commit edf88dc016
1503 files changed
+329728 -41987

No files matched your search

File diff suppressed because it is too large. Load diff
+20 -4
View File
@@ -22,8 +22,12 @@
<div class="filter-actions-row">
<span class="filter-hint">按组织名称模糊查询。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
@@ -243,7 +247,15 @@
<script setup lang="ts">
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Close, Check, View, OfficeBuilding, RefreshLeft, Search } from '@element-plus/icons-vue'
import {
Plus,
Close,
Check,
View,
OfficeBuilding,
RefreshLeft,
Search
} from '@element-plus/icons-vue'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import {
fetchDeptTree,
@@ -472,7 +484,11 @@
{ label: '组织名称', value: viewRow.value?.deptName },
{ label: '上级组织', value: getParentDeptDisplay(viewRow.value?.parentId) },
{ label: '组织类别', value: getDeptCategoryLabel(viewRow.value?.deptCategoryCode || '') },
{ label: '状态', value: viewRow.value?.status === '1' ? '正常' : '停用', tagType: viewRow.value?.status === '1' ? 'success' : 'info' },
{
label: '状态',
value: viewRow.value?.status === '1' ? '正常' : '停用',
tagType: viewRow.value?.status === '1' ? 'success' : 'info'
},
{ label: '负责人', value: viewRow.value?.leader },
{ label: '联系电话', value: viewRow.value?.leaderPhone },
{ label: '备注', value: viewRow.value?.remark, span: true }
+31 -61
View File
@@ -15,18 +15,18 @@
<el-form :model="searchForm" class="filter-form" @submit.prevent>
<div class="filter-grid">
<el-form-item label="关键词">
<el-input
v-model="searchForm.keyword"
placeholder="字典名称/类型编码"
clearable
/>
<el-input v-model="searchForm.keyword" placeholder="字典名称/类型编码" clearable />
</el-form-item>
</div>
<div class="filter-actions-row">
<span class="filter-hint">按字典名称、类型编码模糊查询。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
@@ -62,12 +62,7 @@
@selection-change="handleSelectionChange"
@row-dblclick="handleView"
>
<el-table-column
type="selection"
min-width="55"
align="center"
header-align="center"
/>
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
<el-table-column
type="index"
label="序号"
@@ -115,18 +110,11 @@
<el-button class="btn-op-item" @click="handleView(row)">
<el-icon><View /></el-icon>查看
</el-button>
<el-button
class="btn-op-item primary"
@click="handleDictData(row)"
>
<el-button class="btn-op-item primary" @click="handleDictData(row)">
字典数据配置
</el-button>
<el-button class="btn-op-item primary" @click="handleEdit(row)">
编辑
</el-button>
<el-button class="btn-op-item" @click="handleDelete(row)">
删除
</el-button>
<el-button class="btn-op-item primary" @click="handleEdit(row)"> 编辑 </el-button>
<el-button class="btn-op-item" @click="handleDelete(row)"> 删除 </el-button>
</template>
</el-table-column>
</el-table>
@@ -137,9 +125,7 @@
:total="pagination.total"
:page-sizes="[10, 20, 50]"
layout="total, sizes, prev, pager, next"
@size-change="
(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())
"
@size-change="(val) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
@current-change="(val) => ((pagination.page = val), loadData())"
/>
</div>
@@ -168,19 +154,10 @@
<el-input v-model="formData.dictName" placeholder="字典名称" />
</el-form-item>
<el-form-item label="字典类型编码" prop="dictType">
<el-input
v-model="formData.dictType"
placeholder="字典类型编码"
:disabled="isEdit"
/>
<el-input v-model="formData.dictType" placeholder="字典类型编码" :disabled="isEdit" />
</el-form-item>
<el-form-item label="备注" style="grid-column: 1 / -1">
<el-input
v-model="formData.remark"
type="textarea"
:rows="2"
placeholder="可选"
/>
<el-input v-model="formData.remark" type="textarea" :rows="2" placeholder="可选" />
</el-form-item>
</div>
</el-form>
@@ -189,12 +166,7 @@
<el-icon><Close /></el-icon>
取消
</el-button>
<el-button
class="btn-main"
type="primary"
@click="handleSubmit"
:loading="submitLoading"
>
<el-button class="btn-main" type="primary" @click="handleSubmit" :loading="submitLoading">
<el-icon><Check /></el-icon>
确定
</el-button>
@@ -292,8 +264,7 @@
align="center"
header-align="center"
:index="
(index) =>
(dictDataPagination.page - 1) * dictDataPagination.pageSize + index + 1
(index) => (dictDataPagination.page - 1) * dictDataPagination.pageSize + index + 1
"
/>
<el-table-column
@@ -326,15 +297,10 @@
header-align="center"
>
<template #default="{ row }">
<el-button
class="btn-op-item primary"
@click="handleEditDictData(row)"
>
<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" @click="handleDeleteDictData(row)"> 删除 </el-button>
</template>
</el-table-column>
</el-table>
@@ -352,9 +318,7 @@
loadDictData()
)
"
@current-change="
(val) => ((dictDataPagination.page = val), loadDictData())
"
@current-change="(val) => ((dictDataPagination.page = val), loadDictData())"
/>
</div>
</div>
@@ -418,7 +382,15 @@
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Close, Check, View, Collection, RefreshLeft, Search } from '@element-plus/icons-vue'
import {
Plus,
Close,
Check,
View,
Collection,
RefreshLeft,
Search
} from '@element-plus/icons-vue'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import { withFullscreenLoading, fullscreenLoadingText } from '@/utils/fullscreen-loading'
import {
@@ -704,11 +676,9 @@
}
async function handleDeleteDictData(row: Api.Dict.DictDataItem) {
await ElMessageBox.confirm(
`确定删除字典数据「${row.dictLabel}」吗?`,
'提示',
{ type: 'warning' }
)
await ElMessageBox.confirm(`确定删除字典数据「${row.dictLabel}」吗?`, '提示', {
type: 'warning'
})
await fetchDeleteDictData(row.id)
await loadDictData()
}
+40 -9
View File
@@ -22,8 +22,12 @@
<div class="filter-actions-row">
<span class="filter-hint">按快递公司名称、编码模糊查询。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
@@ -68,10 +72,34 @@
header-align="center"
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
/>
<el-table-column prop="expressCode" label="快递编码" min-width="120" align="center" header-align="center" />
<el-table-column prop="expressName" label="快递名称" min-width="140" align="center" header-align="center" />
<el-table-column prop="createTime" label="创建时间" min-width="180" align="center" header-align="center" />
<el-table-column label="操作" min-width="320" fixed="right" align="center" header-align="center">
<el-table-column
prop="expressCode"
label="快递编码"
min-width="120"
align="center"
header-align="center"
/>
<el-table-column
prop="expressName"
label="快递名称"
min-width="140"
align="center"
header-align="center"
/>
<el-table-column
prop="createTime"
label="创建时间"
min-width="180"
align="center"
header-align="center"
/>
<el-table-column
label="操作"
min-width="320"
fixed="right"
align="center"
header-align="center"
>
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleView(row)"
><el-icon><View /></el-icon>查看</el-button
@@ -292,7 +320,9 @@
}
async function handleDelete(row: Api.ExpressCompany.ExpressCompanyItem) {
await ElMessageBox.confirm(`确定删除快递公司「${row.expressName}」吗?`, '提示', { type: 'warning' })
await ElMessageBox.confirm(`确定删除快递公司「${row.expressName}」吗?`, '提示', {
type: 'warning'
})
await fetchDeleteExpressCompany(row.id)
ElMessage.success('删除成功')
await loadData()
@@ -301,7 +331,9 @@
async function handleBatchDelete() {
const ids = selectedRows.value.map((r) => r.id)
if (!ids.length) return
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个快递公司吗?`, '提示', { type: 'warning' })
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个快递公司吗?`, '提示', {
type: 'warning'
})
await withFullscreenLoading(async () => {
for (const id of ids) {
await fetchDeleteExpressCompany(id)
@@ -331,6 +363,5 @@
:deep(.el-form-item) {
margin-bottom: 0;
}
}
</style>
+202 -136
View File
@@ -18,7 +18,12 @@
<el-input v-model="filterForm.keyword" placeholder="搜索原因/类型" clearable />
</el-form-item>
<el-form-item label="状态">
<el-select v-model="filterForm.status" placeholder="全部" clearable style="width: 120px">
<el-select
v-model="filterForm.status"
placeholder="全部"
clearable
style="width: 120px"
>
<el-option label="草稿" value="draft" />
<el-option label="审批中" value="pending" />
<el-option label="已通过" value="approved" />
@@ -29,8 +34,12 @@
<div class="filter-actions-row">
<span class="filter-hint">按原因、类型模糊查询。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
@@ -55,23 +64,73 @@
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
<el-table-column prop="leaveTypeLabel" label="请假类型" min-width="100" align="center" header-align="center" />
<el-table-column prop="startDate" label="开始日期" min-width="120" align="center" header-align="center" />
<el-table-column prop="endDate" label="结束日期" min-width="120" align="center" header-align="center" />
<el-table-column prop="days" label="天数" min-width="80" align="center" header-align="center" />
<el-table-column
prop="leaveTypeLabel"
label="请假类型"
min-width="100"
align="center"
header-align="center"
/>
<el-table-column
prop="startDate"
label="开始日期"
min-width="120"
align="center"
header-align="center"
/>
<el-table-column
prop="endDate"
label="结束日期"
min-width="120"
align="center"
header-align="center"
/>
<el-table-column
prop="days"
label="天数"
min-width="80"
align="center"
header-align="center"
/>
<el-table-column prop="reason" label="请假原因" min-width="180" show-overflow-tooltip />
<el-table-column prop="status" label="状态" min-width="100" align="center" header-align="center">
<el-table-column
prop="status"
label="状态"
min-width="100"
align="center"
header-align="center"
>
<template #default="{ row }">
<el-tag :type="statusTagType(row.status)" size="small">{{ statusLabel(row.status) }}</el-tag>
<el-tag :type="statusTagType(row.status)" size="small">{{
statusLabel(row.status)
}}</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" min-width="180" align="center" header-align="center" />
<el-table-column label="操作" fixed="right" min-width="260" align="center" header-align="center">
<el-table-column
prop="createTime"
label="创建时间"
min-width="180"
align="center"
header-align="center"
/>
<el-table-column
label="操作"
fixed="right"
min-width="260"
align="center"
header-align="center"
>
<template #default="{ row }">
<template v-if="row.status === 'draft' || row.status === 'rejected'">
<el-button type="primary" link size="small" @click="handleEdit(row)">编辑</el-button>
<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>
<el-button type="primary" link size="small" @click="handleEdit(row)"
>编辑</el-button
>
<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
>
</template>
<template v-else-if="row.status === 'pending'">
<el-tag type="warning" size="small">审批中</el-tag>
@@ -154,7 +213,12 @@
/>
</el-form-item>
<el-form-item label="请假原因" class="form-col-span-2">
<el-input v-model="formData.reason" type="textarea" :rows="3" placeholder="请输入请假原因" />
<el-input
v-model="formData.reason"
type="textarea"
:rows="3"
placeholder="请输入请假原因"
/>
</el-form-item>
<el-form-item label="备注" class="form-col-span-2">
<el-input v-model="formData.remark" placeholder="选填" />
@@ -176,144 +240,146 @@
</template>
<script setup lang="ts">
import { Close, Check, RefreshLeft, Search } from '@element-plus/icons-vue'
import { leaveStatusLabel, leaveStatusTagType } from '@/utils/status-tag-registry'
import {
fetchLeaveList,
fetchCreateLeave,
fetchUpdateLeave,
fetchDeleteLeave,
fetchSubmitLeave
} from '@/api/leave'
import { Close, Check, RefreshLeft, Search } from '@element-plus/icons-vue'
import { leaveStatusLabel, leaveStatusTagType } from '@/utils/status-tag-registry'
import {
fetchLeaveList,
fetchCreateLeave,
fetchUpdateLeave,
fetchDeleteLeave,
fetchSubmitLeave
} from '@/api/leave'
defineOptions({ name: 'LeaveRequest' })
defineOptions({ name: 'LeaveRequest' })
const loading = ref(false)
const tableData = ref<Api.Leave.LeaveItem[]>([])
const selectedRows = ref<Api.Leave.LeaveItem[]>([])
const pagination = reactive({ page: 1, pageSize: 10, total: 0 })
const loading = ref(false)
const tableData = ref<Api.Leave.LeaveItem[]>([])
const selectedRows = ref<Api.Leave.LeaveItem[]>([])
const pagination = reactive({ page: 1, pageSize: 10, total: 0 })
const filterForm = reactive({ keyword: '', status: '' })
const filterForm = reactive({ keyword: '', status: '' })
const dialogVisible = ref(false)
const isEdit = ref(false)
const editingId = ref('')
const submitting = ref(false)
const dialogVisible = ref(false)
const isEdit = ref(false)
const editingId = ref('')
const submitting = ref(false)
const formData = reactive({
leaveType: 'personal',
startDate: '',
endDate: '',
days: 1,
reason: '',
remark: ''
})
const formData = reactive({
leaveType: 'personal',
startDate: '',
endDate: '',
days: 1,
reason: '',
remark: ''
})
const statusLabel = leaveStatusLabel
const statusTagType = leaveStatusTagType
const statusLabel = leaveStatusLabel
const statusTagType = leaveStatusTagType
function resetForm() {
formData.leaveType = 'personal'
formData.startDate = ''
formData.endDate = ''
formData.days = 1
formData.reason = ''
formData.remark = ''
}
function handleSelectionChange(rows: Api.Leave.LeaveItem[]) {
selectedRows.value = rows
}
async function loadData() {
loading.value = true
try {
const res = await fetchLeaveList({
page: pagination.page,
pageSize: pagination.pageSize,
keyword: filterForm.keyword || undefined,
status: filterForm.status || undefined
})
tableData.value = res.list || []
pagination.total = res.total || 0
} catch {
// error shown by http util
} finally {
loading.value = false
function resetForm() {
formData.leaveType = 'personal'
formData.startDate = ''
formData.endDate = ''
formData.days = 1
formData.reason = ''
formData.remark = ''
}
}
function handleSearch() {
pagination.page = 1
loadData()
}
function handleReset() {
filterForm.keyword = ''
filterForm.status = ''
pagination.page = 1
loadData()
}
function handleAdd() {
isEdit.value = false
editingId.value = ''
resetForm()
dialogVisible.value = true
}
function handleEdit(row: Api.Leave.LeaveItem) {
isEdit.value = true
editingId.value = row.id
formData.leaveType = row.leaveType
formData.startDate = row.startDate
formData.endDate = row.endDate
formData.days = row.days
formData.reason = row.reason
formData.remark = row.remark || ''
dialogVisible.value = true
}
async function handleSave() {
if (!formData.leaveType || !formData.startDate || !formData.endDate || !formData.days) {
ElMessage.warning('请填写必填项')
return
function handleSelectionChange(rows: Api.Leave.LeaveItem[]) {
selectedRows.value = rows
}
submitting.value = true
try {
if (isEdit.value) {
await fetchUpdateLeave(editingId.value, { ...formData })
} else {
await fetchCreateLeave({ ...formData })
async function loadData() {
loading.value = true
try {
const res = await fetchLeaveList({
page: pagination.page,
pageSize: pagination.pageSize,
keyword: filterForm.keyword || undefined,
status: filterForm.status || undefined
})
tableData.value = res.list || []
pagination.total = res.total || 0
} catch {
// error shown by http util
} finally {
loading.value = false
}
dialogVisible.value = false
loadData()
} catch {
// error shown by http util
} finally {
submitting.value = false
}
}
async function handleSubmit(id: string) {
try {
await ElMessageBox.confirm('确定提交审批?提交后将进入审批流程。', '提示', { type: 'warning' })
await fetchSubmitLeave(id)
function handleSearch() {
pagination.page = 1
loadData()
} catch {
// cancelled or error
}
}
async function handleDelete(id: string) {
try {
await ElMessageBox.confirm('确定删除此请假申请?', '提示', { type: 'warning' })
await fetchDeleteLeave(id)
function handleReset() {
filterForm.keyword = ''
filterForm.status = ''
pagination.page = 1
loadData()
} catch {
// cancelled or error
}
}
function handleAdd() {
isEdit.value = false
editingId.value = ''
resetForm()
dialogVisible.value = true
}
function handleEdit(row: Api.Leave.LeaveItem) {
isEdit.value = true
editingId.value = row.id
formData.leaveType = row.leaveType
formData.startDate = row.startDate
formData.endDate = row.endDate
formData.days = row.days
formData.reason = row.reason
formData.remark = row.remark || ''
dialogVisible.value = true
}
async function handleSave() {
if (!formData.leaveType || !formData.startDate || !formData.endDate || !formData.days) {
ElMessage.warning('请填写必填项')
return
}
submitting.value = true
try {
if (isEdit.value) {
await fetchUpdateLeave(editingId.value, { ...formData })
} else {
await fetchCreateLeave({ ...formData })
}
dialogVisible.value = false
loadData()
} catch {
// error shown by http util
} finally {
submitting.value = false
}
}
async function handleSubmit(id: string) {
try {
await ElMessageBox.confirm('确定提交审批?提交后将进入审批流程。', '提示', {
type: 'warning'
})
await fetchSubmitLeave(id)
loadData()
} catch {
// cancelled or error
}
}
async function handleDelete(id: string) {
try {
await ElMessageBox.confirm('确定删除此请假申请?', '提示', { type: 'warning' })
await fetchDeleteLeave(id)
loadData()
} catch {
// cancelled or error
}
}
// 输入检索条件时自动搜索(防抖 300ms)
watchDebounced(
filterForm,
@@ -324,5 +390,5 @@ async function handleDelete(id: string) {
{ debounce: 300, deep: true }
)
onMounted(() => loadData())
onMounted(() => loadData())
</script>
+42 -42
View File
@@ -21,8 +21,12 @@
<div class="filter-actions-row">
<span class="filter-hint">按菜单名称模糊查询。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
@@ -56,12 +60,7 @@
@selection-change="handleSelectionChange"
@row-dblclick="handleView"
>
<el-table-column
type="selection"
min-width="55"
align="center"
header-align="center"
/>
<el-table-column type="selection" min-width="55" align="center" header-align="center" />
<el-table-column
prop="menuName"
label="菜单名称"
@@ -77,10 +76,7 @@
header-align="center"
>
<template #default="{ row }">
<el-tag
:type="menuTypeTagMap[row.menuType]?.type || 'info'"
size="small"
>
<el-tag :type="menuTypeTagMap[row.menuType]?.type || 'info'" size="small">
{{ menuTypeTagMap[row.menuType]?.label || row.menuType }}
</el-tag>
</template>
@@ -144,13 +140,13 @@
</el-tag>
</template>
</el-table-column>
<el-table-column
label="操作"
min-width="400"
fixed="right"
align="center"
header-align="center"
>
<el-table-column
label="操作"
min-width="400"
fixed="right"
align="center"
header-align="center"
>
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleView(row)">
<el-icon><View /></el-icon>查看
@@ -230,12 +226,7 @@
</el-select>
</el-form-item>
<el-form-item label="备注" style="grid-column: 1 / -1">
<el-input
v-model="formData.remark"
type="textarea"
:rows="2"
placeholder="可选"
/>
<el-input v-model="formData.remark" type="textarea" :rows="2" placeholder="可选" />
</el-form-item>
</div>
</el-form>
@@ -244,12 +235,7 @@
<el-icon><Close /></el-icon>
取消
</el-button>
<el-button
class="btn-main"
type="primary"
@click="handleSubmit"
:loading="submitLoading"
>
<el-button class="btn-main" type="primary" @click="handleSubmit" :loading="submitLoading">
<el-icon><Check /></el-icon>
确定
</el-button>
@@ -270,14 +256,17 @@
<script setup lang="ts">
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Close, Check, View, Menu as MenuIcon, RefreshLeft, Search } from '@element-plus/icons-vue'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import {
fetchMenuTree,
fetchCreateMenu,
fetchUpdateMenu,
fetchDeleteMenu
} from '@/api/admin'
Plus,
Close,
Check,
View,
Menu as MenuIcon,
RefreshLeft,
Search
} from '@element-plus/icons-vue'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import { fetchMenuTree, fetchCreateMenu, fetchUpdateMenu, fetchDeleteMenu } from '@/api/admin'
defineOptions({ name: 'SystemMenu' })
@@ -343,13 +332,25 @@
title: '基本信息',
fields: [
{ label: '菜单名称', value: viewRow.value?.menuName },
{ label: '菜单类型', value: menuTypeTagMap[viewRow.value?.menuType || '']?.label || viewRow.value?.menuType, tagType: 'primary' },
{
label: '菜单类型',
value: menuTypeTagMap[viewRow.value?.menuType || '']?.label || viewRow.value?.menuType,
tagType: 'primary'
},
{ label: '路由路径', value: viewRow.value?.path },
{ label: '组件路径', value: viewRow.value?.component },
{ label: '权限标识', value: viewRow.value?.perms },
{ label: '是否外链', value: viewRow.value?.isFrame === 1 ? '否' : '是' },
{ label: '显示状态', value: viewRow.value?.visible === '1' ? '显示' : '隐藏', tagType: viewRow.value?.visible === '1' ? 'success' : 'info' },
{ label: '状态', value: viewRow.value?.status === '1' ? '正常' : '停用', tagType: viewRow.value?.status === '1' ? 'success' : 'info' },
{
label: '显示状态',
value: viewRow.value?.visible === '1' ? '显示' : '隐藏',
tagType: viewRow.value?.visible === '1' ? 'success' : 'info'
},
{
label: '状态',
value: viewRow.value?.status === '1' ? '正常' : '停用',
tagType: viewRow.value?.status === '1' ? 'success' : 'info'
},
{ label: '备注', value: viewRow.value?.remark, span: true }
]
}
@@ -544,6 +545,5 @@
:deep(.el-form-item) {
margin-bottom: 0;
}
}
</style>
File diff suppressed because it is too large. Load diff
+69 -23
View File
@@ -22,8 +22,12 @@
<div class="filter-actions-row">
<span class="filter-hint">按职位名称、编码模糊查询。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
@@ -68,19 +72,51 @@
header-align="center"
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
/>
<el-table-column prop="postName" label="职位名称" min-width="140" align="center" header-align="center" />
<el-table-column prop="postCode" label="职位编码" min-width="120" align="center" header-align="center" />
<el-table-column prop="status" label="状态" min-width="80" align="center" header-align="center">
<el-table-column
prop="postName"
label="职位名称"
min-width="140"
align="center"
header-align="center"
/>
<el-table-column
prop="postCode"
label="职位编码"
min-width="120"
align="center"
header-align="center"
/>
<el-table-column
prop="status"
label="状态"
min-width="80"
align="center"
header-align="center"
>
<template #default="{ row }">
<el-tag :type="row.status === '1' ? 'success' : 'info'" size="small">
{{ row.status === '1' ? '正常' : '停用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" min-width="180" align="center" header-align="center" />
<el-table-column label="操作" min-width="480" fixed="right" align="center" header-align="center">
<el-table-column
prop="createTime"
label="创建时间"
min-width="180"
align="center"
header-align="center"
/>
<el-table-column
label="操作"
min-width="480"
fixed="right"
align="center"
header-align="center"
>
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleView(row)"><el-icon><View /></el-icon>查看</el-button>
<el-button class="btn-op-item" @click="handleView(row)"
><el-icon><View /></el-icon>查看</el-button
>
<el-button class="btn-op-item primary" @click="handlePostBindUsers(row)">
<el-icon><User /></el-icon>
关联用户
@@ -165,10 +201,7 @@
destroy-on-close
:close-on-click-modal="false"
>
<DialogFormBody
:loading="postBindLoading"
body-class="post-bind-dialog-body"
>
<DialogFormBody :loading="postBindLoading" body-class="post-bind-dialog-body">
<p v-if="postBindPostName" class="post-bind-subtitle">
职位:<strong>{{ postBindPostName }}</strong>
</p>
@@ -275,7 +308,16 @@
<script setup lang="ts">
import { ref, reactive, computed, onMounted, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Close, Check, User, View, Briefcase, RefreshLeft, Search } from '@element-plus/icons-vue'
import {
Plus,
Close,
Check,
User,
View,
Briefcase,
RefreshLeft,
Search
} from '@element-plus/icons-vue'
import DialogFormBody from '@/components/business/dialog-form-body/index.vue'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import { MAX_ADMIN_LIST_PAGE_SIZE } from '@/utils/fetch-paged-list'
@@ -334,7 +376,11 @@
fields: [
{ label: '职位名称', value: row.postName },
{ label: '职位编码', value: row.postCode },
{ label: '状态', value: row.status === '1' ? '正常' : '停用', tagType: row.status === '1' ? 'success' : 'info' },
{
label: '状态',
value: row.status === '1' ? '正常' : '停用',
tagType: row.status === '1' ? 'success' : 'info'
},
{ label: '创建时间', value: row.createTime },
{ label: '备注', value: row.remark, span: true }
]
@@ -343,9 +389,7 @@
if (viewBoundUserNames.value.length > 0) {
sections.push({
title: '关联用户',
fields: [
{ label: '已关联用户', value: viewBoundUserNames.value.join('、'), span: true }
]
fields: [{ label: '已关联用户', value: viewBoundUserNames.value.join('、'), span: true }]
})
}
return sections
@@ -355,10 +399,7 @@
viewBoundUserNames.value = []
viewVisible.value = true
try {
const [boundRes] = await Promise.all([
fetchPostBoundUserIds(row.id),
fetchDeptTree()
])
const [boundRes] = await Promise.all([fetchPostBoundUserIds(row.id), fetchDeptTree()])
const boundIds = boundRes?.userIds || []
if (boundIds.length === 0) return
const users = await fetchAllUsersForPostBind()
@@ -384,7 +425,10 @@
const postBindUserFilterDeptId = ref<string | null>(null)
const postBindUserKeyword = ref('')
function findPostBindDeptNodeById(nodes: Api.Dept.DeptItem[], id: string): Api.Dept.DeptItem | null {
function findPostBindDeptNodeById(
nodes: Api.Dept.DeptItem[],
id: string
): Api.Dept.DeptItem | null {
for (const n of nodes) {
if (n.id === id) return n
if (n.children?.length) {
@@ -641,7 +685,9 @@
async function handleBatchDelete() {
const ids = selectedRows.value.map((r) => r.id)
if (!ids.length) return
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个职位吗?`, '提示', { type: 'warning' })
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个职位吗?`, '提示', {
type: 'warning'
})
await withFullscreenLoading(async () => {
for (const id of ids) {
await fetchDeletePost(id)
File diff suppressed because it is too large. Load diff
+19 -4
View File
@@ -22,8 +22,12 @@
<div class="filter-actions-row">
<span class="filter-hint">按角色名称模糊查询。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
@@ -114,7 +118,9 @@
header-align="center"
>
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleView(row)"><el-icon><View /></el-icon>查看</el-button>
<el-button class="btn-op-item" @click="handleView(row)"
><el-icon><View /></el-icon>查看</el-button
>
<el-button class="btn-op-item primary" @click="handleMenuConfig(row)"
>菜单配置</el-button
>
@@ -407,7 +413,16 @@
<script setup lang="ts">
import { ref, reactive, computed, onMounted, nextTick, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Close, Check, DataAnalysis, View, Stamp, RefreshLeft, Search } from '@element-plus/icons-vue'
import {
Plus,
Close,
Check,
DataAnalysis,
View,
Stamp,
RefreshLeft,
Search
} from '@element-plus/icons-vue'
import DialogFormBody from '@/components/business/dialog-form-body/index.vue'
import SystemViewDialog, {
type ViewSection
+85 -17
View File
@@ -22,8 +22,12 @@
<div class="filter-actions-row">
<span class="filter-hint">按站点名称、编码模糊查询。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
@@ -68,27 +72,84 @@
header-align="center"
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
/>
<el-table-column prop="siteName" label="站点名称" min-width="140" align="center" header-align="center" />
<el-table-column prop="siteCode" label="站点编码" min-width="120" align="center" header-align="center" />
<el-table-column prop="siteType" label="站点类型" min-width="100" align="center" header-align="center">
<el-table-column
prop="siteName"
label="站点名称"
min-width="140"
align="center"
header-align="center"
/>
<el-table-column
prop="siteCode"
label="站点编码"
min-width="120"
align="center"
header-align="center"
/>
<el-table-column
prop="siteType"
label="站点类型"
min-width="100"
align="center"
header-align="center"
>
<template #default="{ row }">
{{ getSiteTypeLabel(row.siteType) }}
</template>
</el-table-column>
<el-table-column prop="status" label="状态" min-width="80" align="center" header-align="center">
<el-table-column
prop="status"
label="状态"
min-width="80"
align="center"
header-align="center"
>
<template #default="{ row }">
<el-tag :type="row.status === '1' ? 'success' : 'info'" size="small">
{{ row.status === '1' ? '正常' : '停用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="address" label="地址" min-width="160" align="center" header-align="center" show-overflow-tooltip />
<el-table-column prop="contactName" label="联系人" min-width="100" align="center" header-align="center" />
<el-table-column prop="contactPhone" label="联系电话" min-width="140" align="center" header-align="center" />
<el-table-column prop="createTime" label="创建时间" min-width="180" align="center" header-align="center" />
<el-table-column label="操作" min-width="320" fixed="right" align="center" header-align="center">
<el-table-column
prop="address"
label="地址"
min-width="160"
align="center"
header-align="center"
show-overflow-tooltip
/>
<el-table-column
prop="contactName"
label="联系人"
min-width="100"
align="center"
header-align="center"
/>
<el-table-column
prop="contactPhone"
label="联系电话"
min-width="140"
align="center"
header-align="center"
/>
<el-table-column
prop="createTime"
label="创建时间"
min-width="180"
align="center"
header-align="center"
/>
<el-table-column
label="操作"
min-width="320"
fixed="right"
align="center"
header-align="center"
>
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleView(row)"><el-icon><View /></el-icon>查看</el-button>
<el-button class="btn-op-item" @click="handleView(row)"
><el-icon><View /></el-icon>查看</el-button
>
<el-button class="btn-op-item primary" @click="handleEdit(row)">编辑</el-button>
<el-button class="btn-op-item" @click="handleDelete(row)">删除</el-button>
</template>
@@ -256,7 +317,11 @@
{ label: '站点名称', value: row.siteName },
{ label: '站点编码', value: row.siteCode },
{ label: '站点类型', value: getSiteTypeLabel(row.siteType), tagType: 'primary' },
{ label: '状态', value: row.status === '1' ? '正常' : '停用', tagType: row.status === '1' ? 'success' : 'info' },
{
label: '状态',
value: row.status === '1' ? '正常' : '停用',
tagType: row.status === '1' ? 'success' : 'info'
},
{ label: '地址', value: row.address, span: true }
]
},
@@ -276,7 +341,7 @@
})
.join('、')
: '无',
span: true,
span: true
},
{ label: '备注', value: row.remark, span: true },
{ label: '创建时间', value: row.createTime }
@@ -538,7 +603,9 @@
address: formData.address?.trim() || undefined,
contactName: formData.contactName?.trim() || undefined,
contactPhone: formData.contactPhone?.trim() || undefined,
businessScope: formData.businessScopeList.length ? formData.businessScopeList.join(',') : undefined,
businessScope: formData.businessScopeList.length
? formData.businessScopeList.join(',')
: undefined,
orderNum: formData.orderNum,
remark: formData.remark?.trim() || undefined
}
@@ -567,7 +634,9 @@
async function handleBatchDelete() {
const ids = selectedRows.value.map((r) => r.id)
if (!ids.length) return
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个站点吗?`, '提示', { type: 'warning' })
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个站点吗?`, '提示', {
type: 'warning'
})
await withFullscreenLoading(async () => {
for (const id of ids) {
await fetchDeleteSite(id)
@@ -598,6 +667,5 @@
:deep(.el-form-item) {
margin-bottom: 0;
}
}
</style>
+15 -4
View File
@@ -26,8 +26,12 @@
<div class="filter-actions-row">
<span class="filter-hint">按租户编号、名称模糊查询。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
@@ -226,7 +230,15 @@
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Close, Check, View, OfficeBuilding, RefreshLeft, Search } from '@element-plus/icons-vue'
import {
Plus,
Close,
Check,
View,
OfficeBuilding,
RefreshLeft,
Search
} from '@element-plus/icons-vue'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import { withFullscreenLoading, fullscreenLoadingText } from '@/utils/fullscreen-loading'
import {
@@ -444,6 +456,5 @@
:deep(.el-form-item) {
margin-bottom: 0;
}
}
</style>
+46 -9
View File
@@ -22,8 +22,12 @@
<div class="filter-actions-row">
<span class="filter-hint">按名称、编码模糊查询。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
@@ -68,10 +72,34 @@
header-align="center"
:index="(index) => (pagination.page - 1) * pagination.pageSize + index + 1"
/>
<el-table-column prop="unitName" label="单位名称" min-width="150" align="center" header-align="center" />
<el-table-column prop="unitCode" label="单位编码" min-width="120" align="center" header-align="center" />
<el-table-column prop="createTime" label="创建时间" min-width="180" align="center" header-align="center" />
<el-table-column label="操作" min-width="320" fixed="right" align="center" header-align="center">
<el-table-column
prop="unitName"
label="单位名称"
min-width="150"
align="center"
header-align="center"
/>
<el-table-column
prop="unitCode"
label="单位编码"
min-width="120"
align="center"
header-align="center"
/>
<el-table-column
prop="createTime"
label="创建时间"
min-width="180"
align="center"
header-align="center"
/>
<el-table-column
label="操作"
min-width="320"
fixed="right"
align="center"
header-align="center"
>
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleView(row)"
><el-icon><View /></el-icon>查看</el-button
@@ -150,7 +178,15 @@
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Close, Check, View, ScaleToOriginal, RefreshLeft, Search } from '@element-plus/icons-vue'
import {
Plus,
Close,
Check,
View,
ScaleToOriginal,
RefreshLeft,
Search
} from '@element-plus/icons-vue'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import { withFullscreenLoading, fullscreenLoadingText } from '@/utils/fullscreen-loading'
import {
@@ -301,7 +337,9 @@
async function handleBatchDelete() {
const ids = selectedRows.value.map((r) => r.id)
if (!ids.length) return
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个单位吗?`, '提示', { type: 'warning' })
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个单位吗?`, '提示', {
type: 'warning'
})
await withFullscreenLoading(async () => {
for (const id of ids) {
await fetchDeleteItemUnit(id)
@@ -331,6 +369,5 @@
:deep(.el-form-item) {
margin-bottom: 0;
}
}
</style>
File diff suppressed because it is too large. Load diff
+98 -19
View File
@@ -51,8 +51,12 @@
<div class="filter-actions-row">
<span class="filter-hint">支持按关键词、状态筛选。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
@@ -86,29 +90,73 @@
header-align="center"
:index="(index: number) => (pagination.page - 1) * pagination.pageSize + index + 1"
/>
<el-table-column prop="userNo" label="用户账号" min-width="120" align="center" header-align="center" />
<el-table-column prop="nickName" label="用户名" min-width="100" align="center" header-align="center" />
<el-table-column prop="deptName" label="所属组织" min-width="200" align="center" header-align="center">
<el-table-column
prop="userNo"
label="用户账号"
min-width="120"
align="center"
header-align="center"
/>
<el-table-column
prop="nickName"
label="用户名"
min-width="100"
align="center"
header-align="center"
/>
<el-table-column
prop="deptName"
label="所属组织"
min-width="200"
align="center"
header-align="center"
>
<template #default="{ row }">
{{ formatUserDeptDisplay(row) }}
</template>
</el-table-column>
<el-table-column prop="phoneNo" label="手机号" min-width="140" align="center" header-align="center">
<el-table-column
prop="phoneNo"
label="手机号"
min-width="140"
align="center"
header-align="center"
>
<template #default="{ row }">
{{ row.phoneNo || '-' }}
</template>
</el-table-column>
<el-table-column prop="status" label="状态" min-width="80" align="center" header-align="center">
<el-table-column
prop="status"
label="状态"
min-width="80"
align="center"
header-align="center"
>
<template #default="{ row }">
<el-tag :type="row.status === '1' ? 'success' : 'info'" size="small">
{{ row.status === '1' ? '正常' : '停用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建时间" min-width="180" align="center" header-align="center" />
<el-table-column label="操作" min-width="400" fixed="right" align="center" header-align="center">
<el-table-column
prop="createTime"
label="创建时间"
min-width="180"
align="center"
header-align="center"
/>
<el-table-column
label="操作"
min-width="400"
fixed="right"
align="center"
header-align="center"
>
<template #default="{ row }">
<el-button class="btn-op-item" @click="handleView(row)"><el-icon><View /></el-icon>查看</el-button>
<el-button class="btn-op-item" @click="handleView(row)"
><el-icon><View /></el-icon>查看</el-button
>
<el-button class="btn-op-item primary" @click="handleEdit(row)">编辑</el-button>
<el-button class="btn-op-item" @click="handleResetPwd(row)">重置密码</el-button>
<el-button class="btn-op-item" @click="handleDelete(row)">删除</el-button>
@@ -123,7 +171,9 @@
:total="pagination.total"
:page-sizes="[10, 20, 50]"
layout="total, sizes, prev, pager, next"
@size-change="(val: number) => ((pagination.page = 1), (pagination.pageSize = val), loadData())"
@size-change="
(val: number) => ((pagination.page = 1), (pagination.pageSize = val), loadData())
"
@current-change="(val: number) => ((pagination.page = val), loadData())"
/>
</div>
@@ -158,7 +208,12 @@
<el-input v-model="formData.nickName" placeholder="显示名称" />
</el-form-item>
<el-form-item v-if="!isEdit" label="密码" prop="password">
<el-input v-model="formData.password" type="password" show-password placeholder="登录密码" />
<el-input
v-model="formData.password"
type="password"
show-password
placeholder="登录密码"
/>
</el-form-item>
<el-form-item label="手机号">
<el-input v-model="formData.phoneNo" placeholder="可选" />
@@ -180,8 +235,18 @@
</el-select>
</el-form-item>
<el-form-item label="角色" style="grid-column: 1 / -1">
<el-select v-model="formData.roleIds" multiple placeholder="请选择角色" style="width: 100%">
<el-option v-for="item in roleOptions" :key="item.value" :label="item.label" :value="item.value" />
<el-select
v-model="formData.roleIds"
multiple
placeholder="请选择角色"
style="width: 100%"
>
<el-option
v-for="item in roleOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" style="grid-column: 1 / -1">
@@ -215,7 +280,15 @@
<script setup lang="ts">
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Close, Check, View, UserFilled, RefreshLeft, Search } from '@element-plus/icons-vue'
import {
Plus,
Close,
Check,
View,
UserFilled,
RefreshLeft,
Search
} from '@element-plus/icons-vue'
import SystemViewDialog from '@/components/business/system-view-dialog/index.vue'
import {
fetchUserList,
@@ -457,7 +530,9 @@
}
async function handleResetPwd(row: Api.User.UserItem) {
await ElMessageBox.confirm(`确定将用户「${row.nickName}」的密码重置为 111111 吗?`, '提示', { type: 'warning' })
await ElMessageBox.confirm(`确定将用户「${row.nickName}」的密码重置为 111111 吗?`, '提示', {
type: 'warning'
})
await fetchResetPassword(row.id)
}
@@ -479,9 +554,14 @@
{ label: '邮箱', value: row.email },
{
label: '性别',
value: ({ '0': '男', '1': '女', '2': '未知' } as Record<string, string>)[row.sex] || '未知'
value:
({ '0': '男', '1': '女', '2': '未知' } as Record<string, string>)[row.sex] || '未知'
},
{
label: '状态',
value: row.status === '1' ? '正常' : '停用',
tagType: row.status === '1' ? 'success' : 'info'
},
{ label: '状态', value: row.status === '1' ? '正常' : '停用', tagType: row.status === '1' ? 'success' : 'info' },
{ label: '角色', value: formatUserRoleDisplay(row), span: true },
{ label: '创建时间', value: row.createTime },
{ label: '备注', value: row.remark, span: true }
@@ -534,6 +614,5 @@
:deep(.el-form-item) {
margin-bottom: 0;
}
}
</style>
@@ -6,7 +6,13 @@
class="user-dialog"
align-center
>
<ElForm ref="formRef" :model="formData" :rules="rules" label-position="top" class="user-form-grid">
<ElForm
ref="formRef"
:model="formData"
:rules="rules"
label-position="top"
class="user-form-grid"
>
<ElFormItem label="用户名" prop="username">
<ElInput v-model="formData.username" placeholder="请输入用户名" />
</ElFormItem>
@@ -32,8 +38,12 @@
</ElForm>
<template #footer>
<div class="dialog-footer">
<ElButton class="btn-ghost" @click="dialogVisible = false"><el-icon><Close /></el-icon>取消</ElButton>
<ElButton class="btn-main" type="primary" @click="handleSubmit"><el-icon><Check /></el-icon>提交</ElButton>
<ElButton class="btn-ghost" @click="dialogVisible = false"
><el-icon><Close /></el-icon>取消</ElButton
>
<ElButton class="btn-main" type="primary" @click="handleSubmit"
><el-icon><Check /></el-icon>提交</ElButton
>
</div>
</template>
</ElDialog>
@@ -19,7 +19,9 @@
<div class="view-hero-main">
<h2>{{ instanceData?.processName || '审批操作' }}</h2>
<div class="view-hero-tags">
<el-tag size="small" type="info">{{ instanceData?.businessTypeLabel || instanceData?.businessType || '--' }}</el-tag>
<el-tag size="small" type="info">{{
instanceData?.businessTypeLabel || instanceData?.businessType || '--'
}}</el-tag>
</div>
<p v-if="instanceData" class="view-hero-meta">
发起人:{{ instanceData.starterUserName || '--' }}
@@ -64,7 +66,9 @@
</div>
</div>
<template #footer>
<el-button class="btn-ghost" @click="visible = false"><el-icon><Close /></el-icon>取消</el-button>
<el-button class="btn-ghost" @click="visible = false"
><el-icon><Close /></el-icon>取消</el-button
>
<el-button type="primary" class="btn-main" :loading="submitting" @click="handleSubmit">
<el-icon><Check /></el-icon>
确认提交
File diff suppressed because it is too large. Load diff
@@ -23,7 +23,12 @@
/>
</el-form-item>
<el-form-item label="状态">
<el-select v-model="searchForm.status" placeholder="全部" clearable style="width: 140px">
<el-select
v-model="searchForm.status"
placeholder="全部"
clearable
style="width: 140px"
>
<el-option label="进行中" value="running" />
<el-option label="已完成" value="completed" />
<el-option label="已驳回" value="rejected" />
@@ -33,8 +38,12 @@
<div class="filter-actions-row">
<span class="filter-hint">按流程名称、业务单号模糊查询。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
@@ -98,9 +107,17 @@
align="center"
header-align="center"
/>
<el-table-column label="操作" min-width="160" fixed="right" align="center" header-align="center">
<el-table-column
label="操作"
min-width="160"
fixed="right"
align="center"
header-align="center"
>
<template #default="{ row }">
<el-button class="btn-op-item primary" @click="handleViewDetail(row)"><el-icon><View /></el-icon>查看详情</el-button>
<el-button class="btn-op-item primary" @click="handleViewDetail(row)"
><el-icon><View /></el-icon>查看详情</el-button
>
</template>
</el-table-column>
</el-table>
@@ -137,7 +154,9 @@
<h2>{{ detailRow?.processName || '流程详情' }}</h2>
<div class="view-hero-tags">
<ProcessStatusTag :status="detailRow?.status || ''" />
<el-tag size="small" type="info">{{ detailRow?.businessTypeLabel || detailData.businessType || '--' }}</el-tag>
<el-tag size="small" type="info">{{
detailRow?.businessTypeLabel || detailData.businessType || '--'
}}</el-tag>
</div>
<p class="view-hero-meta">
业务单号:{{ detailData.businessId || '--' }}
@@ -147,10 +166,17 @@
</div>
</div>
<div v-if="detailData.businessFormFields && detailData.businessFormFields.length" class="view-section">
<div
v-if="detailData.businessFormFields && detailData.businessFormFields.length"
class="view-section"
>
<h3>申请信息</h3>
<dl class="view-kv-grid">
<div v-for="field in detailData.businessFormFields" :key="field.label" class="view-kv">
<div
v-for="field in detailData.businessFormFields"
:key="field.label"
class="view-kv"
>
<dt>{{ field.label }}</dt>
<dd>{{ field.value || '--' }}</dd>
</div>
@@ -187,7 +213,9 @@
</template>
</div>
<template #footer>
<el-button class="btn-ghost" @click="detailVisible = false"><el-icon><Close /></el-icon>关闭</el-button>
<el-button class="btn-ghost" @click="detailVisible = false"
><el-icon><Close /></el-icon>关闭</el-button
>
</template>
</el-dialog>
</section>
@@ -218,7 +246,7 @@
page: pagination.page,
pageSize: pagination.pageSize,
keyword: searchForm.keyword || undefined,
status: searchForm.status || undefined,
status: searchForm.status || undefined
})
tableData.value = res.list || []
pagination.total = res.total ?? 0
@@ -245,10 +273,7 @@
detailData.value = null
detailRow.value = row
try {
const data = await fetchBusinessAllTasks(
row.businessType || '',
row.businessId || ''
)
const data = await fetchBusinessAllTasks(row.businessType || '', row.businessId || '')
detailData.value = data
} catch {
// error handled globally
@@ -27,8 +27,12 @@
<div class="filter-actions-row">
<span class="filter-hint">按流程名称、编码模糊查询。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
@@ -109,11 +113,23 @@
align="center"
header-align="center"
/>
<el-table-column label="操作" min-width="400" fixed="right" align="center" header-align="center">
<el-table-column
label="操作"
min-width="400"
fixed="right"
align="center"
header-align="center"
>
<template #default="{ row }">
<el-button class="btn-op-item primary" @click="handleDesign(row)"><el-icon><SetUp /></el-icon>流程设计</el-button>
<el-button class="btn-op-item" @click="handleEdit(row)"><el-icon><Edit /></el-icon>编辑</el-button>
<el-button class="btn-op-item" @click="handleDelete(row)"><el-icon><Delete /></el-icon>删除</el-button>
<el-button class="btn-op-item primary" @click="handleDesign(row)"
><el-icon><SetUp /></el-icon>流程设计</el-button
>
<el-button class="btn-op-item" @click="handleEdit(row)"
><el-icon><Edit /></el-icon>编辑</el-button
>
<el-button class="btn-op-item" @click="handleDelete(row)"
><el-icon><Delete /></el-icon>删除</el-button
>
</template>
</el-table-column>
</el-table>
@@ -185,7 +201,16 @@
</template>
<script setup lang="ts">
import { Plus, Close, Check, Search, RefreshLeft, Delete, SetUp, Edit } from '@element-plus/icons-vue'
import {
Plus,
Close,
Check,
Search,
RefreshLeft,
Delete,
SetUp,
Edit
} from '@element-plus/icons-vue'
import { withFullscreenLoading, fullscreenLoadingText } from '@/utils/fullscreen-loading'
import {
fetchProcessDefList,
@@ -310,7 +335,10 @@
}
}
async function handleStatusChange(row: Api.Workflow.ProcessDefItem, val: string | number | boolean) {
async function handleStatusChange(
row: Api.Workflow.ProcessDefItem,
val: string | number | boolean
) {
const newStatus = String(val)
await fetchUpdateProcessDef(row.id, { status: newStatus })
await loadData()
@@ -325,7 +353,9 @@
async function handleBatchDelete() {
const ids = selectedRows.value.map((r) => r.id)
if (!ids.length) return
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个流程吗?`, '提示', { type: 'warning' })
await ElMessageBox.confirm(`确定删除选中的 ${ids.length} 个流程吗?`, '提示', {
type: 'warning'
})
await withFullscreenLoading(async () => {
for (const id of ids) {
await fetchDeleteProcessDef(id)
@@ -26,8 +26,12 @@
<div class="filter-actions-row">
<span class="filter-hint">按流程名称模糊查询。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
@@ -99,9 +103,17 @@
align="center"
header-align="center"
/>
<el-table-column label="操作" min-width="260" fixed="right" align="center" header-align="center">
<el-table-column
label="操作"
min-width="260"
fixed="right"
align="center"
header-align="center"
>
<template #default="{ row }">
<el-button class="btn-op-item primary" @click="handleViewDetail(row)"><el-icon><View /></el-icon>查看详情</el-button>
<el-button class="btn-op-item primary" @click="handleViewDetail(row)"
><el-icon><View /></el-icon>查看详情</el-button
>
</template>
</el-table-column>
</el-table>
@@ -138,7 +150,9 @@
<h2>{{ detailData.processName || '流程详情' }}</h2>
<div class="view-hero-tags">
<ProcessStatusTag :status="detailData.status || ''" />
<el-tag size="small" type="info">{{ detailData.businessTypeLabel || detailData.businessType || '--' }}</el-tag>
<el-tag size="small" type="info">{{
detailData.businessTypeLabel || detailData.businessType || '--'
}}</el-tag>
</div>
<p class="view-hero-meta">
发起人:{{ detailData.starterUserName || '--' }}
@@ -150,10 +164,17 @@
</div>
</div>
<div v-if="detailData.businessFormFields && detailData.businessFormFields.length" class="view-section">
<div
v-if="detailData.businessFormFields && detailData.businessFormFields.length"
class="view-section"
>
<h3>申请信息</h3>
<dl class="view-kv-grid">
<div v-for="field in detailData.businessFormFields" :key="field.label" class="view-kv">
<div
v-for="field in detailData.businessFormFields"
:key="field.label"
class="view-kv"
>
<dt>{{ field.label }}</dt>
<dd>{{ field.value || '--' }}</dd>
</div>
@@ -190,7 +211,9 @@
</template>
</div>
<template #footer>
<el-button class="btn-ghost" @click="detailVisible = false"><el-icon><Close /></el-icon>关闭</el-button>
<el-button class="btn-ghost" @click="detailVisible = false"
><el-icon><Close /></el-icon>关闭</el-button
>
</template>
</el-dialog>
</section>
@@ -253,7 +276,7 @@
businessTypeLabel: row.businessTypeLabel,
businessId: row.businessId,
starterUserId: row.starterUserId,
starterUserName: row.starterUserName,
starterUserName: row.starterUserName
} as Api.Workflow.InstanceDetail & {
processName?: string
businessType?: string
@@ -26,8 +26,12 @@
<div class="filter-actions-row">
<span class="filter-hint">按流程名称模糊查询。</span>
<div class="filter-actions-end">
<el-button class="btn-ghost" @click="handleReset"><el-icon><RefreshLeft /></el-icon>重置</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
<el-button class="btn-ghost" @click="handleReset"
><el-icon><RefreshLeft /></el-icon>重置</el-button
>
<el-button class="btn-main" type="primary" @click="handleSearch"
><el-icon><Search /></el-icon>搜索</el-button
>
</div>
</div>
</el-form>
@@ -87,10 +91,20 @@
align="center"
header-align="center"
/>
<el-table-column label="操作" min-width="260" fixed="right" align="center" header-align="center">
<el-table-column
label="操作"
min-width="260"
fixed="right"
align="center"
header-align="center"
>
<template #default="{ row }">
<el-button class="btn-op-item primary" @click="handleApprove(row)"><el-icon><EditPen /></el-icon>审批</el-button>
<el-button class="btn-op-item" @click="handleViewDetail(row)"><el-icon><View /></el-icon>查看详情</el-button>
<el-button class="btn-op-item primary" @click="handleApprove(row)"
><el-icon><EditPen /></el-icon>审批</el-button
>
<el-button class="btn-op-item" @click="handleViewDetail(row)"
><el-icon><View /></el-icon>查看详情</el-button
>
</template>
</el-table-column>
</el-table>
@@ -135,7 +149,9 @@
<h2>{{ detailData.processName || '流程详情' }}</h2>
<div class="view-hero-tags">
<ProcessStatusTag :status="detailData.status || ''" />
<el-tag size="small" type="info">{{ detailData.businessTypeLabel || detailData.businessType || '--' }}</el-tag>
<el-tag size="small" type="info">{{
detailData.businessTypeLabel || detailData.businessType || '--'
}}</el-tag>
</div>
<p class="view-hero-meta">
发起人:{{ detailData.starterUserName || '--' }}
@@ -147,10 +163,17 @@
</div>
</div>
<div v-if="detailData.businessFormFields && detailData.businessFormFields.length" class="view-section">
<div
v-if="detailData.businessFormFields && detailData.businessFormFields.length"
class="view-section"
>
<h3>申请信息</h3>
<dl class="view-kv-grid">
<div v-for="field in detailData.businessFormFields" :key="field.label" class="view-kv">
<div
v-for="field in detailData.businessFormFields"
:key="field.label"
class="view-kv"
>
<dt>{{ field.label }}</dt>
<dd>{{ field.value || '--' }}</dd>
</div>
@@ -187,7 +210,9 @@
</template>
</div>
<template #footer>
<el-button class="btn-ghost" @click="detailVisible = false"><el-icon><Close /></el-icon>关闭</el-button>
<el-button class="btn-ghost" @click="detailVisible = false"
><el-icon><Close /></el-icon>关闭</el-button
>
</template>
</el-dialog>
</section>
@@ -266,7 +291,7 @@
businessTypeLabel: row.businessTypeLabel,
businessId: row.businessId,
starterUserId: row.starterUserId,
starterUserName: row.starterUserName,
starterUserName: row.starterUserName
} as Api.Workflow.InstanceDetail & {
processName?: string
businessType?: string