feat: 新增部门报餐和请假申请API及字典选择组件

新增部门报餐和员工请假申请的API接口文件,包含列表查询、详情获取、新增、修改和删除功能
添加可编辑的字典选择组件DictSelect,支持字典项的双击编辑、快速新增和刷新功能
This commit is contained in:
砂糖
2026-01-17 14:51:01 +08:00
parent 1669263430
commit 2a501c5486
3 changed files with 405 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询员工请假申请列表
export function listLeaveRequest(query) {
return request({
url: '/wms/leaveRequest/list',
method: 'get',
params: query
})
}
// 查询员工请假申请详细
export function getLeaveRequest(leaveId) {
return request({
url: '/wms/leaveRequest/' + leaveId,
method: 'get'
})
}
// 新增员工请假申请
export function addLeaveRequest(data) {
return request({
url: '/wms/leaveRequest',
method: 'post',
data: data
})
}
// 修改员工请假申请
export function updateLeaveRequest(data) {
return request({
url: '/wms/leaveRequest',
method: 'put',
data: data
})
}
// 删除员工请假申请
export function delLeaveRequest(leaveId) {
return request({
url: '/wms/leaveRequest/' + leaveId,
method: 'delete'
})
}

View File

@@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询部门报餐主列表
export function listMealReport(query) {
return request({
url: '/wms/mealReport/list',
method: 'get',
params: query
})
}
// 查询部门报餐主详细
export function getMealReport(reportId) {
return request({
url: '/wms/mealReport/' + reportId,
method: 'get'
})
}
// 新增部门报餐主
export function addMealReport(data) {
return request({
url: '/wms/mealReport',
method: 'post',
data: data
})
}
// 修改部门报餐主
export function updateMealReport(data) {
return request({
url: '/wms/mealReport',
method: 'put',
data: data
})
}
// 删除部门报餐主
export function delMealReport(reportId) {
return request({
url: '/wms/mealReport/' + reportId,
method: 'delete'
})
}

View File

