generated from Leo_Ding/web-template
454 lines
16 KiB
Vue
454 lines
16 KiB
Vue
<template>
|
||
<x-search-bar class="mb-8-2">
|
||
<template #default="{ gutter, colSpan }">
|
||
<a-form :model="searchFormData" layout="inline" labelAlign="left">
|
||
<a-row :gutter="[24, 24]">
|
||
<!-- 所在区域 -->
|
||
<a-col :span="8" v-if="platForm !== 'yunying'">
|
||
<a-form-item label="所属服务组织" name="station">
|
||
<node-tree v-model:value="searchFormData.station" />
|
||
</a-form-item>
|
||
</a-col>
|
||
<!-- 姓名 -->
|
||
<a-col :span="8">
|
||
<a-form-item label="姓名" name="name">
|
||
<a-input v-model:value="searchFormData.name" placeholder="请输入姓名" />
|
||
</a-form-item>
|
||
</a-col>
|
||
|
||
<!-- 身份证号 -->
|
||
<a-col :span="8">
|
||
<a-form-item label="联系电话" name="phone">
|
||
<a-input v-model:value="searchFormData.phone" placeholder="请输入联系电话" />
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="8">
|
||
<a-form-item label="护理人员类型" name="serviceType">
|
||
<a-select v-model:value="searchFormData.serviceType" allowClear>
|
||
<a-select-option v-for="item in dicsStore.dictOptions.STAFF_TYPE" :key="item.dval"
|
||
:value="item.dval">{{
|
||
item.introduction }}</a-select-option>
|
||
</a-select>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="8">
|
||
<a-form-item label="护理人员状态" name="status">
|
||
<a-select v-model:value="searchFormData.status" allowClear>
|
||
<a-select-option v-for="item in dicsStore.dictOptions.STAFF_STATUS" :key="item.dval"
|
||
:value="item.dval">{{
|
||
item.introduction }}</a-select-option>
|
||
</a-select>
|
||
</a-form-item>
|
||
</a-col>
|
||
<a-col :span="8">
|
||
<a-form-item label="用工形式" name="workType">
|
||
<a-select v-model:value="searchFormData.workType" allowClear>
|
||
<a-select-option v-for="item in dicsStore.dictOptions.USE_TYPE" :key="item.dval"
|
||
:value="item.dval">{{
|
||
item.introduction }}</a-select-option>
|
||
</a-select>
|
||
</a-form-item>
|
||
</a-col>
|
||
<!-- 操作按钮 -->
|
||
<a-col class="align-right" :span="24">
|
||
<a-space>
|
||
<a-button @click="handleResetSearch">{{ $t('button.reset') }}</a-button>
|
||
<a-button ghost type="primary" @click="handleSearch">
|
||
{{ $t('button.search') }}
|
||
</a-button>
|
||
</a-space>
|
||
</a-col>
|
||
</a-row>
|
||
</a-form>
|
||
</template>
|
||
</x-search-bar>
|
||
<a-row :gutter="8" :wrap="false">
|
||
<a-col flex="auto">
|
||
<a-card title="服务人员列表">
|
||
<template #extra>
|
||
<a-space>
|
||
<a-button type="primary" @click="$refs.editDialogRef.handleCreate(record)">新建</a-button>
|
||
<a-button type="primary">导出</a-button>
|
||
<a-button type="dashed">导出记录</a-button>
|
||
</a-space>
|
||
</template>
|
||
<a-table :columns="columns" :data-source="listData" bordered="true" :loading="loading"
|
||
:pagination="paginationState" :scroll="{ x: 'max-content' }" @change="onTableChange">
|
||
<template #bodyCell="{ index, column, record }">
|
||
<template v-if="column.key === 'serialNumber'">
|
||
<span>{{ index + 1 }}</span>
|
||
</template>
|
||
<template v-if="column.key === 'workType'">
|
||
<span>{{ dicsStore.getDictLabel('USE_TYPE', record.workType) }}</span>
|
||
</template>
|
||
<template v-if="column.key === 'gender'">
|
||
<span v-if="record.gender == '1'">男</span>
|
||
<span v-else>女</span>
|
||
</template>
|
||
<template v-if="column.key === 'status'">
|
||
<a-tag>{{ dicsStore.getDictLabel('STAFF_STATUS', record.status) }}</a-tag>
|
||
</template>
|
||
<template v-if="column.key === 'serviceType'">
|
||
<span>{{ dicsStore.getDictLabel('STAFF_TYPE', record.serviceType) }}</span>
|
||
</template>
|
||
|
||
<template v-if="'action' === column.key">
|
||
<x-action-button @click="$refs.editDialogRef.handleEdit(record)">
|
||
<span>编辑</span>
|
||
</x-action-button>
|
||
<x-action-button @click="$refs.detailRef.handleEdit(record)">
|
||
<span>详情</span>
|
||
</x-action-button>
|
||
<x-action-button @click="treeHandleEdit(record.id)" v-if="platForm === 'yunying'">
|
||
<span>服务项目</span>
|
||
</x-action-button>
|
||
<x-action-button @click="handleStop(record)"
|
||
v-if="platForm === 'yunying' && (record.status == '1' || record.status == '4')">
|
||
<span v-if="record.status === '1'">停用</span>
|
||
<span v-if="record.status === '4'">启用</span>
|
||
</x-action-button>
|
||
<x-action-button @click="handleDelete(record)">
|
||
<span style="color: #ff4d4f;">删除</span>
|
||
</x-action-button>
|
||
</template>
|
||
</template>
|
||
</a-table>
|
||
</a-card>
|
||
</a-col>
|
||
</a-row>
|
||
<edit-dialog ref="editDialogRef" @ok="onOk"></edit-dialog>
|
||
<detail ref="detailRef"></detail>
|
||
<a-modal v-model:open="treeOpen" title="绑定服务项目" @ok="handleOk">
|
||
<a-card>
|
||
<a-spin :spinning="spinning">
|
||
<a-tree v-model:expandedKeys="expandedKeys" v-model:selectedKeys="selectedKeys"
|
||
v-model:checkedKeys="checkedKeys" checkable :tree-data="treeData" @check="onCheck">
|
||
<template #title="{ title, key }">
|
||
<span v-if="key === '0-0-1-0'" style="color: #1890ff">{{ title }}</span>
|
||
<template v-else>{{ title }}</template>
|
||
</template>
|
||
</a-tree>
|
||
</a-spin>
|
||
</a-card>
|
||
</a-modal>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { message, Modal } from 'ant-design-vue'
|
||
import { ref } from 'vue'
|
||
import apis from '@/apis'
|
||
import { config } from '@/config'
|
||
import { usePagination } from '@/hooks'
|
||
import { useI18n } from 'vue-i18n'
|
||
import EditDialog from './components/EditDialog.vue'
|
||
import { useDicsStore } from '@/store'
|
||
import AreaCascader from '@/components/AreaCascader/index.vue'
|
||
import detail from './components/detail.vue'
|
||
import dayjs from 'dayjs'
|
||
import NodeTree from '@/components/NodeTree/index.vue'
|
||
import storage from '@/utils/storage'
|
||
import { getBirthDate, spliceUrl } from '@/utils/util'
|
||
defineOptions({
|
||
name: 'allocation',
|
||
})
|
||
const currentId = ref('')
|
||
const spinning = ref(false)
|
||
const expandedKeys = ref([])
|
||
const selectedKeys = ref([])
|
||
const checkedKeys = ref([])
|
||
const treeData = ref([])
|
||
const treeOpen = ref(false)
|
||
const dicsStore = useDicsStore()
|
||
const platForm = storage.local.getItem('platform')
|
||
const columns = [
|
||
{
|
||
title: '序号',
|
||
dataIndex: 'serialNumber',
|
||
key: 'serialNumber',
|
||
align: 'center',
|
||
width: 80,
|
||
},
|
||
{
|
||
title: '姓名',
|
||
dataIndex: 'name',
|
||
key: 'name',
|
||
align: 'center',
|
||
width: 100,
|
||
},
|
||
{
|
||
title: '性别',
|
||
dataIndex: 'gender',
|
||
key: 'gender',
|
||
align: 'center',
|
||
width: 80,
|
||
},
|
||
{
|
||
title: '电话',
|
||
dataIndex: 'phone',
|
||
key: 'phone',
|
||
align: 'center',
|
||
width: 80,
|
||
},
|
||
{
|
||
title: '身份证号',
|
||
dataIndex: 'idCard',
|
||
key: 'idCard',
|
||
align: 'center',
|
||
width: 180,
|
||
},
|
||
{
|
||
title: '护理人员类型',
|
||
dataIndex: 'serviceType',
|
||
key: 'serviceType',
|
||
align: 'center',
|
||
width: 120,
|
||
},
|
||
{
|
||
title: '用工形式',
|
||
dataIndex: 'workType',
|
||
key: 'workType',
|
||
align: 'center',
|
||
width: 120,
|
||
},
|
||
{
|
||
title: '状态',
|
||
dataIndex: 'status',
|
||
key: 'status',
|
||
align: 'center',
|
||
width: 120,
|
||
},
|
||
{
|
||
title: '所属服务组织',
|
||
dataIndex: 'stationName',
|
||
key: 'stationName',
|
||
align: 'center',
|
||
width: 120,
|
||
},
|
||
// {
|
||
// title: '组织所在区域',
|
||
// dataIndex: 'areaLabels',
|
||
// key: 'areaLabels',
|
||
// align: 'center',
|
||
// width: 120,
|
||
// },
|
||
|
||
{
|
||
title: '操作',
|
||
dataIndex: 'action',
|
||
key: 'action',
|
||
align: 'center',
|
||
width: 250,
|
||
fixed: 'right',
|
||
}
|
||
];
|
||
const { t } = useI18n() // 解构出t方法
|
||
const { listData, loading, showLoading, hideLoading, paginationState, resetPagination, searchFormData } = usePagination()
|
||
const editDialogRef = ref()
|
||
const detailRef = ref()
|
||
|
||
getPageList()
|
||
|
||
async function getPageList() {
|
||
try {
|
||
loading.value = true
|
||
const { pageSize, current } = paginationState
|
||
const { success, data, total } = await apis.serviceStaffList
|
||
.getProjectList({
|
||
companyId: storage.local.getItem('companyId'),
|
||
stationId: storage.local.getItem('stationId'),
|
||
pageSize,
|
||
current: current,
|
||
...searchFormData.value,
|
||
})
|
||
.catch(() => {
|
||
throw new Error()
|
||
})
|
||
|
||
if (config('http.code.success') === success) {
|
||
listData.value = data
|
||
paginationState.total = total
|
||
loading.value = false
|
||
getServerProject()
|
||
}
|
||
} catch (error) {
|
||
loading.value = false
|
||
}
|
||
}
|
||
// 判断是否为叶子节点
|
||
function isLeafNode(nodeKey, data = treeData.value) {
|
||
for (const item of data) {
|
||
if (item.key === nodeKey) {
|
||
return !item.children || item.children.length === 0;
|
||
}
|
||
if (item.children && item.children.length > 0) {
|
||
const found = isLeafNode(nodeKey, item.children);
|
||
if (found !== null) return found;
|
||
}
|
||
}
|
||
return null; // 未找到
|
||
}
|
||
|
||
// 获取所有叶子节点(递归)
|
||
function getAllLeafKeys(data) {
|
||
let leaves = [];
|
||
data.forEach(item => {
|
||
if (!item.children || item.children.length === 0) {
|
||
leaves.push(item.key);
|
||
} else {
|
||
leaves = leaves.concat(getAllLeafKeys(item.children));
|
||
}
|
||
});
|
||
return leaves;
|
||
}
|
||
|
||
// 处理勾选
|
||
const onCheck = (checkedKeysObj, info) => {
|
||
console.log(checkedKeysObj)
|
||
// const { checked, halfChecked } = checkedKeysObj;
|
||
|
||
// 只保留叶子节点
|
||
const leafCheckedKeys = checkedKeysObj.filter(key => {
|
||
return isLeafNode(key) === true;
|
||
});
|
||
|
||
// 更新受控的 checkedKeys(可选:只显示叶子被选中)
|
||
checkedKeys.value = leafCheckedKeys;
|
||
};
|
||
/**核销 */
|
||
const getServerProject = async (id) => {
|
||
try {
|
||
currentId.value = id
|
||
const { data, success } = await apis.serviceStaffList.getTreeData({ categoryType: '1' })
|
||
if (success) {
|
||
treeData.value = transformCategories(data)
|
||
}
|
||
} catch (error) {
|
||
console.log(error.msg)
|
||
}
|
||
}
|
||
async function treeHandleEdit(id){
|
||
try {
|
||
currentId.value=id
|
||
spinning.value=true
|
||
treeOpen.value = true
|
||
const {data,success}=await apis.serviceStaffList.getProject({current:1,pageSize:99,servicePersonId:id})
|
||
if (success) {
|
||
checkedKeys.value=data.map(item=>item.projectId)
|
||
console.log(selectedKeys.value)
|
||
}
|
||
spinning.value=false
|
||
} catch (error) {
|
||
spinning.value=false
|
||
}
|
||
|
||
}
|
||
function transformCategories(data) {
|
||
return data.map(category => ({
|
||
key: category.categoryId,
|
||
title: category.categoryName,
|
||
children: category.projects.map(project => ({
|
||
key: project.id,
|
||
title: project.name
|
||
}))
|
||
}));
|
||
}
|
||
const handleOk = async () => {
|
||
try {
|
||
const params = { servicePersonId: currentId.value, projectIds: checkedKeys.value }
|
||
const {success} = await apis.serviceStaffList.createProject(params)
|
||
if(success){
|
||
message.success('绑定成功')
|
||
treeOpen.value=false
|
||
checkedKeys.value=[]
|
||
}
|
||
} catch (error) {
|
||
console.log(error)
|
||
}
|
||
|
||
}
|
||
const handleStop = async (record) => {
|
||
let params = {
|
||
...record,
|
||
birthDay: record.birthDate2
|
||
}
|
||
|
||
if (record.laborContract && record.laborContract.length > 0) {
|
||
params.laborContractStartAt = record.laborContract[0]
|
||
params.laborContractEndAt = record.laborContract[1]
|
||
}
|
||
params.imgs = (record.imgs && record.imgs.length) > 0 ? record.imgs.map(item => spliceUrl(item)) : []
|
||
params.attachments = (record.attachments && record.attachments.length) > 0 ? record.attachments.map(item => spliceUrl(item)) : []
|
||
params.commissionRate = record.commissionRate ?? record.commissionRate / 100
|
||
params.status = record.status == '4' ? '1' : '4'
|
||
console.log(params)
|
||
const { success } = await apis.serviceStaffList.updateItem(params).catch(() => {
|
||
throw new Error()
|
||
})
|
||
if (success) {
|
||
getPageList()
|
||
}
|
||
}
|
||
/**
|
||
* 删除
|
||
*/
|
||
function handleDelete({ id }) {
|
||
Modal.confirm({
|
||
title: t('pages.system.user.delTip'),
|
||
content: t('button.confirm'),
|
||
okText: t('button.confirm'),
|
||
onOk: () => {
|
||
return new Promise((resolve, reject) => {
|
||
; (async () => {
|
||
try {
|
||
const { success } = await apis.productOrder.delItem(id).catch(() => {
|
||
throw new Error()
|
||
})
|
||
if (config('http.code.success') === success) {
|
||
resolve()
|
||
message.success(t('component.message.success.delete'))
|
||
await getPageList()
|
||
}
|
||
} catch (error) {
|
||
reject()
|
||
}
|
||
})()
|
||
})
|
||
},
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 分页
|
||
*/
|
||
function onTableChange({ current, pageSize }) {
|
||
paginationState.current = current
|
||
paginationState.pageSize = pageSize
|
||
getPageList()
|
||
}
|
||
|
||
/**
|
||
* 搜索
|
||
*/
|
||
function handleSearch() {
|
||
resetPagination()
|
||
getPageList()
|
||
}
|
||
/**
|
||
* 重置
|
||
*/
|
||
function handleResetSearch() {
|
||
searchFormData.value = {}
|
||
resetPagination()
|
||
getPageList()
|
||
}
|
||
/**
|
||
* 编辑完成
|
||
*/
|
||
async function onOk() {
|
||
await getPageList()
|
||
}
|
||
|
||
</script>
|
||
|
||
<style lang="less" scoped></style>
|