Commit 7452feec by zhangtw
parents e5b5fb79 f4fa16c1
......@@ -47,8 +47,9 @@ export const dmUserOffice = (param) => {
export const getUserTypeList = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategory/selectList'
url: '/api/ac/jilinsscgsdp/keyDmUserCategory/selectList',
method: 'post',
data: param
})
}
// 获取人员多选器列表(所有在职人员)
......
......@@ -167,3 +167,77 @@ export const getWorkloadDetails = (param) => {
data: param
})
}
// ===== 图表分析 =====
// 汇总统计数据
export const getSummaryStats = () => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategory/getSummaryStats',
method: 'post'
})
}
// 请假类型统计
export const getLeaveTypeStats = () => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategory/getLeaveTypeStats',
method: 'post'
})
}
// 人员请假统计
export const getLeaveUserStats = () => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategory/getLeaveUserStats',
method: 'post'
})
}
// 用品领用统计
export const getMaterialUsageStats = () => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategory/getMaterialUsageStats',
method: 'post'
})
}
// 库存预警列表
export const getStockWarningList = () => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategory/getStockWarningList',
method: 'post'
})
}
// ===== 部门管理 =====
export const getOrgList = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategory/selectOrgList',
method: 'post',
data: param
})
}
export const saveOrg = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategory/saveOrg',
method: 'post',
data: param
})
}
export const deleteOrg = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategory/deleteOrg',
method: 'post',
data: param
})
}
export const assignUsersToOrg = (param) => {
return axios.request({
url: '/api/ac/jilinsscgsdp/keyDmUserCategory/assignUsersToOrg',
method: 'post',
data: param
})
}
......@@ -254,5 +254,13 @@ export default [
title: '日常管理统计'
},
component: () => import('@/view/key-person/key_dm_inventory/stats')
},
{
path: '/key-person/dmChartAnalysis',
name: 'dmChartAnalysis',
meta: {
title: '日常数据统计分析'
},
component: () => import('@/view/key-person/key_dm_conf/chartAnalysis')
}
]
<template>
<div class="chart-analysis-wrapper">
<!-- 第一行:统计标签 -->
<div class="header-container">
<div class="title-wrapper">
<div class="title-bar"></div>
<h3 class="title-text">数据概览</h3>
</div>
</div>
<Row class="statistics-bar">
<Col span="8">
<div class="statistics-item leave-count">
<div class="stat-icon">
<Icon type="ios-calendar-outline" size="32" />
</div>
<div class="stat-content">
<div class="stat-title">请假申请次数</div>
<div class="stat-number">{{ summaryData.leaveCount }}</div>
<div class="stat-unit"></div>
</div>
</div>
</Col>
<Col span="8">
<div class="statistics-item borrow-count">
<div class="stat-icon">
<Icon type="ios-paper-outline" size="32" />
</div>
<div class="stat-content">
<div class="stat-title">办公用品申领次数</div>
<div class="stat-number">{{ summaryData.borrowCount }}</div>
<div class="stat-unit"></div>
</div>
</div>
</Col>
<Col span="8">
<div class="statistics-item inbound-count">
<div class="stat-icon">
<Icon type="ios-archive-outline" size="32" />
</div>
<div class="stat-content">
<div class="stat-title">办公用品入库次数</div>
<div class="stat-number">{{ summaryData.inboundCount }}</div>
<div class="stat-unit"></div>
</div>
</div>
</Col>
</Row>
<!-- 第二行:请假相关图表 -->
<div class="header-container">
<div class="title-wrapper">
<div class="title-bar"></div>
<h3 class="title-text">请假数据分析</h3>
</div>
</div>
<Row :gutter="16">
<Col span="10">
<Card>
<div class="chart-title">请假类型占比</div>
<div ref="leaveTypeChart" class="chart-container"></div>
</Card>
</Col>
<Col span="14">
<Card>
<div class="chart-title">月度各人员请假次数</div>
<div ref="leaveUserChart" class="chart-container"></div>
</Card>
</Col>
</Row>
<!-- 第三行:办公用品相关图表和表格 -->
<div class="header-container">
<div class="title-wrapper">
<div class="title-bar"></div>
<h3 class="title-text">办公用品数据分析</h3>
</div>
</div>
<Row :gutter="16">
<Col span="10">
<Card>
<div class="chart-title">月度各用品领用量</div>
<div ref="materialUsageChart" class="chart-container"></div>
</Card>
</Col>
<Col span="14">
<Card class="stock-warning-card">
<div class="chart-title">库存预警信息</div>
<div class="table-container">
<Table :data="stockWarningData" :columns="stockWarningColumns" size="small" border :height="chartHeight">
<template slot="threshold" slot-scope="{ row }">
<span>{{ row.min_stock }}-{{ row.max_stock }}</span>
</template>
<template slot="status" slot-scope="{ row }">
<Tag :color="row.status === 'low' ? 'red' : 'orange'">
{{ row.status === 'low' ? '库存不足' : '库存过高' }}
</Tag>
</template>
</Table>
</div>
</Card>
</Col>
</Row>
</div>
</template>
<script>
import * as echarts from 'echarts'
import {
getSummaryStats,
getLeaveTypeStats,
getLeaveUserStats,
getMaterialUsageStats,
getStockWarningList
} from '@/api/key-dm'
export default {
name: 'chart-analysis',
data () {
return {
summaryData: {
leaveCount: 0,
borrowCount: 0,
inboundCount: 0
},
leaveTypeChart: null,
leaveUserChart: null,
materialUsageChart: null,
chartHeight: 240,
stockWarningData: [],
stockWarningColumns: [
{ title: '用品名称', key: 'material_name', align: 'center', minWidth: 50 },
{ title: '现有数量', key: 'available_quantity', align: 'center', minWidth: 50 },
{ title: '阙值范围', slot: 'threshold', align: 'center', minWidth: 50 },
{ title: '状态', slot: 'status', align: 'center', minWidth: 50 }
]
}
},
mounted () {
this.loadData()
},
beforeDestroy () {
if (this.leaveTypeChart) {
this.leaveTypeChart.dispose()
}
if (this.leaveUserChart) {
this.leaveUserChart.dispose()
}
if (this.materialUsageChart) {
this.materialUsageChart.dispose()
}
},
methods: {
loadData () {
this.loadSummaryStats()
this.loadLeaveTypeStats()
this.loadLeaveUserStats()
this.loadMaterialUsageStats()
this.loadStockWarningList()
},
loadSummaryStats () {
getSummaryStats().then(ret => {
if (ret.data && ret.data.errcode === 0) {
this.summaryData = ret.data.data || this.summaryData
}
}).catch(() => {
this.$Message.error('获取统计数据失败')
})
},
loadLeaveTypeStats () {
getLeaveTypeStats().then(ret => {
if (ret.data && ret.data.errcode === 0) {
this.initLeaveTypeChart(ret.data.data || [])
}
}).catch(() => {
this.$Message.error('获取请假类型统计失败')
})
},
loadLeaveUserStats () {
getLeaveUserStats().then(ret => {
if (ret.data && ret.data.errcode === 0) {
this.initLeaveUserChart(ret.data.data || [])
}
}).catch(() => {
this.$Message.error('获取人员请假统计失败')
})
},
loadMaterialUsageStats () {
getMaterialUsageStats().then(ret => {
if (ret.data && ret.data.errcode === 0) {
this.initMaterialUsageChart(ret.data.data || [])
}
}).catch(() => {
this.$Message.error('获取用品领用统计失败')
})
},
loadStockWarningList () {
getStockWarningList().then(ret => {
if (ret.data && ret.data.errcode === 0) {
this.stockWarningData = ret.data.data || []
}
}).catch(() => {
this.$Message.error('获取库存预警数据失败')
})
},
initLeaveTypeChart (data) {
this.$nextTick(() => {
const chartDom = this.$refs.leaveTypeChart
if (!chartDom) return
this.leaveTypeChart = echarts.init(chartDom)
const colors = ['#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc', '#91cc75', '#fac858', '#ee6666']
const option = {
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {
orient: 'vertical',
left: 'left',
textStyle: {
fontSize: 12
}
},
color: colors,
series: [
{
name: '请假类型',
type: 'pie',
radius: ['50%', '70%'],
avoidLabelOverlap: false,
label: {
show: true,
position: 'outside',
formatter: '{b}: {c}',
fontSize: 12
},
emphasis: {
label: {
show: true,
fontSize: '16',
fontWeight: 'bold'
}
},
labelLine: {
show: true,
length: 10,
length2: 10
},
data: data.map((item, index) => ({
value: item.count,
name: item.type_name,
itemStyle: {
color: colors[index % colors.length]
}
}))
}
]
}
this.leaveTypeChart.setOption(option)
})
},
initLeaveUserChart (data) {
this.$nextTick(() => {
const chartDom = this.$refs.leaveUserChart
if (!chartDom) return
this.leaveUserChart = echarts.init(chartDom)
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
data: data.map(item => item.user_name),
axisLabel: {
rotate: 45
}
},
yAxis: {
type: 'value'
},
series: [
{
name: '请假次数',
type: 'bar',
data: data.map(item => item.leave_count),
itemStyle: {
color: '#409EFF'
}
}
]
}
this.leaveUserChart.setOption(option)
})
},
initMaterialUsageChart (data) {
this.$nextTick(() => {
const chartDom = this.$refs.materialUsageChart
if (!chartDom) return
this.materialUsageChart = echarts.init(chartDom)
const colors = ['#73c0de', '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc', '#91cc75', '#fac858', '#ee6666']
const option = {
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {
orient: 'vertical',
left: 'left',
textStyle: {
fontSize: 12
}
},
color: colors,
series: [
{
name: '领用量',
type: 'pie',
radius: ['50%', '70%'],
avoidLabelOverlap: false,
label: {
show: true,
position: 'outside',
formatter: '{b}: {c}',
fontSize: 12
},
emphasis: {
label: {
show: true,
fontSize: '16',
fontWeight: 'bold'
}
},
labelLine: {
show: true,
length: 10,
length2: 10
},
data: data.map((item, index) => ({
value: item.total_quantity,
name: item.material_name,
itemStyle: {
color: colors[index % colors.length]
}
}))
}
]
}
this.materialUsageChart.setOption(option)
})
}
}
}
</script>
<style scoped>
.chart-analysis-wrapper {
padding: 20px;
}
.header-container {
margin: 20px 0 10px 0;
}
.title-wrapper {
display: flex;
align-items: center;
}
.title-bar {
width: 4px;
height: 20px;
background-color: #409EFF;
margin-right: 10px;
}
.title-text {
margin: 0;
font-size: 18px;
font-weight: 600;
color: #333;
}
.statistics-bar {
margin-bottom: 20px;
}
.statistics-item {
display: flex;
align-items: center;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 8px;
margin: 0 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.statistics-item.leave-count {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}
.statistics-item.borrow-count {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}
.statistics-item.inbound-count {
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
}
.stat-icon {
color: white;
margin-right: 20px;
}
.stat-content {
flex: 1;
}
.stat-title {
font-size: 14px;
color: rgba(255, 255, 255, 0.8);
margin-bottom: 8px;
}
.stat-number {
font-size: 36px;
font-weight: bold;
color: white;
margin-bottom: 4px;
display: inline;
}
.stat-unit {
font-size: 16px;
color: rgba(255, 255, 255, 0.8);
display: inline;
}
.chart-container {
width: 100%;
height: 240px;
}
.chart-title {
font-size: 16px;
font-weight: 600;
margin-bottom: 16px;
text-align: center;
}
.stock-warning-card {
height: 315px;
display: flex;
flex-direction: column;
}
.table-container {
flex: 1;
overflow: hidden;
}
</style>
......@@ -9,17 +9,51 @@
</template>
</Table>
</TabPane>
<!-- 部门管理 -->
<TabPane label="部门管理" name="org">
<div class="search-div">
<Row type="flex" :gutter="16">
<Col span="12">
<span>部门名称:</span>
<Input v-model="filters.org.org_name" placeholder="请输入" style="width: 200px" />
</Col>
<Col span="12" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('org')">搜索</Button>
<Button type="primary" class="mr10" @click="handleReset('org')">重置</Button>
<Button type="primary" @click="openAddModal('org')">新增</Button>
</Col>
</Row>
</div>
<Table border :loading="loading.org" :columns="orgColumns" :data="tables.org">
<template slot="action" slot-scope="{ row }">
<Button size="small" type="primary" class="mr5" @click="openEditModal('org', row)">修改</Button>
<Button size="small" type="info" class="mr5" @click="openUserAssignModal(row)">人员划分</Button>
<Poptip confirm title="确认删除?" transfer @on-ok="handleDelete('org', row)">
<Button size="small" type="error">删除</Button>
</Poptip>
</template>
</Table>
<Page
class="page_style"
:total="pagers.org.totalRecord"
:current="pagers.org.pageNo"
:page-size="pagers.org.pageSize"
show-total
show-sizer
@on-change="pageChange('org', $event)"
@on-page-size-change="sizeChange('org', $event)"
/>
</TabPane>
<!-- 假种管理 -->
<TabPane label="假种管理" name="leaveType">
<div class="search-div">
<Row type="flex" :gutter="16">
<Col span="6">
<span>类型名称:</span>
<Input v-model="filters.leaveType.type_name" placeholder="请输入" style="width: 70%" />
</Col>
<Col span="6">
<Col span="12">
<span>类型编码:</span>
<Input v-model="filters.leaveType.type_code" placeholder="请输入" style="width: 70%" />
<Input v-model="filters.leaveType.type_code" placeholder="请输入" style="width: 200px" class="mr10" />
<span>类型名称:</span>
<Input v-model="filters.leaveType.type_name" placeholder="请输入" style="width: 200px" />
</Col>
<Col span="12" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('leaveType')">搜索</Button>
......@@ -52,13 +86,11 @@
<TabPane label="办公用品分类管理" name="materialCategory">
<div class="search-div">
<Row type="flex" :gutter="16">
<Col span="6">
<span>分类名称:</span>
<Input v-model="filters.materialCategory.category_name" placeholder="请输入" style="width: 70%" />
</Col>
<Col span="6">
<Col span="12">
<span>分类编码:</span>
<Input v-model="filters.materialCategory.category_code" placeholder="请输入" style="width: 70%" />
<Input v-model="filters.materialCategory.category_code" placeholder="请输入" style="width: 200px" class="mr10" />
<span>分类名称:</span>
<Input v-model="filters.materialCategory.category_name" placeholder="请输入" style="width: 200px" />
</Col>
<Col span="12" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('materialCategory')">搜索</Button>
......@@ -91,19 +123,15 @@
<TabPane label="办公用品管理" name="material">
<div class="search-div">
<Row type="flex" :gutter="16">
<Col span="6">
<span>名称:</span>
<Input v-model="filters.material.material_name" placeholder="请输入" style="width: 70%" />
</Col>
<Col span="6">
<span>编码:</span>
<Input v-model="filters.material.material_code" placeholder="请输入" style="width: 70%" />
</Col>
<Col span="6">
<Col span="18">
<span>分类:</span>
<Select v-model="filters.material.category_id" clearable style="width: 70%">
<Select v-model="filters.material.category_id" clearable style="width: 200px" class="mr10">
<Option v-for="cat in materialCategoryOptions" :key="cat.id" :value="cat.id">{{ cat.category_name }}</Option>
</Select>
<span>编码:</span>
<Input v-model="filters.material.material_code" placeholder="请输入" style="width: 200px" class="mr10" />
<span>名称:</span>
<Input v-model="filters.material.material_name" placeholder="请输入" style="width: 200px" />
</Col>
<Col span="6" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('material')">搜索</Button>
......@@ -180,27 +208,12 @@
<Input type="textarea" :rows="3" v-model="modals.leaveType.form.remark" placeholder="请输入类型描述" />
</FormItem>
<Row :gutter="16">
<Col span="12">
<FormItem label="基准天数" prop="base_days">
<InputNumber v-model="modals.leaveType.form.base_days" :min="0" :precision="2" style="width: 100%" />
</FormItem>
</Col>
<Col span="12">
<!-- <Col span="12">
<FormItem label="年度上限" prop="max_days_per_year">
<InputNumber v-model="modals.leaveType.form.max_days_per_year" :min="0" :precision="2" style="width: 100%" />
</FormItem>
</Col>
</Row>
<Row :gutter="16">
<Col span="12">
<FormItem label="需要审批">
<Select v-model="modals.leaveType.form.need_approval" style="width: 100%">
<Option :value="1">需要</Option>
<Option :value="0">不需要</Option>
</Select>
</FormItem>
</Col>
<Col span="12">
</Col> -->
<Col span="24">
<FormItem label="排序号" prop="order_no">
<InputNumber v-model="modals.leaveType.form.order_no" :min="0" style="width: 100%" />
</FormItem>
......@@ -356,9 +369,55 @@
</div>
</Modal>
<!-- 部门管理弹窗 -->
<Modal v-model="modals.org.visible" :title="modals.org.isEdit ? '修改部门' : '新增部门'" width="600" :mask-closable="false">
<Form :label-width="120" :model="modals.org.form" :rules="modals.org.rules" ref="orgForm">
<!-- <FormItem label="部门编码" prop="org_code">
<Input v-model="modals.org.form.org_code" placeholder="请输入部门编码" />
</FormItem> -->
<FormItem label="部门名称" prop="org_name">
<Input v-model="modals.org.form.org_name" placeholder="请输入部门名称" />
</FormItem>
<!-- <FormItem label="所属机构编码" prop="source_org">
<Input v-model="modals.org.form.source_org" placeholder="请输入所属机构编码" />
</FormItem> -->
<FormItem label="部门描述" prop="remark">
<Input type="textarea" :rows="3" v-model="modals.org.form.remark" placeholder="请输入部门描述" />
</FormItem>
<FormItem label="排序号" prop="order_no">
<InputNumber v-model="modals.org.form.order_no" :min="0" style="width: 100%" />
</FormItem>
</Form>
<div slot="footer">
<Button @click="modals.org.visible = false">取消</Button>
<Button type="primary" :loading="modals.org.saving" @click="handleSave('org')">保存</Button>
</div>
</Modal>
<!-- 人员划分弹窗 -->
<Modal v-model="userAssignModal.visible" title="人员划分" width="800" :mask-closable="false">
<div style="margin-bottom: 16px;">
<span style="font-weight: bold;">部门:</span>{{ userAssignModal.orgName }}
</div>
<div style="margin-bottom: 16px;">
<span style="font-weight: bold;">已划分人员:</span>
<div style="margin-top: 8px;">
<Tag v-for="user in userAssignModal.selectedUsers" :key="user.user_id" closable @on-close="removeAssignedUser(user)">
{{ user.user_name }}
</Tag>
</div>
</div>
<div slot="footer">
<Button @click="userAssignModal.visible = false">取消</Button>
<Button type="primary" @click="addUsersToOrg">添加人员</Button>
<Button type="primary" :loading="userAssignModal.saving" @click="saveUserAssignment">保存</Button>
</div>
</Modal>
<!-- 人员选择器 -->
<UserMultiSelector
v-model="userSelectorVisible"
:round="userRound"
@on-ok="handleUserSelectorOk"
@cancel="userSelectorVisible = false" />
......@@ -379,7 +438,11 @@ import {
importMaterial,
getPermissionConfigList,
savePermissionUsers,
getUserDmPermissionList
getUserDmPermissionList,
getOrgList,
saveOrg,
deleteOrg,
assignUsersToOrg
} from '@/api/key-dm'
import axios from 'axios'
import UserMultiSelector from '@/view/key-person/key_dm_user/userMultiSelector.vue'
......@@ -393,25 +456,29 @@ export default {
filters: {
leaveType: { type_name: '', type_code: '' },
materialCategory: { category_name: '', category_code: '' },
material: { material_name: '', material_code: '', category_id: '' }
material: { material_name: '', material_code: '', category_id: '' },
org: { org_name: '', org_code: '' }
},
tables: {
permissionConfig: [],
leaveType: [],
materialCategory: [],
material: []
material: [],
org: []
},
loading: {
permissionConfig: false,
leaveType: false,
materialCategory: false,
material: false
material: false,
org: false
},
pagers: {
permissionConfig: { pageNo: 1, pageSize: 10, totalRecord: 0 },
leaveType: { 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 },
org: { pageNo: 1, pageSize: 10, totalRecord: 0 }
},
modals: {
leaveType: {
......@@ -473,6 +540,23 @@ export default {
category_id: [{ required: true, message: '请选择分类', trigger: 'change' }],
material_name: [{ required: true, message: '请输入物料名称', trigger: 'blur' }]
}
},
org: {
visible: false,
isEdit: false,
saving: false,
form: {
id: '',
source_org: '',
org_code: '',
org_name: '',
remark: '',
order_no: 0
},
rules: {
// org_code: [{ required: true, message: '请输入部门编码', trigger: 'blur' }],
org_name: [{ required: true, message: '请输入部门名称', trigger: 'blur' }]
}
}
},
userConfigModal: {
......@@ -482,6 +566,13 @@ export default {
permissionName: '',
selectedUsers: []
},
userAssignModal: {
visible: false,
saving: false,
orgId: '',
orgName: '',
selectedUsers: []
},
userSelectorVisible: false,
importShow: false,
impBtnDisabled: false,
......@@ -490,8 +581,8 @@ export default {
{ type: 'index', title: '序号', width: 60, align: 'center' },
{ title: '类型编码', key: 'type_code', align: 'center' },
{ title: '类型名称', key: 'type_name', align: 'center' },
{ title: '基准天数', key: 'base_days', align: 'center', width: 100 },
{ title: '需要审批', key: 'need_approval', align: 'center', width: 100, render: (h, { row }) => h('span', row.need_approval === 1 ? '需要' : '不需要') },
// { title: '基准天数', key: 'base_days', align: 'center', width: 100 },
// { title: '需要审批', key: 'need_approval', align: 'center', width: 100, render: (h, { row }) => h('span', row.need_approval === 1 ? '需要' : '不需要') },
{ title: '排序号', key: 'order_no', align: 'center', width: 100 },
{ title: '操作', slot: 'action', align: 'center', width: 180, fixed: 'right' }
],
......@@ -528,12 +619,23 @@ export default {
{ title: '配置人员', key: 'user_names', align: 'center', minWidth: 300 },
{ title: '操作', slot: 'action', align: 'center', width: 120, fixed: 'right' }
],
orgColumns: [
{ type: 'index', title: '序号', width: 60, align: 'center' },
// { title: '部门编码', key: 'org_code', align: 'center' },
{ title: '部门名称', key: 'org_name', align: 'center' },
// { title: '所属机构编码', key: 'source_org', align: 'center' },
{ title: '部门人员', key: 'user_names', align: 'center' },
{ title: '描述', key: 'remark', align: 'center' },
{ title: '排序号', key: 'order_no', align: 'center', width: 100 },
{ title: '操作', slot: 'action', align: 'center', width: 200, fixed: 'right' }
],
power: {
leave_approval: false, // 请假审核
leave_view: false, // 请假查询(统计)
supply_approval: false, // 用品申领审核
supply_view: false // 用品查询(统计)
}
},
userRound: '1'
}
},
created () {
......@@ -572,7 +674,8 @@ export default {
permissionConfig: () => Promise.resolve({ data: { errcode: 0, data: [] } }),
leaveType: getLeaveTypeList,
materialCategory: getMaterialCategoryList,
material: getMaterialList
material: getMaterialList,
org: getOrgList
}
const api = apiMap[tab]
if (!api) return
......@@ -597,7 +700,8 @@ export default {
permissionConfig: () => ({}),
leaveType: () => ({ type_name: '', type_code: '' }),
materialCategory: () => ({ category_name: '', category_code: '' }),
material: () => ({ material_name: '', material_code: '', category_id: '' })
material: () => ({ material_name: '', material_code: '', category_id: '' }),
org: () => ({ org_name: '', org_code: '' })
}
this.filters[tab] = resetMap[tab]()
this.pagers[tab].pageNo = 1
......@@ -662,6 +766,14 @@ export default {
can_borrow: 1,
material_desc: '',
order_no: 0
},
org: {
id: '',
source_org: '',
org_code: '',
org_name: '',
remark: '',
order_no: 0
}
}
return JSON.parse(JSON.stringify(defaults[tab]))
......@@ -676,7 +788,8 @@ export default {
const saveApiMap = {
leaveType: saveLeaveType,
materialCategory: saveMaterialCategory,
material: saveMaterial
material: saveMaterial,
org: saveOrg
}
const api = saveApiMap[tab]
api(modal.form).then(ret => {
......@@ -698,7 +811,8 @@ export default {
const deleteApiMap = {
leaveType: deleteLeaveType,
materialCategory: deleteMaterialCategory,
material: deleteMaterial
material: deleteMaterial,
org: deleteOrg
}
const api = deleteApiMap[tab]
api({ id: row.id }).then(ret => {
......@@ -748,17 +862,29 @@ export default {
console.log('this.userConfigModal', this.userConfigModal)
},
addUsers () {
this.userRound = '1'
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]
if (this.userConfigModal.visible) {
// 权限配置弹窗
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]
} else if (this.userAssignModal.visible) {
// 人员划分弹窗
const existingIds = this.userAssignModal.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.userAssignModal.selectedUsers = [...this.userAssignModal.selectedUsers, ...newUsers]
}
this.userSelectorVisible = false
},
removeUser (user) {
......@@ -876,6 +1002,46 @@ export default {
const areaId = info.area_id || ''
if (areaId && areaId.startsWith('2201')) return true
return false
},
openUserAssignModal (row) {
this.userAssignModal.visible = true
this.userAssignModal.orgId = row.id
this.userAssignModal.orgName = row.org_name
this.userAssignModal.selectedUsers = row.user_names ? (JSON.parse(row.users) || []) : []
// 加载该部门已分配的人员
// this.loadOrgAssignedUsers(row.id)
},
// loadOrgAssignedUsers (orgId) {
// getOrgList({ pageNo: 1, pageSize: 1000, params: { id: orgId } }).then(ret => {
// if (ret.data && ret.data.errcode === 0) {
// const data = ret.data.data || {}
// // 这里可以根据实际需求调整如何获取已分配的人员
// // 暂时设置为空,后续根据实际业务逻辑调整
// }
// })
// },
addUsersToOrg () {
this.userRound = '2'
this.userSelectorVisible = true
},
removeAssignedUser (user) {
this.userAssignModal.selectedUsers = this.userAssignModal.selectedUsers.filter(u => u.user_id !== user.user_id)
},
saveUserAssignment () {
this.userAssignModal.saving = true
const userIds = this.userAssignModal.selectedUsers.map(u => u.user_id)
assignUsersToOrg({
org_id: this.userAssignModal.orgId,
user_ids: userIds
}).then(ret => {
if (ret.data && ret.data.errcode === 0) {
this.fetchList("org")
this.$Message.success('保存成功')
this.userAssignModal.visible = false
} else {
this.$Notice.error({ title: '保存失败', desc: ret.data && ret.data.errmsg })
}
}).finally(() => { })
}
}
}
......
......@@ -152,84 +152,128 @@ export default {
const et = this.workEnd ? normalizeVisitTimeValue(this.workEnd) : null
if (type === 'leave') {
this.detailModal.columns = [
{ title: '人员', key: 'user_name', align: 'center' },
{ title: '开始', key: 'start_time', align: 'center', render: (h, params) => {
const time = params.row.start_time
if (time) {
const date = new Date(time)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return h('span', `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`)
{
title: '人员',
key: 'user_name',
align: 'center'
},
{
title: '开始',
key: 'start_time',
align: 'center',
render: (h, params) => {
const time = params.row.start_time
if (time) {
const date = new Date(time)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return h('span', `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`)
}
return h('span', '-')
}
return h('span', '-')
}},
{ title: '结束', key: 'end_time', align: 'center', render: (h, params) => {
const time = params.row.end_time
if (time) {
const date = new Date(time)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return h('span', `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`)
},
{
title: '结束',
key: 'end_time',
align: 'center',
render: (h, params) => {
const time = params.row.end_time
if (time) {
const date = new Date(time)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return h('span', `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`)
}
return h('span', '-')
}
return h('span', '-')
}},
{ title: '时长', key: 'duration', align: 'center' },
{ title: '状态', key: 'status', align: 'center', render: (h, params) => {
const status = params.row.status
let statusText = ''
switch (status) {
case 0: statusText = '未提交'; break
case 1: statusText = '审核中'; break
case 9: statusText = '审核通过'; break
case -1: statusText = '驳回'; break
default: statusText = status
},
{
title: '时长',
key: 'duration',
align: 'center'
},
{
title: '状态',
key: 'status',
align: 'center',
render: (h, params) => {
const status = params.row.status
let statusText = ''
switch (status) {
case 0: statusText = '未提交'; break
case 1: statusText = '审核中'; break
case 9: statusText = '审核通过'; break
case -1: statusText = '驳回'; break
default: statusText = status
}
return h('span', statusText)
}
return h('span', statusText)
}}
}
]
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 })
})
} else {
this.detailModal.columns = [
{ title: '申请时间', key: 'submit_time', align: 'center', render: (h, params) => {
const time = params.row.submit_time
if (time) {
const date = new Date(time)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return h('span', `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`)
{
title: '申请时间',
key: 'submit_time',
align: 'center',
render: (h, params) => {
const time = params.row.submit_time
if (time) {
const date = new Date(time)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return h('span', `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`)
}
return h('span', '-')
}
return h('span', '-')
}},
{ title: '物料', key: 'material_name', align: 'center' },
{ title: '申请数量', key: 'apply_quantity', align: 'center' },
{ title: '归还数量', key: 'returned_quantity', align: 'center' },
{ title: '状态', key: 'approval_status', align: 'center', render: (h, params) => {
const status = params.row.approval_status
let statusText = ''
switch (status) {
case 0: statusText = '待提交'; break
case 1: statusText = '审核中'; break
case 9: statusText = '审核通过'; break
case -1: statusText = '驳回'; break
default: statusText = status
},
{
title: '物料',
key: 'material_name',
align: 'center'
},
{
title: '申请数量',
key: 'apply_quantity',
align: 'center'
},
{
title: '归还数量',
key: 'returned_quantity',
align: 'center'
},
{
title: '状态',
key: 'approval_status',
align: 'center',
render: (h, params) => {
const status = params.row.approval_status
let statusText = ''
switch (status) {
case 0: statusText = '待提交'; break
case 1: statusText = '审核中'; break
case 9: statusText = '审核通过'; break
case -1: statusText = '驳回'; break
default: statusText = status
}
return h('span', statusText)
}
return h('span', statusText)
}}
}
]
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 })
......
......@@ -4,22 +4,20 @@
<TabPane label="请假申请" name="apply">
<div class="search-div">
<Row type="flex" :gutter="16" class="mt8">
<Col span="12">
<Col span="20">
<span>开始:</span>
<DatePicker v-model="filters.apply.start_time" type="date" placeholder="开始日期" style="min-width:110px;margin-right:20px" />
<span>结束:</span>
<DatePicker v-model="filters.apply.end_time" type="date" placeholder="结束日期" style="min-width:110px;margin-right:20px" />
</Col>
<Col span="8">
<span>状态:</span>
<Select v-model="filters.apply.status" style="width: 60%">
<Select v-model="filters.apply.status" style="width: 150px">
<Option v-for="opt in statusOptions" :key="opt.id" :value="opt.id">{{ opt.name }}</Option>
</Select>
</Col>
<Col span="4" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('apply')">搜索</Button>
<Button class="mr10" @click="handleReset('apply')">重置</Button>
<Button type="success" @click="openApplyModal">申请</Button>
<Button type="primary" class="mr10" @click="handleReset('apply')">重置</Button>
<Button type="primary" @click="openApplyModal">申请</Button>
</Col>
</Row>
</div>
......@@ -53,21 +51,19 @@
<TabPane label="审核历史查询" name="history">
<div class="search-div">
<Row type="flex" :gutter="16" align="middle">
<Col span="12">
<Col span="20">
<span>开始:</span>
<DatePicker v-model="filters.history.start_time" type="date" placeholder="开始日期" style="min-width:110px;margin-right:20px" />
<span>结束:</span>
<DatePicker v-model="filters.history.end_time" type="date" placeholder="结束日期" style="min-width:110px;margin-right:20px" />
</Col>
<Col span="8">
<span>状态:</span>
<Select v-model="filters.history.status" style="width: 60%">
<Select v-model="filters.history.status" style="width: 150px" class="mr10">
<Option v-for="opt in statusOptions" :key="opt.id" :value="opt.id">{{ opt.name }}</Option>
</Select>
</Col>
<Col span="4" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('history')">搜索</Button>
<Button @click="handleReset('history')">重置</Button>
<Button type="primary" @click="handleReset('history')">重置</Button>
</Col>
</Row>
</div>
......@@ -83,21 +79,19 @@
<TabPane label="请假申请查询" name="query">
<div class="search-div">
<Row type="flex" :gutter="16" align="middle">
<Col span="8">
<Col span="16">
<span>开始:</span>
<DatePicker v-model="filters.query.start_time" type="date" placeholder="开始日期" style="min-width:110px;margin-right:20px" />
<span>结束:</span>
<DatePicker v-model="filters.query.end_time" type="date" placeholder="结束日期" style="min-width:110px;margin-right:20px" />
</Col>
<Col span="8">
<span>状态:</span>
<Select v-model="filters.query.status" style="width: 60%">
<Select v-model="filters.query.status" style="width: 150px">
<Option v-for="opt in statusOptions" :key="opt.id" :value="opt.id">{{ opt.name }}</Option>
</Select>
</Col>
<Col span="8" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch('query')">搜索</Button>
<Button @click="handleReset('query')">重置</Button>
<Button type="primary" @click="handleReset('query')">重置</Button>
</Col>
</Row>
</div>
......@@ -119,11 +113,11 @@
<span>结束:</span>
<DatePicker v-model="statsEnd" type="date" placeholder="结束日期" style="min-width:110px;margin-right:20px" />
<span>部门:</span>
<Input v-model="statsDept" placeholder="请输入部门名称" style="width:65%" />
<Input v-model="statsDept" placeholder="请输入部门名称" style="width: 200px" />
</Col>
<Col span="8" class="text-right">
<Button type="primary" class="mr10" @click="loadStats">统计</Button>
<Button @click="resetStats">重置</Button>
<Button type="primary" @click="resetStats">重置</Button>
</Col>
</Row>
</div>
......@@ -415,6 +409,7 @@ export default {
if (name === 'pending') this.fetchList('pending')
if (name === 'history') this.fetchList('history')
if (name === 'query') this.fetchList('query')
if (name === 'stats') this.loadStats()
},
fetchList (tab) {
const apiMap = { apply: getLeaveListByUserId, pending: getPendingList, history: getApprovalHistory, query: getLeaveList }
......
......@@ -10,11 +10,11 @@
</Col> -->
<Col :span="12" class="text-left">
<span>姓名:</span>
<Input v-model="filters.name" placeholder="请输入姓名" style="width: 40%" />
<Input v-model="filters.name" placeholder="请输入姓名" style="width: 200px" />
</Col>
<Col :span="12" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch">搜索</Button>
<Button @click="handleReset" class="mr10">重置</Button>
<Button type="primary" @click="handleReset" class="mr10">重置</Button>
<Button type="primary" class="mr10" @click="handleSync">同步</Button>
</Col>
</Row>
......@@ -56,10 +56,10 @@
<!-- 角色已移除 -->
<!-- <FormItem label="归属部门">
<SelectDisplay v-model="editModal.form.office_id" placeholder="请输入机构" @open="openOfficeSelect(editModal.form)" />
</FormItem>
<FormItem label="直属领导">
<SelectDisplay v-model="editModal.form.leader" placeholder="只能选择本级或父机构人员" @open="openSelectLeader(editModal.form)" />
</FormItem> -->
<FormItem label="直属领导">
<Input v-model="editModal.form.leader_name" readonly placeholder="点击选择直属领导" @click.native="selectLeader" style="cursor: pointer" />
</FormItem>
<FormItem label="是否离职">
<Select v-model="editModal.form.is_leave" style="width: 160px">
<Option :value="0">未离职</Option>
......@@ -72,16 +72,26 @@
<Button type="primary" :loading="editModal.saving" @click="saveEdit">保存</Button>
</div>
</Modal>
<!-- 人员选择器 -->
<UserSelector
v-model="userSelectorVisible"
permission=""
@on-ok="handleLeaderSelected"
@cancel="userSelectorVisible = false" />
<!-- 领导与归属部门选择已移除 -->
</div>
</template>
<script>
import { getDmUserList, syncDmUsersByOffice, saveDmUser } from '@/api/key-dm-user'
import UserSelector from './userSelector.vue'
import { normalizeVisitTimeValue } from '@/view/key-person/key_dm_conf/dates.js'
export default {
name: 'key-dm-user-index',
components: {},
components: { UserSelector },
data () {
return {
officeCode: '',
......@@ -103,7 +113,8 @@ export default {
visible: false,
saving: false,
form: {}
}
},
userSelectorVisible: false
// leader / office state 已移除
}
},
......@@ -167,7 +178,7 @@ export default {
const params = { office_code: this.officeCode }
this.$Modal.confirm({
title: '确认同步',
content: '将同步本机构及下属机构的用户,已存在的记录会被更新(不覆盖 null 值),是否继续?',
content: '将同步本机构及下属机构的用户,已存在的记录会被更新,是否继续?',
onOk: () => {
this.loading = true
syncDmUsersByOffice(params).then(ret => {
......@@ -188,11 +199,20 @@ export default {
this.editModal.form = copy
this.editModal.visible = true
},
selectLeader () {
this.userSelectorVisible = true
},
handleLeaderSelected (user) {
this.editModal.form.leader = user.id
this.editModal.form.leader_name = user.name
this.userSelectorVisible = false
},
/* leader / office 相关方法已移除 */
saveEdit () {
this.$refs.editForm.validate(valid => {
// no strict validation here, just save
this.editModal.saving = true
this.editModal.form.in_work_time = this.editModal.form.in_work_time ? normalizeVisitTimeValue(this.editModal.form.in_work_time) : null
saveDmUser(this.editModal.form).then(ret => {
if (ret.data && ret.data.errcode === 0) {
this.$Message.success('保存成功')
......
......@@ -4,7 +4,7 @@
<Row type="flex" :gutter="16" align="middle">
<Col :span="12">
<span>姓名:</span>
<Input v-model="filters.name" placeholder="请输入姓名" @on-enter="handleSearch" />
<Input v-model="filters.name" placeholder="请输入姓名" style="width: 200px" />
</Col>
<Col :span="12" class="text-right">
<Button type="primary" class="mr10" @click="handleSearch">搜索</Button>
......@@ -37,7 +37,9 @@ export default {
name: 'user-multi-selector',
props: {
// v-model: value 控制显示
value: { type: Boolean, default: false }
value: { type: Boolean, default: false },
// 范围参数1父,本级,下级2本级
round: { type: String, default: '1' }
},
data () {
return {
......@@ -50,12 +52,12 @@ export default {
confirming: false,
columns: [
{ type: 'selection', width: 60, align: 'center' },
{ title: '归属部门', key: 'office_name', align: 'center', minWidth: 150 },
{ title: '姓名', key: 'name', align: 'center', minWidth: 100 },
{ title: '工号', key: 'gh', align: 'center', minWidth: 120 },
{ title: '邮箱', key: 'email', align: 'center', minWidth: 150 },
// { 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 }
{ title: '手机', key: 'mobile', align: 'center', minWidth: 120 }
]
}
},
......@@ -78,11 +80,7 @@ export default {
methods: {
fetchList () {
this.loading = true
const payload = {
pageNo: this.pager.pageNo,
pageSize: this.pager.pageSize,
params: this.filters
}
const payload = Object.assign({}, { pageNo: this.pager.pageNo, pageSize: this.pager.pageSize, round: this.round }, this.filters)
getUserMultiSelectorList(payload).then(ret => {
if (ret.data && ret.data.errcode === 0) {
const data = ret.data.data || {}
......
<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="请输入姓名" style="width: 200px" />
</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"
border
highlight-row
@on-current-change="onCurrentRowChange"
@on-row-dblclick="onRowDblclick" />
<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" :disabled="!selectedRow">确定</Button>
</div>
</Modal>
</template>
<script>
import { getUserSelectorList } from '@/api/key-dm-user'
export default {
name: 'user-selector',
props: {
// v-model: value 控制显示
value: { type: Boolean, default: false },
// 权限参数
permission: { type: String, default: '' }
},
data () {
return {
visibleInternal: false,
filters: { name: '' },
rows: [],
loading: false,
pager: { pageNo: 1, pageSize: 10, totalRecord: 0 },
selectedRow: null,
confirming: false,
columns: [
{ 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 },
{ title: '人员分类', key: 'category_names', align: 'center', minWidth: 200 }
]
}
},
computed: {
visible: {
get () { return this.value },
set (v) { this.$emit('input', v) }
}
},
watch: {
visible (v) {
if (v) {
this.pager.pageNo = 1
this.selectedRow = null
this.filters.name = ''
this.fetchList()
}
}
},
methods: {
fetchList () {
this.loading = true
const payload = Object.assign({},
{ pageNo: this.pager.pageNo, pageSize: this.pager.pageSize, office_code: this.officeCode, permission: this.permission },
this.filters)
getUserSelectorList(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()
},
onCurrentRowChange (currentRow, oldCurrentRow) {
this.selectedRow = currentRow
},
onRowDblclick (row, index) {
this.selectedRow = row
this.handleConfirm()
},
handleCancel () {
this.$emit('cancel')
this.$emit('input', false)
},
handleConfirm () {
if (!this.selectedRow) {
this.$Message.warning('请先选择人员')
return
}
this.confirming = true
// emit selected user to parent
this.$emit('on-ok', this.selectedRow)
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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论