Commit 6391ed84 by yubin

请假

parents de498718 3a9e709f
import axios from '@/libs/api.request'
// 使用统计
export const getUsageStats = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmStats/selectUsageStats',
method: 'post',
data: param
})
}
export const getUsageDetails = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmStats/selectUsageDetails',
method: 'post',
data: param
})
}
// 工作量统计
export const getWorkloadStats = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmStats/selectWorkloadStats',
method: 'post',
data: param
})
}
export const getWorkloadDetails = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmStats/selectWorkloadDetails',
method: 'post',
data: param
})
}
...@@ -27,10 +27,10 @@ export const saveDmUser = (param) => { ...@@ -27,10 +27,10 @@ export const saveDmUser = (param) => {
}) })
} }
// 分页查询日常人员可选上级领导列表 // 获取人员选择器列表(根据机构和权限过滤)
export const dmUserLeader = (param) => { export const getUserSelectorList = (param) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUser/dmUserLeader', url: '/api/ac/jilinsscgsdp/keyDmUser/selectUserSelectorList',
method: 'post', method: 'post',
data: param data: param
}) })
...@@ -48,6 +48,13 @@ export const dmUserOffice = (param) => { ...@@ -48,6 +48,13 @@ export const dmUserOffice = (param) => {
export const getUserTypeList = (param) => { export const getUserTypeList = (param) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategory/selectList', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/selectList',
})
}
// 获取人员多选器列表(所有在职人员)
export const getUserMultiSelectorList = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUser/selectUserMultiSelectorList',
method: 'post', method: 'post',
data: param data: param
}) })
......
import axios from '@/libs/api.request' import axios from '@/libs/api.request'
// ===== 人员分类管理 ===== // ===== 人员权限配置 =====
export const getUserCategoryList = (param) => { export const getPermissionConfigList = () => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategory/selectList', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/selectPermissionConfigList',
method: 'post', method: 'post'
data: param
})
}
export const saveUserCategory = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategory/save',
method: 'post',
data: param
}) })
} }
export const deleteUserCategory = (param) => { export const savePermissionUsers = (param) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategory/delete', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/savePermissionUsers',
method: 'post', method: 'post',
data: param data: param
}) })
} }
// ===== 人员分类权限管理 ===== // ===== 请假类型管理 =====
export const getUserCategoryPermissionList = (param) => { export const getLeaveTypeList = (param) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategoryPermission/selectList', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/selectLeaveTypeList',
method: 'post', method: 'post',
data: param data: param
}) })
} }
export const saveUserCategoryPermission = (param) => { export const saveLeaveType = (param) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategoryPermission/save', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/saveLeaveType',
method: 'post', method: 'post',
data: param data: param
}) })
} }
// ===== 请假类型管理 ===== export const deleteLeaveType = (param) => {
export const getLeaveTypeList = (param) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmLeaveType/selectList', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/deleteLeaveType',
method: 'post', method: 'post',
data: param data: param
}) })
} }
export const saveLeaveType = (param) => { export const findLeaveTypeList = (param) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmLeaveType/save', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/findLeaveTypeList',
method: 'post', method: 'post',
data: param data: param
}) })
} }
export const deleteLeaveType = (param) => { // ===== 办公用品分类管理 =====
export const getMaterialCategoryList = (param) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmLeaveType/delete', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/selectMaterialCategoryList',
method: 'post', method: 'post',
data: param data: param
}) })
} }
// ===== 办公用品分类管理 ===== export const saveMaterialCategory = (param) => {
export const getMaterialCategoryList = (param) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmMaterialCategory/selectList', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/saveMaterialCategory',
method: 'post', method: 'post',
data: param data: param
}) })
} }
export const saveMaterialCategory = (param) => { export const deleteMaterialCategory = (param) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmMaterialCategory/save', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/deleteMaterialCategory',
method: 'post', method: 'post',
data: param data: param
}) })
} }
export const deleteMaterialCategory = (param) => { export const findMaterialCategoryList = (param) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmMaterialCategory/delete', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/findMaterialCategoryList',
method: 'post', method: 'post',
data: param data: param
}) })
...@@ -95,7 +85,7 @@ export const deleteMaterialCategory = (param) => { ...@@ -95,7 +85,7 @@ export const deleteMaterialCategory = (param) => {
// ===== 办公用品管理 ===== // ===== 办公用品管理 =====
export const getMaterialList = (param) => { export const getMaterialList = (param) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmMaterial/selectList', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/selectMaterialList',
method: 'post', method: 'post',
data: param data: param
}) })
...@@ -103,7 +93,7 @@ export const getMaterialList = (param) => { ...@@ -103,7 +93,7 @@ export const getMaterialList = (param) => {
export const saveMaterial = (param) => { export const saveMaterial = (param) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmMaterial/save', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/saveMaterial',
method: 'post', method: 'post',
data: param data: param
}) })
...@@ -111,7 +101,7 @@ export const saveMaterial = (param) => { ...@@ -111,7 +101,7 @@ export const saveMaterial = (param) => {
export const deleteMaterial = (param) => { export const deleteMaterial = (param) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmMaterial/delete', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/deleteMaterial',
method: 'post', method: 'post',
data: param data: param
}) })
...@@ -120,7 +110,7 @@ export const deleteMaterial = (param) => { ...@@ -120,7 +110,7 @@ export const deleteMaterial = (param) => {
// 导入物料(Excel) // 导入物料(Excel)
export const importMaterial = (formData) => { export const importMaterial = (formData) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmMaterial/import', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/importMaterial',
method: 'post', method: 'post',
data: formData data: formData
}) })
...@@ -129,7 +119,42 @@ export const importMaterial = (formData) => { ...@@ -129,7 +119,42 @@ export const importMaterial = (formData) => {
// 下载物料导入模板 // 下载物料导入模板
export const materialTemplateDownload = (param) => { export const materialTemplateDownload = (param) => {
return axios.request({ return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmMaterial/templateDownload', url: '/api/ac/jilinsscgsdp/keyDmUserCategory/templateDownload',
method: 'post',
data: param
})
}
// --统计部分---------------------------------------------------------------------------------------------
// 使用统计
export const getUsageStats = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmStats/selectUsageStats',
method: 'post',
data: param
})
}
export const getUsageDetails = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmStats/selectUsageDetails',
method: 'post',
data: param
})
}
// 工作量统计
export const getWorkloadStats = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmStats/selectWorkloadStats',
method: 'post',
data: param
})
}
export const getWorkloadDetails = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmStats/selectWorkloadDetails',
method: 'post', method: 'post',
data: param data: param
}) })
......
/* eslint-disable */
export function normalizeVisitTimeValue (value) {
if (!value && value !== 0) return ''
if (value instanceof Date) {
return Number.isNaN(value.getTime()) ? '' : formatDateSegments(value)
}
if (typeof value === 'number' && !Number.isNaN(value)) {
const fromNumber = new Date(value)
return Number.isNaN(fromNumber.getTime()) ? '' : formatDateSegments(fromNumber)
}
if (typeof value === 'string') {
const trimmed = value.trim()
if (!trimmed) return ''
const direct = new Date(trimmed)
if (!Number.isNaN(direct.getTime())) return formatDateSegments(direct)
const withSlash = new Date(trimmed.replace(/-/g, '/'))
if (!Number.isNaN(withSlash.getTime())) return formatDateSegments(withSlash)
const match = trimmed.match(/^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2}))?)?$/)
if (match) {
const [, y, m, d, hh = '00', mm = '00', ss = '00'] = match
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
return ''
}
if (value && typeof value === 'object' && typeof value.valueOf === 'function') {
const timestamp = value.valueOf()
if (!Number.isNaN(timestamp)) {
const fromValue = new Date(timestamp)
return Number.isNaN(fromValue.getTime()) ? '' : formatDateSegments(fromValue)
}
}
return ''
}
function formatDateSegments (d) {
const y = d.getFullYear()
const mm = String(d.getMonth() + 1).padStart(2, '0')
const dd = String(d.getDate()).padStart(2, '0')
const HH = String(d.getHours()).padStart(2, '0')
const MM = String(d.getMinutes()).padStart(2, '0')
const SS = String(d.getSeconds()).padStart(2, '0')
return `${y}-${mm}-${dd} ${HH}:${MM}:${SS}`
}
<template> <template>
<div class="key-dm-wrapper"> <div class="key-dm-wrapper">
<Tabs v-model="activeTab" @on-click="handleTabChange"> <Tabs v-model="activeTab" @on-click="handleTabChange">
<!-- 人员分类管理 --> <!-- 人员权限配置 -->
<TabPane label="人员分类管理" name="userCategory"> <TabPane label="人员权限配置" name="permissionConfig">
<div class="search-div"> <Table border :loading="loading.permissionConfig" :columns="permissionConfigColumns" :data="tables.permissionConfig">
<Row type="flex" :gutter="16">
<Col span="6">
<span>分类名称:</span>
<Input v-model="filters.userCategory.catgory_name" placeholder="请输入" style="width: 70%" />
</Col>
<Col span="12" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('userCategory')">搜索</Button>
<Button class="mr10" @click="handleReset('userCategory')">重置</Button>
<Button type="success" @click="openAddModal('userCategory')">新增</Button>
</Col>
</Row>
</div>
<Table border :loading="loading.userCategory" :columns="userCategoryColumns" :data="tables.userCategory">
<template slot="action" slot-scope="{ row }"> <template slot="action" slot-scope="{ row }">
<Button size="small" type="primary" class="mr5" @click="openEditModal('userCategory', row)">修改</Button> <Button size="small" type="primary" @click="openUserConfigModal(row)">配置人员</Button>
<Button size="small" type="warning" class="mr5" @click="openPermissionModal(row)">权限配置</Button>
<Poptip confirm title="确认删除?" transfer @on-ok="handleDelete('userCategory', row)">
<Button size="small" type="error">删除</Button>
</Poptip>
</template> </template>
</Table> </Table>
<Page
class="page_style"
:total="pagers.userCategory.totalRecord"
:current="pagers.userCategory.pageNo"
:page-size="pagers.userCategory.pageSize"
show-total
show-sizer
@on-change="pageChange('userCategory', $event)"
@on-page-size-change="sizeChange('userCategory', $event)"
/>
</TabPane> </TabPane>
<!-- 假种管理 --> <!-- 假种管理 -->
<TabPane label="假种管理" name="leaveType"> <TabPane label="假种管理" name="leaveType">
<div class="search-div"> <div class="search-div">
...@@ -51,8 +23,8 @@ ...@@ -51,8 +23,8 @@
</Col> </Col>
<Col span="12" class="text-right"> <Col span="12" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('leaveType')">搜索</Button> <Button type="primary" class="mr10" @click="handleSearch('leaveType')">搜索</Button>
<Button class="mr10" @click="handleReset('leaveType')">重置</Button> <Button type="primary" class="mr10" @click="handleReset('leaveType')">重置</Button>
<Button type="success" @click="openAddModal('leaveType')">新增</Button> <Button type="primary" @click="openAddModal('leaveType')">新增</Button>
</Col> </Col>
</Row> </Row>
</div> </div>
...@@ -82,16 +54,16 @@ ...@@ -82,16 +54,16 @@
<Row type="flex" :gutter="16"> <Row type="flex" :gutter="16">
<Col span="6"> <Col span="6">
<span>分类名称:</span> <span>分类名称:</span>
<Input v-model="filters.materialCategory.category_Name" placeholder="请输入" style="width: 70%" /> <Input v-model="filters.materialCategory.category_name" placeholder="请输入" style="width: 70%" />
</Col> </Col>
<Col span="6"> <Col span="6">
<span>分类编码:</span> <span>分类编码:</span>
<Input v-model="filters.materialCategory.category_Code" placeholder="请输入" style="width: 70%" /> <Input v-model="filters.materialCategory.category_code" placeholder="请输入" style="width: 70%" />
</Col> </Col>
<Col span="12" class="text-right"> <Col span="12" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('materialCategory')">搜索</Button> <Button type="primary" class="mr10" @click="handleSearch('materialCategory')">搜索</Button>
<Button class="mr10" @click="handleReset('materialCategory')">重置</Button> <Button type="primary" class="mr10" @click="handleReset('materialCategory')">重置</Button>
<Button type="success" @click="openAddModal('materialCategory')">新增</Button> <Button type="primary" @click="openAddModal('materialCategory')">新增</Button>
</Col> </Col>
</Row> </Row>
</div> </div>
...@@ -120,23 +92,23 @@ ...@@ -120,23 +92,23 @@
<div class="search-div"> <div class="search-div">
<Row type="flex" :gutter="16"> <Row type="flex" :gutter="16">
<Col span="6"> <Col span="6">
<span>物料名称:</span> <span>名称:</span>
<Input v-model="filters.material.material_name" placeholder="请输入" style="width: 70%" /> <Input v-model="filters.material.material_name" placeholder="请输入" style="width: 70%" />
</Col> </Col>
<Col span="6"> <Col span="6">
<span>物料编码:</span> <span>编码:</span>
<Input v-model="filters.material.material_code" placeholder="请输入" style="width: 70%" /> <Input v-model="filters.material.material_code" placeholder="请输入" style="width: 70%" />
</Col> </Col>
<Col span="6"> <Col span="6">
<span>分类:</span> <span>分类:</span>
<Select v-model="filters.material.category_id" clearable style="width: 70%"> <Select v-model="filters.material.category_id" clearable style="width: 70%">
<Option v-for="cat in materialCategoryOptions" :key="cat.id" :value="cat.id">{{ cat.category_Name }}</Option> <Option v-for="cat in materialCategoryOptions" :key="cat.id" :value="cat.id">{{ cat.category_name }}</Option>
</Select> </Select>
</Col> </Col>
<Col span="6" class="text-right"> <Col span="6" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('material')">搜索</Button> <Button type="primary" class="mr10" @click="handleSearch('material')">搜索</Button>
<Button class="mr10" @click="handleReset('material')">重置</Button> <Button type="primary" class="mr10" @click="handleReset('material')">重置</Button>
<Button type="success" @click="openAddModal('material')">新增</Button> <Button type="primary" class="mr10" @click="openAddModal('material')">新增</Button>
<Button type="primary" class="mr10" v-if="showImport()" @click="importShow = true">导入</Button> <Button type="primary" class="mr10" v-if="showImport()" @click="importShow = true">导入</Button>
</Col> </Col>
</Row> </Row>
...@@ -162,30 +134,13 @@ ...@@ -162,30 +134,13 @@
</TabPane> </TabPane>
</Tabs> </Tabs>
<!-- 人员分类管理弹窗 -->
<Modal v-model="modals.userCategory.visible" :title="modals.userCategory.isEdit ? '修改人员分类' : '新增人员分类'" width="600" :mask-closable="false">
<Form :label-width="120" :model="modals.userCategory.form" :rules="modals.userCategory.rules" ref="userCategoryForm">
<FormItem label="分类名称" prop="catgory_name">
<Input v-model="modals.userCategory.form.catgory_name" placeholder="请输入分类名称" />
</FormItem>
<FormItem label="描述" prop="remark">
<Input type="textarea" :rows="3" v-model="modals.userCategory.form.remark" placeholder="请输入描述" />
</FormItem>
<FormItem label="排序号" prop="order_no">
<InputNumber v-model="modals.userCategory.form.order_no" :min="0" style="width: 100%" />
</FormItem>
</Form>
<div slot="footer">
<Button @click="modals.userCategory.visible = false">取消</Button>
<Button type="primary" :loading="modals.userCategory.saving" @click="handleSave('userCategory')">保存</Button>
</div>
</Modal>
<!-- 导入物料弹窗 --> <!-- 导入物料弹窗 -->
<Modal v-model="importShow" title="物料导入" width="360"> <Modal v-model="importShow" title="物料导入" width="360">
<Row type="flex" justify="center" align="middle"> <Row type="flex" justify="center" align="middle">
<Col span="10"> <Col span="10">
<div style="text-align: center;"> <div style="text-align: center;">
<Upload <Upload
action="#"
:show-upload-list="false" :show-upload-list="false"
:before-upload="handleBeforeUpload" :before-upload="handleBeforeUpload"
:format="['xls','xlsx']" :format="['xls','xlsx']"
...@@ -261,11 +216,11 @@ ...@@ -261,11 +216,11 @@
<!-- 办公用品分类管理弹窗 --> <!-- 办公用品分类管理弹窗 -->
<Modal v-model="modals.materialCategory.visible" :title="modals.materialCategory.isEdit ? '修改办公用品分类' : '新增办公用品分类'" width="600" :mask-closable="false"> <Modal v-model="modals.materialCategory.visible" :title="modals.materialCategory.isEdit ? '修改办公用品分类' : '新增办公用品分类'" width="600" :mask-closable="false">
<Form :label-width="120" :model="modals.materialCategory.form" :rules="modals.materialCategory.rules" ref="materialCategoryForm"> <Form :label-width="120" :model="modals.materialCategory.form" :rules="modals.materialCategory.rules" ref="materialCategoryForm">
<FormItem label="分类编码" prop="category_Code"> <FormItem label="分类编码" prop="category_code">
<Input v-model="modals.materialCategory.form.category_Code" placeholder="请输入分类编码" /> <Input v-model="modals.materialCategory.form.category_code" placeholder="请输入分类编码" />
</FormItem> </FormItem>
<FormItem label="分类名称" prop="category_Name"> <FormItem label="分类名称" prop="category_name">
<Input v-model="modals.materialCategory.form.category_Name" placeholder="请输入分类名称" /> <Input v-model="modals.materialCategory.form.category_name" placeholder="请输入分类名称" />
</FormItem> </FormItem>
<FormItem label="分类描述" prop="remark"> <FormItem label="分类描述" prop="remark">
<Input type="textarea" :rows="3" v-model="modals.materialCategory.form.remark" placeholder="请输入分类描述" /> <Input type="textarea" :rows="3" v-model="modals.materialCategory.form.remark" placeholder="请输入分类描述" />
...@@ -287,20 +242,20 @@ ...@@ -287,20 +242,20 @@
<Col span="12"> <Col span="12">
<FormItem label="分类" prop="category_id"> <FormItem label="分类" prop="category_id">
<Select v-model="modals.material.form.category_id" placeholder="请选择分类" style="width: 100%"> <Select v-model="modals.material.form.category_id" placeholder="请选择分类" style="width: 100%">
<Option v-for="cat in materialCategoryOptions" :key="cat.id" :value="cat.id">{{ cat.category_Name }}</Option> <Option v-for="cat in materialCategoryOptions" :key="cat.id" :value="cat.id">{{ cat.category_name }}</Option>
</Select> </Select>
</FormItem> </FormItem>
</Col> </Col>
<Col span="12"> <Col span="12">
<FormItem label="物料编码" prop="material_code"> <FormItem label="编码" prop="material_code">
<Input v-model="modals.material.form.material_code" placeholder="请输入物料编码" /> <Input v-model="modals.material.form.material_code" placeholder="请输入编码" />
</FormItem> </FormItem>
</Col> </Col>
</Row> </Row>
<Row :gutter="16"> <Row :gutter="16">
<Col span="12"> <Col span="12">
<FormItem label="物料名称" prop="material_name"> <FormItem label="名称" prop="material_name">
<Input v-model="modals.material.form.material_name" placeholder="请输入物料名称" /> <Input v-model="modals.material.form.material_name" placeholder="请输入名称" />
</FormItem> </FormItem>
</Col> </Col>
<Col span="12"> <Col span="12">
...@@ -328,7 +283,7 @@ ...@@ -328,7 +283,7 @@
</FormItem> </FormItem>
</Col> </Col>
<Col span="12"> <Col span="12">
<FormItem label="物料状态" prop="status"> <FormItem label="状态" prop="status">
<Select v-model="modals.material.form.status" style="width: 100%"> <Select v-model="modals.material.form.status" style="width: 100%">
<Option :value="0">报废</Option> <Option :value="0">报废</Option>
<Option :value="1">使用</Option> <Option :value="1">使用</Option>
...@@ -364,6 +319,13 @@ ...@@ -364,6 +319,13 @@
</FormItem> </FormItem>
</Col> </Col>
</Row> </Row>
<Row :gutter="16">
<Col span="24">
<FormItem label="供应商" prop="supplier_name">
<Input v-model="modals.material.form.supplier_name" placeholder="请输入供应商" style="width: 100%" />
</FormItem>
</Col>
</Row>
<FormItem label="物料描述" prop="material_desc"> <FormItem label="物料描述" prop="material_desc">
<Input type="textarea" :rows="3" v-model="modals.material.form.material_desc" placeholder="请输入物料描述" /> <Input type="textarea" :rows="3" v-model="modals.material.form.material_desc" placeholder="请输入物料描述" />
</FormItem> </FormItem>
...@@ -374,31 +336,37 @@ ...@@ -374,31 +336,37 @@
</div> </div>
</Modal> </Modal>
<!-- 权限配置弹窗 --> <!-- 人员权限配置弹窗 -->
<Modal v-model="permissionModal.visible" title="权限配置" width="600" :mask-closable="false"> <Modal v-model="userConfigModal.visible" title="人员权限配置" width="800" :mask-closable="false">
<Form :label-width="120"> <div style="margin-bottom: 16px;">
<FormItem label="分类名称"> <span style="font-weight: bold;">权限:</span>{{ userConfigModal.permissionName }}
<Input :value="permissionModal.categoryName" disabled /> </div>
</FormItem> <div style="margin-bottom: 16px;">
<FormItem label="权限配置"> <span style="font-weight: bold;">已配置人员:</span>
<Select v-model="permissionModal.selectedPermissions" multiple clearable filterable placeholder="请选择权限"> <div style="margin-top: 8px;">
<Option v-for="opt in permissionOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</Option> <Tag v-for="user in userConfigModal.selectedUsers" :key="user.user_id" closable @on-close="removeUser(user)">
</Select> {{ user.user_name }}
</FormItem> </Tag>
</Form> </div>
</div>
<div slot="footer"> <div slot="footer">
<Button @click="permissionModal.visible = false">取消</Button> <Button @click="userConfigModal.visible = false">取消</Button>
<Button type="primary" :loading="permissionModal.saving" @click="savePermission">保存</Button> <Button type="primary" @click="addUsers">添加人员</Button>
<Button type="primary" :loading="userConfigModal.saving" @click="saveUserConfig">保存</Button>
</div> </div>
</Modal> </Modal>
<!-- 人员选择器 -->
<UserMultiSelector
v-model="userSelectorVisible"
@on-ok="handleUserSelectorOk"
@cancel="userSelectorVisible = false" />
</div> </div>
</template> </template>
<script> <script>
import { import {
getUserCategoryList,
saveUserCategory,
deleteUserCategory,
getLeaveTypeList, getLeaveTypeList,
saveLeaveType, saveLeaveType,
deleteLeaveType, deleteLeaveType,
...@@ -408,57 +376,43 @@ import { ...@@ -408,57 +376,43 @@ import {
getMaterialList, getMaterialList,
saveMaterial, saveMaterial,
deleteMaterial, deleteMaterial,
getUserCategoryPermissionList,
saveUserCategoryPermission,
importMaterial, importMaterial,
materialTemplateDownload getPermissionConfigList,
savePermissionUsers
} from '@/api/key-dm' } from '@/api/key-dm'
import { getDictList } from '@/api/common' import axios from 'axios'
import UserMultiSelector from '@/view/key-person/key_dm_user/userMultiSelector.vue'
export default { export default {
name: 'key-dm-index', name: 'key-dm-index',
components: { UserMultiSelector },
data () { data () {
return { return {
activeTab: 'userCategory', activeTab: 'permissionConfig',
filters: { filters: {
userCategory: { catgory_name: '' },
leaveType: { type_name: '', type_code: '' }, leaveType: { type_name: '', type_code: '' },
materialCategory: { category_Name: '', category_Code: '' }, materialCategory: { category_name: '', category_code: '' },
material: { material_name: '', material_code: '', category_id: '' } material: { material_name: '', material_code: '', category_id: '' }
}, },
tables: { tables: {
userCategory: [], permissionConfig: [],
leaveType: [], leaveType: [],
materialCategory: [], materialCategory: [],
material: [] material: []
}, },
loading: { loading: {
userCategory: false, permissionConfig: false,
leaveType: false, leaveType: false,
materialCategory: false, materialCategory: false,
material: false material: false
}, },
pagers: { pagers: {
userCategory: { pageNo: 1, pageSize: 10, totalRecord: 0 }, permissionConfig: { pageNo: 1, pageSize: 10, totalRecord: 0 },
leaveType: { pageNo: 1, pageSize: 10, totalRecord: 0 }, leaveType: { pageNo: 1, pageSize: 10, totalRecord: 0 },
materialCategory: { pageNo: 1, pageSize: 10, totalRecord: 0 }, materialCategory: { pageNo: 1, pageSize: 10, totalRecord: 0 },
material: { pageNo: 1, pageSize: 10, totalRecord: 0 } material: { pageNo: 1, pageSize: 10, totalRecord: 0 }
}, },
modals: { modals: {
userCategory: {
visible: false,
isEdit: false,
saving: false,
form: {
id: '',
catgory_name: '',
remark: '',
order_no: 0
},
rules: {
catgory_name: [{ required: true, message: '请输入分类名称', trigger: 'blur' }]
}
},
leaveType: { leaveType: {
visible: false, visible: false,
isEdit: false, isEdit: false,
...@@ -484,14 +438,14 @@ export default { ...@@ -484,14 +438,14 @@ export default {
saving: false, saving: false,
form: { form: {
id: '', id: '',
category_Code: '', category_code: '',
category_Name: '', category_name: '',
remark: '', remark: '',
order_no: 0 order_no: 0
}, },
rules: { rules: {
category_Code: [{ required: true, message: '请输入分类编码', trigger: 'blur' }], category_code: [{ required: true, message: '请输入分类编码', trigger: 'blur' }],
category_Name: [{ required: true, message: '请输入分类名称', trigger: 'blur' }] category_name: [{ required: true, message: '请输入分类名称', trigger: 'blur' }]
} }
}, },
material: { material: {
...@@ -520,25 +474,17 @@ export default { ...@@ -520,25 +474,17 @@ export default {
} }
} }
}, },
permissionModal: { userConfigModal: {
visible: false, visible: false,
saving: false, saving: false,
categoryId: '', permissionCode: '',
categoryName: '', permissionName: '',
selectedPermissions: [] selectedUsers: []
}, },
userSelectorVisible: false,
importShow: false, importShow: false,
impBtnDisabled: false, impBtnDisabled: false,
permissionOptions: [],
materialCategoryOptions: [], materialCategoryOptions: [],
userCategoryColumns: [
{ type: 'index', title: '序号', width: 60, align: 'center' },
{ title: '分类名称', key: 'catgory_name', align: 'center' },
{ title: '描述', key: 'remark', align: 'center' },
{ title: '权限', key: 'permission_names', align: 'center', minWidth: 200 },
{ title: '排序号', key: 'order_no', align: 'center', width: 100 },
{ title: '操作', slot: 'action', align: 'center', width: 250, fixed: 'right' }
],
leaveTypeColumns: [ leaveTypeColumns: [
{ type: 'index', title: '序号', width: 60, align: 'center' }, { type: 'index', title: '序号', width: 60, align: 'center' },
{ title: '类型编码', key: 'type_code', align: 'center' }, { title: '类型编码', key: 'type_code', align: 'center' },
...@@ -550,20 +496,21 @@ export default { ...@@ -550,20 +496,21 @@ export default {
], ],
materialCategoryColumns: [ materialCategoryColumns: [
{ type: 'index', title: '序号', width: 60, align: 'center' }, { type: 'index', title: '序号', width: 60, align: 'center' },
{ title: '分类编码', key: 'category_Code', align: 'center' }, { title: '分类编码', key: 'category_code', align: 'center' },
{ title: '分类名称', key: 'category_Name', align: 'center' }, { title: '分类名称', key: 'category_name', align: 'center' },
{ title: '分类描述', key: 'remark', align: 'center' }, { title: '分类描述', key: 'remark', align: 'center' },
{ title: '排序号', key: 'order_no', align: 'center', width: 100 }, { title: '排序号', key: 'order_no', align: 'center', width: 100 },
{ title: '操作', slot: 'action', align: 'center', width: 180, fixed: 'right' } { title: '操作', slot: 'action', align: 'center', width: 180, fixed: 'right' }
], ],
materialColumns: [ materialColumns: [
{ type: 'index', title: '序号', width: 60, align: 'center' }, { type: 'index', title: '序号', width: 60, align: 'center' },
{ title: '分类', key: 'category_name', align: 'center' }, { title: '分类', key: 'category_name', minwidth: 120, align: 'center' },
{ title: '物料编码', key: 'material_code', align: 'center' }, { title: '物料编码', key: 'material_code', minwidth: 120, align: 'center' },
{ title: '物料名称', key: 'material_name', align: 'center' }, { title: '物料名称', key: 'material_name', minwidth: 180, align: 'center' },
{ title: '规格型号', key: 'material_spec', align: 'center' }, { title: '规格型号', key: 'material_spec', minwidth: 100, align: 'center' },
{ title: '单位', key: 'unit', align: 'center', width: 80 }, { title: '单位', key: 'unit', align: 'center', minwidth: 80 },
{ title: '单价', key: 'unit_price', align: 'center', width: 100 }, { title: '单价', key: 'unit_price', align: 'center', minwidth: 100 },
{ title: '供应商', key: 'supplier_name', align: 'center', minwidth: 120 },
{ title: '物料状态', { title: '物料状态',
key: 'status', key: 'status',
align: 'center', align: 'center',
...@@ -573,22 +520,32 @@ export default { ...@@ -573,22 +520,32 @@ export default {
return h('span', statusMap[row.status] || '-') return h('span', statusMap[row.status] || '-')
} }, } },
{ title: '操作', slot: 'action', align: 'center', width: 180, fixed: 'right' } { title: '操作', slot: 'action', align: 'center', width: 180, fixed: 'right' }
],
permissionConfigColumns: [
{ type: 'index', title: '序号', width: 60, align: 'center' },
{ title: '权限名称', key: 'permission_name', align: 'center', minWidth: 150 },
{ title: '配置人员', key: 'user_names', align: 'center', minWidth: 300 },
{ title: '操作', slot: 'action', align: 'center', width: 120, fixed: 'right' }
] ]
} }
}, },
created () { created () {
this.loadPermissionDict()
this.loadMaterialCategoryOptions() this.loadMaterialCategoryOptions()
this.loadPermissionConfig()
this.fetchList(this.activeTab) this.fetchList(this.activeTab)
}, },
methods: { methods: {
handleTabChange (name) { handleTabChange (name) {
this.activeTab = name this.activeTab = name
if (name === 'permissionConfig') {
this.loadPermissionConfig()
} else {
this.fetchList(name) this.fetchList(name)
}
}, },
fetchList (tab) { fetchList (tab) {
const apiMap = { const apiMap = {
userCategory: getUserCategoryList, permissionConfig: () => Promise.resolve({ data: { errcode: 0, data: [] } }),
leaveType: getLeaveTypeList, leaveType: getLeaveTypeList,
materialCategory: getMaterialCategoryList, materialCategory: getMaterialCategoryList,
material: getMaterialList material: getMaterialList
...@@ -601,27 +558,6 @@ export default { ...@@ -601,27 +558,6 @@ export default {
if (ret.data && ret.data.errcode === 0) { if (ret.data && ret.data.errcode === 0) {
const data = ret.data.data || {} const data = ret.data.data || {}
this.tables[tab] = data.results || [] this.tables[tab] = data.results || []
// 如果是人员分类,加载每行的权限名称并拼接显示
if (tab === 'userCategory' && Array.isArray(this.tables[tab]) && this.tables[tab].length > 0) {
const rows = this.tables[tab]
// 并行查询每个分类的权限配置(可优化为批量接口)
const promises = rows.map(r => {
return getUserCategoryPermissionList({ category_id: r.id }).then(res => {
let names = ''
if (res.data && res.data.errcode === 0) {
const list = res.data.data || res.data.results || []
names = (Array.isArray(list) ? list.map(it => it.permission_name).filter(Boolean) : []).join(',')
}
// 确保响应式设置字段
this.$set(r, 'permission_names', names)
return r
}).catch(() => {
this.$set(r, 'permission_names', '')
return r
})
})
Promise.all(promises).then(() => { /* table updated */ })
}
this.pagers[tab].totalRecord = data.totalRecord || 0 this.pagers[tab].totalRecord = data.totalRecord || 0
} else { } else {
this.$Notice.error({ title: '查询失败', desc: ret.data.errmsg || '请稍后重试' }) this.$Notice.error({ title: '查询失败', desc: ret.data.errmsg || '请稍后重试' })
...@@ -634,9 +570,9 @@ export default { ...@@ -634,9 +570,9 @@ export default {
}, },
handleReset (tab) { handleReset (tab) {
const resetMap = { const resetMap = {
userCategory: () => ({ catgory_name: '' }), permissionConfig: () => ({}),
leaveType: () => ({ type_name: '', type_code: '' }), leaveType: () => ({ type_name: '', type_code: '' }),
materialCategory: () => ({ category_Name: '', category_Code: '' }), materialCategory: () => ({ category_name: '', category_code: '' }),
material: () => ({ material_name: '', material_code: '', category_id: '' }) material: () => ({ material_name: '', material_code: '', category_id: '' })
} }
this.filters[tab] = resetMap[tab]() this.filters[tab] = resetMap[tab]()
...@@ -670,12 +606,6 @@ export default { ...@@ -670,12 +606,6 @@ export default {
}, },
getDefaultForm (tab) { getDefaultForm (tab) {
const defaults = { const defaults = {
userCategory: {
id: '',
catgory_name: '',
remark: '',
order_no: 0
},
leaveType: { leaveType: {
id: '', id: '',
type_code: '', type_code: '',
...@@ -688,8 +618,8 @@ export default { ...@@ -688,8 +618,8 @@ export default {
}, },
materialCategory: { materialCategory: {
id: '', id: '',
category_Code: '', category_code: '',
category_Name: '', category_name: '',
remark: '', remark: '',
order_no: 0 order_no: 0
}, },
...@@ -720,7 +650,6 @@ export default { ...@@ -720,7 +650,6 @@ export default {
if (!valid) return if (!valid) return
modal.saving = true modal.saving = true
const saveApiMap = { const saveApiMap = {
userCategory: saveUserCategory,
leaveType: saveLeaveType, leaveType: saveLeaveType,
materialCategory: saveMaterialCategory, materialCategory: saveMaterialCategory,
material: saveMaterial material: saveMaterial
...@@ -731,6 +660,10 @@ export default { ...@@ -731,6 +660,10 @@ export default {
this.$Message.success('保存成功') this.$Message.success('保存成功')
modal.visible = false modal.visible = false
this.fetchList(tab) this.fetchList(tab)
// 如果是办公用品分类管理操作成功,刷新分类选项
if (tab === 'materialCategory') {
this.loadMaterialCategoryOptions()
}
} else { } else {
this.$Notice.error({ title: '保存失败', desc: ret.data.errmsg || '请稍后重试' }) this.$Notice.error({ title: '保存失败', desc: ret.data.errmsg || '请稍后重试' })
} }
...@@ -739,7 +672,6 @@ export default { ...@@ -739,7 +672,6 @@ export default {
}, },
handleDelete (tab, row) { handleDelete (tab, row) {
const deleteApiMap = { const deleteApiMap = {
userCategory: deleteUserCategory,
leaveType: deleteLeaveType, leaveType: deleteLeaveType,
materialCategory: deleteMaterialCategory, materialCategory: deleteMaterialCategory,
material: deleteMaterial material: deleteMaterial
...@@ -749,61 +681,12 @@ export default { ...@@ -749,61 +681,12 @@ export default {
if (ret.data && ret.data.errcode === 0) { if (ret.data && ret.data.errcode === 0) {
this.$Message.success('删除成功') this.$Message.success('删除成功')
this.fetchList(tab) this.fetchList(tab)
} else { // 如果是办公用品分类管理删除成功,刷新分类选项
this.$Notice.error({ title: '删除失败', desc: ret.data.errmsg || '请稍后重试' }) if (tab === 'materialCategory') {
} this.loadMaterialCategoryOptions()
})
},
openPermissionModal (row) {
this.permissionModal.visible = true
this.permissionModal.categoryId = row.id
this.permissionModal.categoryName = row.catgory_name
this.permissionModal.selectedPermissions = []
// 加载已有权限
getUserCategoryPermissionList({ category_id: row.id }).then(ret => {
if (ret.data && ret.data.errcode === 0) {
const list = ret.data.data || ret.data.results || []
this.permissionModal.selectedPermissions = list.map(item => item.permission_mark).filter(Boolean)
}
})
},
savePermission () {
if (!this.permissionModal.categoryId) {
this.$Message.warning('分类ID不存在')
return
}
this.permissionModal.saving = true
const permissions = Array.isArray(this.permissionModal.selectedPermissions) ? this.permissionModal.selectedPermissions : []
const permissionList = permissions.map(mark => {
const opt = this.permissionOptions.find(p => p.value === mark)
return {
category_id: this.permissionModal.categoryId,
permission_mark: mark,
permission_name: opt ? opt.label : mark
} }
})
saveUserCategoryPermission({
category_id: this.permissionModal.categoryId,
permissions: permissionList
}).then(ret => {
if (ret.data && ret.data.errcode === 0) {
this.$Message.success('保存成功')
this.permissionModal.visible = false
this.fetchList('userCategory')
} else { } else {
this.$Notice.error({ title: '保存失败', desc: ret.data.errmsg || '请稍后重试' }) this.$Notice.error({ title: '删除失败', desc: ret.data.errmsg || '请稍后重试' })
}
}).finally(() => { this.permissionModal.saving = false })
},
loadPermissionDict () {
// 从字典获取权限选项,字典类型为 daily_manage_dict_permission
getDictList({ type: 'daily_manage_dict_permission' }).then(res => {
if (res.data && res.data.errcode === 0) {
const results = res.data.data && res.data.data.results ? res.data.data.results : []
this.permissionOptions = results.map(it => ({
label: it.label || it.name || '',
value: it.value || it.dictValue || ''
})).filter(it => it.label && it.value)
} }
}) })
}, },
...@@ -816,26 +699,104 @@ export default { ...@@ -816,26 +699,104 @@ export default {
const raw = data.results || [] const raw = data.results || []
// 规范化后端字段名,确保 id 字段为小写 id,以便 Select v-model 绑定正常工作 // 规范化后端字段名,确保 id 字段为小写 id,以便 Select v-model 绑定正常工作
this.materialCategoryOptions = Array.isArray(raw) ? raw.map(it => ({ this.materialCategoryOptions = Array.isArray(raw) ? raw.map(it => ({
id: (it.Id || it.id || it.category_Code || '').toString(), id: (it.id || it.id || it.category_code || '').toString(),
category_Name: (it.category_Name || it.categoryName || it.category_Code || '') category_name: (it.category_name || it.categoryName || it.category_code || '')
})) : [] })) : []
} }
}) })
}, },
tplDownload () { loadPermissionConfig () {
// 下载物料导入模板 // 从字典获取权限配置数据,并加载对应的用户配置
materialTemplateDownload({}).then(ret => { this.loading.permissionConfig = true
if (ret && ret.data && ret.data.errcode === 0) { getPermissionConfigList().then(ret => {
// const data = ret.data.data if (ret.data && ret.data.errcode === 0) {
// 如果后端直接返回文件流需要采用 axios blob 下载,这里假设返回 url 或 blob handled by backend this.tables.permissionConfig = ret.data.data || []
// 简单提示或可实现下载逻辑
this.$Notice.success({ title: '模板已准备,请在后台下载' })
} else { } else {
this.$Notice.error({ title: '模板下载失败', desc: ret.data && ret.data.errmsg }) this.$Notice.error({ title: '加载失败', desc: ret.data && ret.data.errmsg })
}
}).finally(() => { this.loading.permissionConfig = false })
},
openUserConfigModal (row) {
this.userConfigModal.visible = true
this.userConfigModal.permissionCode = row.permission_code
this.userConfigModal.permissionName = row.permission_name
this.userConfigModal.selectedUsers = row.user_names ? (JSON.parse(row.users) || []) : []
console.log('this.userConfigModal', this.userConfigModal)
},
addUsers () {
this.userSelectorVisible = true
},
handleUserSelectorOk (selectedUsers) {
// 将新选择的用户添加到已选用户列表中,避免重复
const existingIds = this.userConfigModal.selectedUsers.map(u => u.user_id)
const newUsers = selectedUsers.filter(u => !existingIds.includes(u.id)).map(u => ({
user_id: u.id,
user_name: u.name,
gh: u.gh
}))
this.userConfigModal.selectedUsers = [...this.userConfigModal.selectedUsers, ...newUsers]
this.userSelectorVisible = false
},
removeUser (user) {
this.userConfigModal.selectedUsers = this.userConfigModal.selectedUsers.filter(u => u.user_id !== user.user_id)
},
saveUserConfig () {
this.userConfigModal.saving = true
const userIds = this.userConfigModal.selectedUsers.map(u => u.user_id)
savePermissionUsers({
permission_code: this.userConfigModal.permissionCode,
user_ids: userIds
}).then(ret => {
if (ret.data && ret.data.errcode === 0) {
this.$Message.success('保存成功')
this.userConfigModal.visible = false
this.loadPermissionConfig()
} else {
this.$Notice.error({ title: '保存失败', desc: ret.data && ret.data.errmsg })
}
}).finally(() => { this.userConfigModal.saving = false })
},
// tplDownload () {
// // 下载物料导入模板
// materialTemplateDownload({}).then(ret => {
// if (ret && ret.data && ret.data.errcode === 0) {
// // const data = ret.data.data
// // 如果后端直接返回文件流需要采用 axios blob 下载,这里假设返回 url 或 blob handled by backend
// // 简单提示或可实现下载逻辑
// this.$Notice.success({ title: '模板已准备,请在后台下载' })
// } else {
// this.$Notice.error({ title: '模板下载失败', desc: ret.data && ret.data.errmsg })
// }
// }).catch(() => {
// this.$Notice.error({ title: '模板下载失败' })
// })
// },
async tplDownload () {
// 下载物料导入模板
try {
const response = await axios.post(
'/api/ac/jilinsscgsdp/keyDmUserCategory/templateDownload',
{},
{
responseType: 'blob'
}
)
const url = window.URL.createObjectURL(new Blob([response.data]))
// 创建隐藏的a标签并设置属性
const link = document.createElement('a')
link.href = url
link.download = '办公用品导入模板.xlsx' // 自定义下载文件名和扩展名
link.style.display = 'none'
document.body.appendChild(link)
// 触发点击下载
link.click()
// 清理
document.body.removeChild(link)
window.URL.revokeObjectURL(url)
} catch (error) {
console.error('下载失败:', error)
// 可以在这里添加错误提示
} }
}).catch(() => {
this.$Notice.error({ title: '模板下载失败' })
})
}, },
handleBeforeUpload (file) { handleBeforeUpload (file) {
const fileExt = file.name.split('.').pop().toLocaleLowerCase() const fileExt = file.name.split('.').pop().toLocaleLowerCase()
...@@ -899,6 +860,7 @@ export default { ...@@ -899,6 +860,7 @@ export default {
<style scoped> <style scoped>
.key-dm-wrapper { .key-dm-wrapper {
padding: 10px; padding: 10px;
min-height: 80vh;
} }
.search-div { .search-div {
border: 1px solid #dce1e7; border: 1px solid #dce1e7;
......
...@@ -23,14 +23,7 @@ ...@@ -23,14 +23,7 @@
</Row> </Row>
</div> </div>
<Table :data="rows" :loading="loading" @on-selection-change="onSelectionChange" border> <Table :data="rows" :loading="loading" :columns="columns" @on-selection-change="onSelectionChange" border />
<TableColumn type="selection" width="60"></TableColumn>
<TableColumn prop="material_code" title="物料编码" align="center" />
<TableColumn prop="material_name" title="物料名称" align="center" />
<TableColumn prop="unit" title="单位" align="center" width="80" />
<TableColumn prop="available_quantity" title="可用库存" align="center" width="120" />
<TableColumn prop="category_Name" title="分类" align="center" />
</Table>
<Page class="page_style" :total="pager.totalRecord" :current="pager.pageNo" :page-size="pager.pageSize" show-total show-sizer <Page class="page_style" :total="pager.totalRecord" :current="pager.pageNo" :page-size="pager.pageSize" show-total show-sizer
@on-change="pageChange" @on-page-size-change="sizeChange" /> @on-change="pageChange" @on-page-size-change="sizeChange" />
...@@ -62,7 +55,15 @@ export default { ...@@ -62,7 +55,15 @@ export default {
pager: { pageNo: 1, pageSize: 10, totalRecord: 0 }, pager: { pageNo: 1, pageSize: 10, totalRecord: 0 },
selectedRows: [], selectedRows: [],
confirming: false, confirming: false,
categoryOptions: [] categoryOptions: [],
columns: [
{ type: 'selection', width: 60 },
{ title: '物料编码', key: 'material_code', align: 'center' },
{ title: '物料名称', key: 'material_name', align: 'center' },
{ title: '单位', key: 'unit', align: 'center', width: 80 },
{ title: '可用库存', key: 'available_quantity', align: 'center', width: 120 },
{ title: '分类', key: 'category_Name', align: 'center' }
]
} }
}, },
computed: { computed: {
...@@ -146,5 +147,3 @@ export default { ...@@ -146,5 +147,3 @@ export default {
.mr10 { margin-right: 10px; } .mr10 { margin-right: 10px; }
.page_style { margin-top: 12px; text-align: right; } .page_style { margin-top: 12px; text-align: right; }
</style> </style>
...@@ -82,14 +82,14 @@ ...@@ -82,14 +82,14 @@
<Input type="textarea" v-model="inboundModal.form.remark" :rows="2" /> <Input type="textarea" v-model="inboundModal.form.remark" :rows="2" />
</FormItem> </FormItem>
<h4>明细(从物料库选择)</h4> <h4>明细(从物料库选择)
<Table :data="inboundModal.details" size="small" border> <div style="float: right;">
<TableColumn prop="material_code" title="物料编码" /> <Button size="small" class="mr5" type="primary" @click="showMaterialSelector = true">添加</Button>
<TableColumn prop="material_name" title="物料名称" /> <Button size="small" type="error" @click="deleteSelectedInboundDetails">删除</Button>
<TableColumn prop="inbound_quantity" title="入库数量" /> </div>
<TableColumn prop="unit_price" title="单价" /> </h4>
<TableColumn prop="total_amount" title="总金额" /> <Table :data="inboundModal.details" :columns="inboundDetailColumns" size="small" border @on-selection-change="onInboundDetailSelectionChange" style="width: 100%" />
</Table> <MaterialSelector v-model="showMaterialSelector" :selected="[]" @on-ok="handleInboundMaterialSelectorOk" @cancel="showMaterialSelector = false" />
</Form> </Form>
<div slot="footer"> <div slot="footer">
<Button @click="inboundModal.visible=false">取消</Button> <Button @click="inboundModal.visible=false">取消</Button>
...@@ -103,11 +103,7 @@ ...@@ -103,11 +103,7 @@
<FormItem label="申请单号"><span>{{ returnModal.record.application_no }}</span></FormItem> <FormItem label="申请单号"><span>{{ returnModal.record.application_no }}</span></FormItem>
<FormItem label="申请人"><span>{{ returnModal.record.applicant_name }}</span></FormItem> <FormItem label="申请人"><span>{{ returnModal.record.applicant_name }}</span></FormItem>
<FormItem label="归还明细"> <FormItem label="归还明细">
<Table :data="returnModal.details" size="small" border> <Table :data="returnModal.details" :columns="returnDetailColumns" size="small" border />
<TableColumn prop="material_name" title="物料名称" />
<TableColumn prop="apply_quantity" title="申请数量" />
<TableColumn prop="returned_quantity" title="归还数量" />
</Table>
</FormItem> </FormItem>
</Form> </Form>
<div slot="footer"> <div slot="footer">
...@@ -122,18 +118,9 @@ ...@@ -122,18 +118,9 @@
<div v-else> <div v-else>
<Row :gutter="16"><Col span="12"><p><strong>单号:</strong>{{ detailModal.data.inbound_no || detailModal.data.application_no }}</p></Col></Row> <Row :gutter="16"><Col span="12"><p><strong>单号:</strong>{{ detailModal.data.inbound_no || detailModal.data.application_no }}</p></Col></Row>
<Row class="mt8"><Col span="24"><h4>明细</h4></Col></Row> <Row class="mt8"><Col span="24"><h4>明细</h4></Col></Row>
<Table :data="detailModal.details" size="small" border> <Table :data="detailModal.details" :columns="detailDetailColumns" size="small" border />
<TableColumn prop="material_code" title="物料编码" />
<TableColumn prop="material_name" title="物料名称" />
<TableColumn prop="inbound_quantity" title="数量" />
<TableColumn prop="unit_price" title="单价" />
</Table>
<Row class="mt8"><Col span="24"><h4>操作日志</h4></Col></Row> <Row class="mt8"><Col span="24"><h4>操作日志</h4></Col></Row>
<Table :data="detailModal.logs" size="small" border> <Table :data="detailModal.logs" :columns="detailLogsColumns" size="small" border />
<TableColumn prop="op_type" title="操作类型" />
<TableColumn prop="quantity" title="数量" />
<TableColumn prop="create_time" title="时间" />
</Table>
</div> </div>
<div slot="footer"><Button type="primary" @click="detailModal.visible=false">关闭</Button></div> <div slot="footer"><Button type="primary" @click="detailModal.visible=false">关闭</Button></div>
</Modal> </Modal>
...@@ -151,9 +138,11 @@ import { ...@@ -151,9 +138,11 @@ import {
getInventoryList, getInventoryList,
getInboundById getInboundById
} from '@/api/key-dm-inbound' } from '@/api/key-dm-inbound'
import MaterialSelector from '@/view/key-person/key_dm_conf/materialSelector.vue'
export default { export default {
name: 'key-dm-inbound-index', name: 'key-dm-inbound-index',
components: { MaterialSelector },
data () { data () {
return { return {
activeTab: 'inbound', activeTab: 'inbound',
...@@ -186,6 +175,67 @@ export default { ...@@ -186,6 +175,67 @@ export default {
{ title: '可用', key: 'available_quantity', align: 'center' }, { title: '可用', key: 'available_quantity', align: 'center' },
{ title: '借出', key: 'borrowed_quantity', align: 'center' } { title: '借出', key: 'borrowed_quantity', align: 'center' }
], ],
// 模态窗口内表格列定义
inboundDetailColumns: [
{ type: 'selection', width: 60 },
{ title: '物料编码', key: 'material_code', minWidth: 120 },
{ title: '物料名称', key: 'material_name', minWidth: 150 },
{ title: '入库数量', key: 'inbound_quantity', minWidth: 120, render: (h, params) => {
return h('InputNumber', {
props: {
value: params.row.inbound_quantity || 0,
min: 0,
precision: 0
},
style: { width: '100px' },
on: {
input: (val) => {
params.row.inbound_quantity = val || 0
params.row.total_amount = ((params.row.inbound_quantity || 0) * (params.row.unit_price || 0)).toFixed(2)
}
}
})
}},
{ title: '单价', key: 'unit_price', minWidth: 120, render: (h, params) => {
return h('InputNumber', {
props: {
value: params.row.unit_price || 0,
min: 0,
precision: 2
},
style: { width: '100px' },
on: {
input: (val) => {
params.row.unit_price = val || 0
params.row.total_amount = ((params.row.inbound_quantity || 0) * (params.row.unit_price || 0)).toFixed(2)
}
}
})
}},
{ title: '总金额', key: 'total_amount', minWidth: 120, render: (h, params) => {
const amount = ((params.row.inbound_quantity || 0) * (params.row.unit_price || 0)).toFixed(2)
return h('span', amount)
}}
],
returnDetailColumns: [
{ title: '物料名称', key: 'material_name' },
{ title: '申请数量', key: 'apply_quantity' },
{ title: '归还数量', key: 'returned_quantity' }
],
detailDetailColumns: [
{ title: '物料编码', key: 'material_code' },
{ title: '物料名称', key: 'material_name' },
{ title: '数量', key: 'inbound_quantity' },
{ title: '单价', key: 'unit_price' }
],
detailLogsColumns: [
{ title: '操作类型', key: 'op_type' },
{ title: '数量', key: 'quantity' },
{ title: '时间', key: 'create_time' }
],
// 选择器控制与已选明细
showMaterialSelector: false,
inboundSelectedDetails: [],
inboundModal: { visible: false, isEdit: false, saving: false, form: {}, details: [] }, inboundModal: { visible: false, isEdit: false, saving: false, form: {}, details: [] },
returnModal: { visible: false, record: {}, details: [], saving: false }, returnModal: { visible: false, record: {}, details: [], saving: false },
detailModal: { visible: false, loading: false, data: {}, details: [], logs: [] } detailModal: { visible: false, loading: false, data: {}, details: [], logs: [] }
...@@ -222,6 +272,40 @@ export default { ...@@ -222,6 +272,40 @@ export default {
this.inboundModal.details = [] this.inboundModal.details = []
this.inboundModal.visible = true this.inboundModal.visible = true
}, },
onInboundDetailSelectionChange (list) {
this.inboundSelectedDetails = list || []
},
handleInboundMaterialSelectorOk (selectedRows) {
if (!Array.isArray(selectedRows) || selectedRows.length === 0) {
this.$Message.warning('未选择物料')
return
}
selectedRows.forEach(sel => {
const code = sel.material_code
const exist = this.inboundModal.details.find(d => d.material_code === code)
if (exist) {
exist.inbound_quantity = Number(exist.inbound_quantity || 0) + 1
} else {
this.inboundModal.details.push({
material_code: sel.material_code,
material_name: sel.material_name,
inbound_quantity: 0,
unit_price: 0,
total_amount: 0
})
}
})
this.showMaterialSelector = false
},
deleteSelectedInboundDetails () {
if (!this.inboundSelectedDetails || this.inboundSelectedDetails.length === 0) {
this.$Message.warning('请先选择要删除的明细行')
return
}
const toRemoveCodes = this.inboundSelectedDetails.map(r => r.material_code)
this.inboundModal.details = this.inboundModal.details.filter(d => !toRemoveCodes.includes(d.material_code))
this.inboundSelectedDetails = []
},
openEdit (row) { openEdit (row) {
this.inboundModal.isEdit = true this.inboundModal.isEdit = true
getInboundById({ id: row.id }).then(ret => { getInboundById({ id: row.id }).then(ret => {
......
...@@ -67,13 +67,14 @@ ...@@ -67,13 +67,14 @@
</FormItem> </FormItem>
<h4>申请明细</h4> <h4>申请明细</h4>
<Table :data="applyModal.details" size="small" border> <Row type="flex" justify="end" class="mb8">
<TableColumn prop="material_code" title="物料编码" /> <Col>
<TableColumn prop="material_name" title="物料名称" /> <Button size="small" class="mr5" type="primary" @click="showMaterialSelector = true">添加</Button>
<TableColumn prop="apply_quantity" title="申请数量" /> <Button size="small" type="error" @click="deleteSelectedDetails">删除</Button>
<TableColumn prop="unit" title="单位" /> </Col>
<TableColumn prop="issue_remark" title="备注" /> </Row>
</Table> <Table :data="applyModal.details" :columns="applyDetailColumns" size="small" border @on-selection-change="onApplyDetailSelectionChange" />
<MaterialSelector v-model="showMaterialSelector" :selected="[]" @on-ok="handleMaterialSelectorOk" @cancel="showMaterialSelector = false" />
</Form> </Form>
<div slot="footer"> <div slot="footer">
<Button @click="applyModal.visible=false">取消</Button> <Button @click="applyModal.visible=false">取消</Button>
...@@ -87,12 +88,7 @@ ...@@ -87,12 +88,7 @@
<FormItem label="申请单号"><span>{{ approveModal.record.application_no }}</span></FormItem> <FormItem label="申请单号"><span>{{ approveModal.record.application_no }}</span></FormItem>
<FormItem label="申请人"><span>{{ approveModal.record.applicant_name }}</span></FormItem> <FormItem label="申请人"><span>{{ approveModal.record.applicant_name }}</span></FormItem>
<FormItem label="申请明细"> <FormItem label="申请明细">
<Table :data="approveModal.details" size="small" border> <Table :data="approveModal.details" :columns="approveDetailColumns" size="small" border />
<TableColumn prop="material_name" title="物料名称" />
<TableColumn prop="apply_quantity" title="申请数量" />
<TableColumn prop="unit" title="单位" />
<TableColumn prop="available_quantity" title="可用库存" />
</Table>
</FormItem> </FormItem>
<FormItem label="审批意见"> <FormItem label="审批意见">
<Input type="textarea" v-model="approveModal.opinion" placeholder="驳回时必填" /> <Input type="textarea" v-model="approveModal.opinion" placeholder="驳回时必填" />
...@@ -112,20 +108,9 @@ ...@@ -112,20 +108,9 @@
<Row :gutter="16"><Col span="12"><p><strong>申请人:</strong>{{ detailModal.data.applicant_name }}</p></Col><Col span="12"><p><strong>部门:</strong>{{ detailModal.data.department_name }}</p></Col></Row> <Row :gutter="16"><Col span="12"><p><strong>申请人:</strong>{{ detailModal.data.applicant_name }}</p></Col><Col span="12"><p><strong>部门:</strong>{{ detailModal.data.department_name }}</p></Col></Row>
<Row class="mt8"><Col span="24"><p><strong>领用用途:</strong>{{ detailModal.data.borrow_purpose }}</p></Col></Row> <Row class="mt8"><Col span="24"><p><strong>领用用途:</strong>{{ detailModal.data.borrow_purpose }}</p></Col></Row>
<Row class="mt8"><Col span="24"><h4>明细</h4></Col></Row> <Row class="mt8"><Col span="24"><h4>明细</h4></Col></Row>
<Table :data="detailModal.details" size="small" border> <Table :data="detailModal.details" :columns="detailDetailColumns" size="small" border />
<TableColumn prop="material_code" title="物料编码" />
<TableColumn prop="material_name" title="物料名称" />
<TableColumn prop="apply_quantity" title="申请数量" />
<TableColumn prop="unit" title="单位" />
<TableColumn prop="returned_quantity" title="已归还" />
</Table>
<Row class="mt8"><Col span="24"><h4>审批记录</h4></Col></Row> <Row class="mt8"><Col span="24"><h4>审批记录</h4></Col></Row>
<Table :data="detailModal.logs" size="small" border> <Table :data="detailModal.logs" :columns="detailLogsColumns" size="small" border />
<TableColumn prop="op_type" title="操作类型" />
<TableColumn prop="quantity" title="数量" />
<TableColumn prop="create_time" title="时间" />
<TableColumn prop="create_by" title="操作人" />
</Table>
</div> </div>
<div slot="footer"><Button type="primary" @click="detailModal.visible=false">关闭</Button></div> <div slot="footer"><Button type="primary" @click="detailModal.visible=false">关闭</Button></div>
</Modal> </Modal>
...@@ -143,9 +128,11 @@ import { ...@@ -143,9 +128,11 @@ import {
rejectBorrow, rejectBorrow,
getBorrowById getBorrowById
} from '@/api/key-dm-inventory' } from '@/api/key-dm-inventory'
import MaterialSelector from '@/view/key-person/key_dm_conf/materialSelector.vue'
export default { export default {
name: 'key-dm-inventory-index', name: 'key-dm-inventory-index',
components: { MaterialSelector },
data () { data () {
return { return {
activeTab: 'apply', activeTab: 'apply',
...@@ -180,6 +167,37 @@ export default { ...@@ -180,6 +167,37 @@ export default {
{ title: '审批完成时间', key: 'approval_complete_time', align: 'center' }, { title: '审批完成时间', key: 'approval_complete_time', align: 'center' },
{ title: '操作', slot: 'action', width: 100, align: 'center' } { title: '操作', slot: 'action', width: 100, align: 'center' }
], ],
// 模态窗口内表格列定义
applyDetailColumns: [
{ type: 'selection', width: 60 },
{ title: '物料编码', key: 'material_code' },
{ title: '物料名称', key: 'material_name' },
{ title: '申请数量', key: 'apply_quantity' },
{ title: '单位', key: 'unit' },
{ title: '备注', key: 'issue_remark' }
],
approveDetailColumns: [
{ title: '物料名称', key: 'material_name' },
{ title: '申请数量', key: 'apply_quantity' },
{ title: '单位', key: 'unit' },
{ title: '可用库存', key: 'available_quantity' }
],
detailDetailColumns: [
{ title: '物料编码', key: 'material_code' },
{ title: '物料名称', key: 'material_name' },
{ title: '申请数量', key: 'apply_quantity' },
{ title: '单位', key: 'unit' },
{ title: '已归还', key: 'returned_quantity' }
],
detailLogsColumns: [
{ title: '操作类型', key: 'op_type' },
{ title: '数量', key: 'quantity' },
{ title: '时间', key: 'create_time' },
{ title: '操作人', key: 'create_by' }
],
// 选择器控制与已选明细
showMaterialSelector: false,
applySelectedDetails: [],
applyModal: { visible: false, isEdit: false, saving: false, form: {}, details: [] }, applyModal: { visible: false, isEdit: false, saving: false, form: {}, details: [] },
approveModal: { visible: false, record: {}, details: [], opinion: '', submitting: false }, approveModal: { visible: false, record: {}, details: [], opinion: '', submitting: false },
detailModal: { visible: false, loading: false, data: {}, details: [], logs: [] } detailModal: { visible: false, loading: false, data: {}, details: [], logs: [] }
...@@ -227,6 +245,41 @@ export default { ...@@ -227,6 +245,41 @@ export default {
}) })
this.applyModal.visible = true this.applyModal.visible = true
}, },
onApplyDetailSelectionChange (list) {
this.applySelectedDetails = list || []
},
handleMaterialSelectorOk (selectedRows) {
if (!Array.isArray(selectedRows) || selectedRows.length === 0) {
this.$Message.warning('未选择物料')
return
}
selectedRows.forEach(sel => {
const code = sel.material_code
const exist = this.applyModal.details.find(d => d.material_code === code)
if (exist) {
exist.apply_quantity = Number(exist.apply_quantity || 0) + 1
} else {
this.applyModal.details.push({
material_code: sel.material_code,
material_name: sel.material_name,
apply_quantity: 1,
unit: sel.unit,
issue_remark: '',
available_quantity: sel.available_quantity || 0
})
}
})
this.showMaterialSelector = false
},
deleteSelectedDetails () {
if (!this.applySelectedDetails || this.applySelectedDetails.length === 0) {
this.$Message.warning('请先选择要删除的明细行')
return
}
const toRemoveCodes = this.applySelectedDetails.map(r => r.material_code)
this.applyModal.details = this.applyModal.details.filter(d => !toRemoveCodes.includes(d.material_code))
this.applySelectedDetails = []
},
saveApplication () { saveApplication () {
this.applyModal.saving = true this.applyModal.saving = true
const payload = Object.assign({}, this.applyModal.form, { details: this.applyModal.details }) const payload = Object.assign({}, this.applyModal.form, { details: this.applyModal.details })
......
<template> <template>
<div class="key-dm-stats-wrapper"> <div class="key-dm-stats-wrapper">
<Tabs v-model="activeTab" @on-click="handleTabChange"> <Tabs v-model="activeTab" @on-click="handleTabChange" class="tabsCls">
<TabPane label="办公用品使用统计" name="usage"> <TabPane label="办公用品使用统计" name="usage">
<div class="search-div"> <div class="search-div">
<Row type="flex" :gutter="16" align="middle"> <Row type="flex" :gutter="16" align="middle">
<Col :span="8"> <Col :span="20">
<span>时间段</span> <span>开始</span>
<DatePicker v-model="usageRange" type="daterange" style="width:70%" /> <DatePicker v-model="usageStart" type="date" style="min-width:110px;margin-right:20px" />
</Col> <span>结束:</span>
<Col :span="8"> <DatePicker v-model="usageEnd" type="date" style="min-width:110px;margin-right:20px" />
<span>物料:</span> <span>物料:</span>
<Input v-model="usageMaterial" placeholder="物料名称或编码" style="width:70%" /> <Input v-model="usageMaterial" placeholder="物料名称或编码" style="width: 150px" />
</Col> </Col>
<Col :span="8" class="text-right"> <Col :span="4" class="text-right">
<Button type="primary" class="mr10" @click="loadUsage">统计</Button> <Button type="primary" class="mr10" @click="loadUsage">统计</Button>
<Button @click="resetUsage">重置</Button> <Button @click="resetUsage">重置</Button>
</Col> </Col>
...@@ -28,9 +28,11 @@ ...@@ -28,9 +28,11 @@
<TabPane label="工作量统计" name="workload"> <TabPane label="工作量统计" name="workload">
<div class="search-div"> <div class="search-div">
<Row type="flex" :gutter="16" align="middle"> <Row type="flex" :gutter="16" align="middle">
<Col :span="10"> <Col :span="18">
<span>时间段:</span> <span>开始:</span>
<DatePicker v-model="workRange" type="daterange" style="width:70%" /> <DatePicker v-model="workStart" type="date" style="min-width:110px;margin-right:20px" />
<span>结束:</span>
<DatePicker v-model="workEnd" type="date" style="min-width:110px;margin-right:20px" />
</Col> </Col>
<Col :span="6" class="text-right"> <Col :span="6" class="text-right">
<Button type="primary" class="mr10" @click="loadWorkload">统计</Button> <Button type="primary" class="mr10" @click="loadWorkload">统计</Button>
...@@ -49,25 +51,26 @@ ...@@ -49,25 +51,26 @@
<!-- 使用明细弹窗 --> <!-- 使用明细弹窗 -->
<Modal v-model="detailModal.visible" title="明细" width="800"> <Modal v-model="detailModal.visible" title="明细" width="800">
<Table :data="detailModal.rows" size="small" border> <Table :data="detailModal.rows" :columns="detailModal.columns" size="small" border />
<TableColumn v-for="col in detailModal.columns" :key="col.key" :prop="col.key" :title="col.title" />
</Table>
<div slot="footer"><Button type="primary" @click="detailModal.visible=false">关闭</Button></div> <div slot="footer"><Button type="primary" @click="detailModal.visible=false">关闭</Button></div>
</Modal> </Modal>
</div> </div>
</template> </template>
<script> <script>
import { getUsageStats, getUsageDetails, getWorkloadStats, getWorkloadDetails } from '@/api/key-dm-stats' import { getUsageStats, getUsageDetails, getWorkloadStats, getWorkloadDetails } from '@/api/key-dm'
import { normalizeVisitTimeValue } from '@/view/key-person/key_dm_conf/dates.js'
export default { export default {
name: 'key-dm-stats-index', name: 'key-dm-stats-index',
data () { data () {
return { return {
activeTab: 'usage', activeTab: 'usage',
usageRange: [], usageStart: new Date(new Date().getFullYear(), new Date().getMonth(), 1),
usageEnd: new Date(),
usageMaterial: '', usageMaterial: '',
workRange: [], workStart: new Date(new Date().getFullYear(), new Date().getMonth(), 1),
workEnd: new Date(),
tables: { usage: [], workload: [] }, tables: { usage: [], workload: [] },
loading: { usage: false, workload: false }, loading: { usage: false, workload: false },
usageColumns: [ usageColumns: [
...@@ -87,48 +90,83 @@ export default { ...@@ -87,48 +90,83 @@ export default {
{ title: '请假时长(天)', key: 'leave_duration', align: 'center' }, { title: '请假时长(天)', key: 'leave_duration', align: 'center' },
{ title: '操作', slot: 'action', width: 160, align: 'center' } { title: '操作', slot: 'action', width: 160, align: 'center' }
], ],
detailModal: { visible: false, rows: [], columns: [] } detailModal: {
visible: false,
rows: [],
columns: []
}
} }
}, },
created () {
this.loadUsage()
},
methods: { methods: {
handleTabChange (name) { handleTabChange (name) {
this.activeTab = name this.activeTab = name
if (name === 'usage') {
this.loadUsage()
} else {
this.loadWorkload()
}
}, },
loadUsage () { loadUsage () {
this.loading.usage = true this.loading.usage = true
const params = { start: this.usageRange[0], end: this.usageRange[1], material: this.usageMaterial } const st = this.usageStart ? normalizeVisitTimeValue(this.usageStart) : null
getUsageStats({ params }).then(ret => { const et = this.usageEnd ? normalizeVisitTimeValue(this.usageEnd) : null
const params = { start: st, end: et, material: this.usageMaterial }
getUsageStats(params).then(ret => {
if (ret.data && ret.data.errcode === 0) this.tables.usage = ret.data.data || [] if (ret.data && ret.data.errcode === 0) this.tables.usage = ret.data.data || []
else this.$Notice.error({ title: '查询失败', desc: ret.data && ret.data.errmsg }) else this.$Notice.error({ title: '查询失败', desc: ret.data && ret.data.errmsg })
}).finally(() => { this.loading.usage = false }) }).finally(() => { this.loading.usage = false })
}, },
resetUsage () { this.usageRange = []; this.usageMaterial = ''; this.tables.usage = [] }, resetUsage () { this.usageStart = null; this.usageEnd = null; this.usageMaterial = ''; this.tables.usage = [] },
openUsageDetail (row) { openUsageDetail (row) {
this.detailModal.columns = [{ key: 'user_name', title: '人员' }, { key: 'quantity', title: '数量' }, { key: 'material_name', title: '物料' }, { key: 'department_name', title: '部门' }] this.detailModal.columns = [
{ title: '部门', key: 'department_name', align: 'center' },
{ title: '人员', key: 'user_name', align: 'center' },
{ title: '物料', key: 'material_name', align: 'center' },
{ title: '申请数量', key: 'apply_quantity', align: 'center' },
{ title: '已归还数量', key: 'returned_quantity', align: 'center' }
]
this.detailModal.visible = true this.detailModal.visible = true
getUsageDetails({ params: { start: this.usageRange[0], end: this.usageRange[1], material: this.usageMaterial, department: row.department_id } }).then(ret => { const st = this.usageStart ? normalizeVisitTimeValue(this.usageStart) : null
const et = this.usageEnd ? normalizeVisitTimeValue(this.usageEnd) : null
getUsageDetails({ start: st, end: et, material: row.material_id, department: row.department_id }).then(ret => {
if (ret.data && ret.data.errcode === 0) this.detailModal.rows = ret.data.data || [] if (ret.data && ret.data.errcode === 0) this.detailModal.rows = ret.data.data || []
else this.$Notice.error({ title: '查询失败', desc: ret.data && ret.data.errmsg }) else this.$Notice.error({ title: '查询失败', desc: ret.data && ret.data.errmsg })
}) })
}, },
loadWorkload () { loadWorkload () {
this.loading.workload = true this.loading.workload = true
const params = { start: this.workRange[0], end: this.workRange[1] } const st = this.workStart ? normalizeVisitTimeValue(this.workStart) : null
getWorkloadStats({ params }).then(ret => { const et = this.workEnd ? normalizeVisitTimeValue(this.workEnd) : null
const params = { start: st, end: et }
getWorkloadStats(params).then(ret => {
if (ret.data && ret.data.errcode === 0) this.tables.workload = ret.data.data || [] if (ret.data && ret.data.errcode === 0) this.tables.workload = ret.data.data || []
else this.$Notice.error({ title: '查询失败', desc: ret.data && ret.data.errmsg }) else this.$Notice.error({ title: '查询失败', desc: ret.data && ret.data.errmsg })
}).finally(() => { this.loading.workload = false }) }).finally(() => { this.loading.workload = false })
}, },
resetWorkload () { this.workRange = []; this.tables.workload = [] }, resetWorkload () { this.workStart = null; this.workEnd = null; this.tables.workload = [] },
openWorkloadDetail (row, type) { openWorkloadDetail (row, type) {
const st = this.workStart ? normalizeVisitTimeValue(this.workStart) : null
const et = this.workEnd ? normalizeVisitTimeValue(this.workEnd) : null
if (type === 'leave') { if (type === 'leave') {
this.detailModal.columns = [{ key: 'user_name', title: '人员' }, { key: 'start_time', title: '开始' }, { key: 'end_time', title: '结束' }, { key: 'duration', title: '时长' }] this.detailModal.columns = [
getWorkloadDetails({ params: { user_id: row.user_id, start: this.workRange[0], end: this.workRange[1], type: 'leave' } }).then(ret => { { title: '人员', key: 'user_name', align: 'center' },
{ title: '开始', key: 'start_time', align: 'center' },
{ title: '结束', key: 'end_time', align: 'center' },
{ title: '时长', key: 'duration', align: 'center' }
]
getWorkloadDetails({ user_id: row.user_id, start: st, end: et, type: 'leave' }).then(ret => {
if (ret.data && ret.data.errcode === 0) { this.detailModal.rows = ret.data.data || []; this.detailModal.visible = true } else this.$Notice.error({ title: '查询失败', desc: ret.data && ret.data.errmsg }) if (ret.data && ret.data.errcode === 0) { this.detailModal.rows = ret.data.data || []; this.detailModal.visible = true } else this.$Notice.error({ title: '查询失败', desc: ret.data && ret.data.errmsg })
}) })
} else { } else {
this.detailModal.columns = [{ key: 'application_no', title: '申请单号' }, { key: 'material_name', title: '物料' }, { key: 'apply_quantity', title: '数量' }] this.detailModal.columns = [
getWorkloadDetails({ params: { user_id: row.user_id, start: this.workRange[0], end: this.workRange[1], type: 'inventory' } }).then(ret => { { title: '申请单号', key: 'application_no', align: 'center' },
{ title: '物料', key: 'material_name', align: 'center' },
{ title: '数量', key: 'apply_quantity', align: 'center' }
]
getWorkloadDetails({ user_id: row.user_id, start: st, end: et, type: 'inventory' }).then(ret => {
if (ret.data && ret.data.errcode === 0) { this.detailModal.rows = ret.data.data || []; this.detailModal.visible = true } else this.$Notice.error({ title: '查询失败', desc: ret.data && ret.data.errmsg }) if (ret.data && ret.data.errcode === 0) { this.detailModal.rows = ret.data.data || []; this.detailModal.visible = true } else this.$Notice.error({ title: '查询失败', desc: ret.data && ret.data.errmsg })
}) })
} }
...@@ -138,7 +176,8 @@ export default { ...@@ -138,7 +176,8 @@ export default {
</script> </script>
<style scoped> <style scoped>
.key-dm-stats-wrapper { padding: 10px; } .key-dm-stats-wrapper { padding: 10px; min-height: 380px;}
.tabsCls { min-height: 380px;}
.search-div { border: 1px solid #dce1e7; padding: 12px; margin-bottom: 12px; background-color: #f8fbff; } .search-div { border: 1px solid #dce1e7; padding: 12px; margin-bottom: 12px; background-color: #f8fbff; }
.mr10 { margin-right: 10px; } .mr10 { margin-right: 10px; }
.text-right { text-align: right; } .text-right { text-align: right; }
......
<template> <template>
<div class="key-dm-leave-wrapper"> <div class="key-dm-leave-wrapper">
<Tabs v-model="activeTab" @on-click="handleTabChange"> <Tabs v-model="activeTab" @on-click="handleTabChange" class="tabsCls">
<TabPane label="请假申请" name="apply"> <TabPane label="请假申请" name="apply">
<div class="search-div"> <div class="search-div">
<Row type="flex" :gutter="16"> <Row type="flex" :gutter="16">
...@@ -71,11 +71,11 @@ ...@@ -71,11 +71,11 @@
<TabPane label="请假统计" name="stats"> <TabPane label="请假统计" name="stats">
<div class="search-div"> <div class="search-div">
<Row type="flex" :gutter="16" align="middle"> <Row type="flex" :gutter="16" align="middle">
<Col span="8"> <Col span="16">
<span>时间段</span> <span>开始</span>
<DatePicker v-model="statsRange" type="daterange" placeholder="选择时间段" style="width:70%" /> <DatePicker v-model="statsStart" type="date" placeholder="开始日期" style="min-width:110px;margin-right:20px" />
</Col> <span>结束:</span>
<Col span="8"> <DatePicker v-model="statsEnd" type="date" placeholder="结束日期" style="min-width:110px;margin-right:20px" />
<span>部门:</span> <span>部门:</span>
<Input v-model="statsDept" placeholder="请输入部门名称" style="width:65%" /> <Input v-model="statsDept" placeholder="请输入部门名称" style="width:65%" />
</Col> </Col>
...@@ -271,7 +271,8 @@ export default { ...@@ -271,7 +271,8 @@ export default {
approveModal: { visible: false, record: {}, comment: '', submitting: false }, approveModal: { visible: false, record: {}, comment: '', submitting: false },
transferModal: { visible: false, selectedApprover: '', comment: '', processing: false, record: {} }, transferModal: { visible: false, selectedApprover: '', comment: '', processing: false, record: {} },
detailModal: { visible: false, loading: false, data: {}, approvals: [] }, detailModal: { visible: false, loading: false, data: {}, approvals: [] },
statsRange: [], statsStart: new Date(new Date().getFullYear(), new Date().getMonth(), 1),
statsEnd: new Date(),
statsDept: '' statsDept: ''
} }
}, },
...@@ -574,8 +575,8 @@ export default { ...@@ -574,8 +575,8 @@ export default {
loadStats () { loadStats () {
this.loading.stats = true this.loading.stats = true
const params = { const params = {
start: this.statsRange && this.statsRange[0], start: this.statsStart,
end: this.statsRange && this.statsRange[1], end: this.statsEnd,
department: this.statsDept department: this.statsDept
} }
getLeaveStats({ params }).then(ret => { getLeaveStats({ params }).then(ret => {
...@@ -588,7 +589,8 @@ export default { ...@@ -588,7 +589,8 @@ export default {
}).finally(() => { this.loading.stats = false }) }).finally(() => { this.loading.stats = false })
}, },
resetStats () { resetStats () {
this.statsRange = [] this.statsStart = null
this.statsEnd = null
this.statsDept = '' this.statsDept = ''
this.tables.stats = [] this.tables.stats = []
} }
...@@ -597,7 +599,8 @@ export default { ...@@ -597,7 +599,8 @@ export default {
</script> </script>
<style scoped> <style scoped>
.key-dm-leave-wrapper { padding: 10px; } .key-dm-leave-wrapper { padding: 10px; min-height: 380px;}
.tabsCls { min-height: 380px;}
.search-div { border: 1px solid #dce1e7; padding: 12px; margin-bottom: 12px; background-color: #f8fbff; } .search-div { border: 1px solid #dce1e7; padding: 12px; margin-bottom: 12px; background-color: #f8fbff; }
.mr10 { margin-right: 10px; } .mr10 { margin-right: 10px; }
.text-right { text-align: right; } .text-right { text-align: right; }
......
<template>
<Modal v-model="visible" title="选择人员" width="900" :mask-closable="false">
<div class="search-div">
<Row type="flex" :gutter="16" align="middle">
<Col :span="12">
<span>姓名:</span>
<Input v-model="filters.name" placeholder="请输入姓名" @on-enter="handleSearch" />
</Col>
<Col :span="12" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch">搜索</Button>
<Button @click="handleReset">重置</Button>
</Col>
</Row>
</div>
<Table
:data="rows"
:loading="loading"
:columns="columns"
@on-selection-change="onSelectionChange"
border />
<Page class="page_style" :total="pager.totalRecord" :current="pager.pageNo" :page-size="pager.pageSize" show-total show-sizer
@on-change="pageChange" @on-page-size-change="sizeChange" />
<div slot="footer">
<Button @click="handleCancel">取消</Button>
<Button type="primary" :loading="confirming" @click="handleConfirm">确定({{ selectedRows.length }})</Button>
</div>
</Modal>
</template>
<script>
import { getUserMultiSelectorList } from '@/api/key-dm-user'
export default {
name: 'user-multi-selector',
props: {
// v-model: value 控制显示
value: { type: Boolean, default: false }
},
data () {
return {
visibleInternal: false,
filters: { name: '' },
rows: [],
loading: false,
pager: { pageNo: 1, pageSize: 10, totalRecord: 0 },
selectedRows: [],
confirming: false,
columns: [
{ type: 'selection', width: 60, align: 'center' },
{ title: '姓名', key: 'name', align: 'center', minWidth: 100 },
{ title: '工号', key: 'gh', align: 'center', minWidth: 120 },
{ title: '邮箱', key: 'email', align: 'center', minWidth: 150 },
{ title: '电话', key: 'phone', align: 'center', minWidth: 120 },
{ title: '手机', key: 'mobile', align: 'center', minWidth: 120 },
{ title: '归属部门', key: 'office_name', align: 'center', minWidth: 150 }
]
}
},
computed: {
visible: {
get () { return this.value },
set (v) { this.$emit('input', v) }
}
},
watch: {
visible (v) {
if (v) {
this.pager.pageNo = 1
this.selectedRows = []
this.filters.name = ''
this.fetchList()
}
}
},
methods: {
fetchList () {
this.loading = true
const payload = {
pageNo: this.pager.pageNo,
pageSize: this.pager.pageSize,
params: this.filters
}
getUserMultiSelectorList(payload).then(ret => {
if (ret.data && ret.data.errcode === 0) {
const data = ret.data.data || {}
this.rows = data.results || []
this.pager.totalRecord = data.totalRecord || 0
} else {
this.$Notice.error({ title: '查询失败', desc: ret.data && ret.data.errmsg })
}
}).finally(() => { this.loading = false })
},
handleSearch () {
this.pager.pageNo = 1
this.fetchList()
},
handleReset () {
this.filters = { name: '' }
this.pager.pageNo = 1
this.fetchList()
},
pageChange (pageNo) {
this.pager.pageNo = pageNo
this.fetchList()
},
sizeChange (size) {
this.pager.pageSize = size
this.pager.pageNo = 1
this.fetchList()
},
onSelectionChange (list) {
this.selectedRows = list || []
},
handleCancel () {
this.$emit('cancel')
this.$emit('input', false)
},
handleConfirm () {
if (this.selectedRows.length === 0) {
this.$Message.warning('请先选择人员')
return
}
this.confirming = true
// emit selected users to parent
this.$emit('on-ok', this.selectedRows)
this.$emit('input', false)
this.confirming = false
}
}
}
</script>
<style scoped>
.search-div { border: 1px solid #dce1e7; padding: 12px; margin-bottom: 12px; background-color: #f8fbff; }
.mr10 { margin-right: 10px; }
.page_style { margin-top: 12px; text-align: right; }
.text-right { text-align: right; }
</style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论