@@ -0,0 +1,317 @@
<template>
<div style="display: flex; align-items: center;" v-loading="loading">
<!-- 下拉选择器绑定计算属性做双向绑定保留原有样式+清空功能 -->
<el-select v-model="innerValue" :placeholder="placeholder" clearable filterable style="width: 200px;">
<el-option
v-for="item in dictOptions"
:key="item.dictValue"
:label="item.dictLabel"
:value="item.dictValue"
/>
</el-select>
<!-- 编辑按钮点击打开弹窗 -->
<div
v-if="editable"
@click="openDictDialog"
style="cursor: pointer; height: 24px; width: 24px; margin-top: 4px; display: flex; align-items: center; justify-content: center; border: 1px solid #828991; margin-left: 8px; border-radius: 2px;"
>
<i class="el-icon-setting"></i>
</div>
<div
v-if="refresh"
@click="handleRefresh"
style="cursor: pointer; height: 24px; width: 24px; margin-top: 4px; display: flex; align-items: center; justify-content: center; border: 1px solid #828991; margin-left: 8px; border-radius: 2px;"
>
<i class="el-icon-refresh"></i>
</div>
<!-- 字典编辑弹窗 -->
<el-dialog
v-if="editable"
:visible.sync="open"
title="字典数据配置"
width="600px"
append-to-body
>
<!-- 快捷新增表单区域仅做新增无编辑功能 -->
<el-form
ref="dictFormRef"
:model="form"
:rules="dictRules"
label-width="68px"
label-position="left"
style="margin-bottom: 20px;"
>
<el-row :gutter="15">
<el-col :span="kisv ? 24 : 12">
<el-form-item label="值/标签" prop="dictValue" v-if="kisv">
<el-input v-model="form.dictValue" placeholder="请输入字典值(标签自动同步)" />
</el-form-item>
<el-form-item label="字典标签" prop="dictLabel" v-else>
<el-input v-model="form.dictLabel" placeholder="请输入字典标签" />
</el-form-item>
</el-col>
<el-col :span="12" v-if="!kisv">
<el-form-item label="字典值" prop="dictValue">
<el-input v-model="form.dictValue" placeholder="请输入字典值" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div style="margin-bottom: 20px;">
<el-button type="primary" size="small" @click="submitAddDict" :loading="btnLoading">新增字典项</el-button>
<el-button size="small" @click="resetDictForm">清空表单</el-button>
<span style="margin-left: 10px;">提示双击单元格中的文字可以快速编辑</span>
</div>
<!-- 字典列表 核心修改双击单元格激活输入框失焦还原文本 -->
<el-table
:data="dictOptions"
border
stripe
size="mini"
style="width: 100%;"
empty-text="暂无字典数据"
>
<!-- 字典标签列kisv=true隐藏false正常展示 -->
<el-table-column label="字典标签" align="center" v-if="!kisv">
<template #default="scope">
<!-- 双击span触发编辑失焦/回车后变回span -->
<span
v-if="editRowId !== scope.row.dictCode"
@dblclick.stop="handleDbEdit(scope.row)"
style="cursor: pointer;"
>
{{ scope.row.dictLabel }}
</span>
<el-input
v-else
v-model="scope.row.dictLabel"
size="mini"
style="width: 100%;"
@change="handleSaveRow(scope.row)"
auto-focus
/>
</template>
</el-table-column>
<!-- 字典值列kisv=true时标题合并 -->
<el-table-column :label="kisv ? '字典值/标签' : '字典值'" align="center">
<template #default="scope">
<!-- 核心默认文本双击才显示输入框失焦立刻消失 -->
<span
v-if="editRowId !== scope.row.dictCode"
@dblclick.stop="handleDbEdit(scope.row)"
style="cursor: pointer;"
>
{{ scope.row.dictValue }}
</span>
<el-input
v-else
v-model="scope.row.dictValue"
size="mini"
style="width: 100%;"
@input="() => handleKisvTableSync(scope.row)"
@change="handleSaveRow(scope.row)"
auto-focus
/>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="100">
<template #default="scope">
<el-button
icon="el-icon-delete"
size="mini"
type="text"
text-danger
@click="handleDelete(scope.row)"
:loading="delBtnLoading === scope.row.dictCode"
>删除</el-button>
</template>
</el-table-column>
</el-table>
</el-dialog>
</div>
</template>
<script>
import { getDicts, addData, updateData, delData, listData } from '@/api/system/dict/data'
import { listType } from '@/api/system/dict/type'
export default {
name: 'DictSelectEdit',
props: {
dictType: { type: String, default: '' },
editable: { type: Boolean, default: true },
kisv: { type: Boolean, default: false },
value: { type: String, default: '' },
placeholder: { type: String, default: '请选择' },
refresh: { type: Boolean, default: true },
},
data() {
return {
dictOptions: [],
dictId: '',
loading: false,
btnLoading: false,
delBtnLoading: '',
open: false,
editRowId: '', // 控制当前编辑行,为空则所有单元格都是文本状态
form: {
dictId: '',
dictLabel: '',
dictValue: '',
dictType: '',
sort: 0
},
dictRules: {
dictLabel: [{ required: true, message: '请输入字典标签', trigger: 'blur' }],
dictValue: [{ required: true, message: '请输入字典值', trigger: 'blur' }]
},
dictFormRef: null
}
},
computed: {
innerValue: {
get() { return this.value },
set(val) { this.$emit('input', val) }
}
},
watch: {
dictType: {
async handler(newVal) {
if (newVal) {
this.loading = true
try {
const dictId = await this.getDictId(newVal)
await this.getDictOptions(dictId)
} catch (err) {
console.error('加载字典失败:', err)
} finally {
this.loading = false
}
}
},
immediate: true
},
'form.dictValue': {
handler(val) {
if (this.kisv && val) this.form.dictLabel = val
},
immediate: true
}
},
methods: {
async getDictId(type) {
const res = await listType({ dictType: type })
if (res.rows?.length !== 1) {
this.$message.error('字典类型异常,未查询到对应配置')
return Promise.reject('字典类型异常')
}
this.dictId = res.rows[0].dictId
return this.dictId
},
// 新增:刷新字典数据
async handleRefresh() {
this.loading = true
try {
await this.getDictOptions(this.dictId)
} catch (err) {
console.error('刷新字典失败:', err)
} finally {
this.loading = false
}
},
async getDictOptions(dictId) {
const res = await listData({ dictType: this.dictType, pageSize: 1000 })
this.dictOptions = res.rows || []
return this.dictOptions
},
openDictDialog() {
this.open = true
this.resetDictForm()
this.form.dictId = this.dictId
this.form.dictType = this.dictType
this.editRowId = '' // 打开弹窗重置编辑状态
},
resetDictForm() {
this.form = { dictId: this.dictId, dictLabel: '', dictValue: '', dictType: this.dictType, sort: 0 }
this.$refs.dictFormRef && this.$refs.dictFormRef.clearValidate()
},
handleKisvTableSync(row) {
if (this.kisv && row.dictValue) row.dictLabel = row.dictValue
},
async submitAddDict() {
const valid = await this.$refs.dictFormRef.validate().catch(() => false)
if (!valid) return
this.loading = true
this.btnLoading = true
try {
await addData(this.form)
this.$message.success('字典项新增成功!')
await this.getDictOptions(this.dictId)
this.resetDictForm()
} catch (err) {
this.$message.error('新增失败,请稍后重试')
console.error(err)
} finally {
this.loading = false
this.btnLoading = false
}
},
// ✅ 新增:双击单元格 激活编辑状态 核心方法
handleDbEdit(row) {
// 同一时间只允许编辑一行,双击其他行关闭当前行编辑
this.editRowId = row.dictCode
},
// ✅ 核心完善:失去焦点/回车 保存数据 + 强制关闭编辑态 → 还原成普通单元格
async handleSaveRow(row) {
if (!row.dictLabel || !row.dictValue) {
this.$message.warning('字典标签和字典值不能为空!')
await this.getDictOptions(this.dictId)
this.editRowId = '' // 校验失败,也必须还原单元格
return
}
row.sort = 0
this.loading = true
try {
await updateData(row)
this.$message.success('字典项修改成功!')
} catch (err) {
this.$message.error('修改失败,请稍后重试')
await this.getDictOptions(this.dictId)
console.error(err)
} finally {
this.loading = false
this.editRowId = '' // ✅必加:保存完成,立刻关闭编辑态,变回文本
}
},
async handleDelete(row) {
const confirm = await this.$confirm('确定要删除该字典项吗?删除后不可恢复!', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).catch(() => false)
if (!confirm) return
this.loading = true
this.delBtnLoading = row.dictCode
try {
await delData(row.dictCode)
this.$message.success('删除成功!')
await this.getDictOptions(this.dictId)
} catch (err) {
this.$message.error('删除失败,请稍后重试')
console.error(err)
} finally {
this.loading = false
this.delBtnLoading = ''
}
}
}
}
</script>