代码修改

This commit is contained in:
qiuyuan 2025-10-13 11:55:39 +08:00
parent def6dbb546
commit 668c8664ce
3 changed files with 197 additions and 308 deletions

View File

@ -0,0 +1,11 @@
// 服务设施模块
import request from '@/utils/request'
// 获取节点
export const getNodeList = (params) => request.basic.get('/api/v1/service-nodes', params)
// 创建节点
export const createNode = (params) => request.basic.post('/api/v1/service-nodes', params)
// 删除节点
export const delNode = (id) => request.basic.delete(`/api/v1/service-nodes/${id}`)

View File

@ -1,9 +1,9 @@
<template> <template>
<div class="org-management"> <div class="org-management">
<!-- <div class="header"> <div class="header" v-if="!hasData">
<h1>组织管理</h1> <h1>组织管理</h1>
<a-button type="primary" @click="showAddModal()">添加根节点</a-button> <a-button type="primary" @click="showAddModal()">添加根节点</a-button>
</div> --> </div>
<div class="org-table"> <div class="org-table">
<a-table <a-table
@ -14,27 +14,30 @@
:expand-icon-as-cell="false" :expand-icon-as-cell="false"
> >
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<template v-if="column.key === 'projectType'"> <template v-if="column.key === 'disabled'">
<a-tag :color="record.projectType === 'Supervision' ? 'blue' : 'green'"> <a-tag :color="record.disabled === false ? 'green' : 'red'">
{{ record.projectType === 'Supervision' ? '监管' : '居家养老床位' }} {{ record.disabled === false ? '启用' : '禁用' }}
</a-tag> </a-tag>
</template> </template>
<template v-if="column.key === 'status'"> <template v-if="column.key === 'created_at'">
<a-tag :color="record.status === 0 ? 'green' : 'red'"> <div>{{ record.created_at ? dayjs(record.created_at).format('YYYY-MM-DD HH:mm') : '-' }}</div>
{{ record.status === 0 ? '启用' : '禁用' }} </template>
</a-tag> <template v-if="column.key === 'updated_at'">
<div>{{ record.updated_at ? dayjs(record.updated_at).format('YYYY-MM-DD HH:mm') : '-' }}</div>
</template> </template>
<template v-if="column.key === 'actions'"> <template v-if="column.key === 'actions'">
<div class="actions"> <div class="actions">
<!-- 修改这里只在前两层显示添加子节点按钮 -->
<a-button <a-button
v-if="getNodeLevel(record) < 2"
size="small" size="small"
type="primary" type="primary"
@click="showAddModal(record)" @click="showAddModal(record)"
v-if="record.projectType === 'Supervision'"
> >
添加子节点 添加子节点
</a-button> </a-button>
<a-button <a-button
style="margin-left: 20px;"
size="small" size="small"
danger danger
@click="handleDelete(record)" @click="handleDelete(record)"
@ -64,17 +67,13 @@
<a-form-item label="节点名称" name="name"> <a-form-item label="节点名称" name="name">
<a-input v-model:value="formState.name" placeholder="请输入节点名称" /> <a-input v-model:value="formState.name" placeholder="请输入节点名称" />
</a-form-item> </a-form-item>
<a-form-item label="节点类型" name="projectType">
<a-select v-model:value="formState.projectType" placeholder="请选择节点类型">
<a-select-option value="Supervision">监管</a-select-option>
<a-select-option value="HomeCareBed">居家养老床位</a-select-option>
</a-select>
</a-form-item>
<a-form-item label="状态" name="status"> <a-form-item label="状态" name="status">
<a-radio-group v-model:value="formState.status"> <a-switch
<a-radio :value="0">启用</a-radio> v-model:checked="formState.status"
<a-radio :value="1">禁用</a-radio> :checked-children="statusText.checked"
</a-radio-group> :un-checked-children="statusText.unchecked"
:disabled="!isEditing"
/>
</a-form-item> </a-form-item>
</a-form> </a-form>
</a-modal> </a-modal>
@ -82,15 +81,34 @@
</template> </template>
<script setup> <script setup>
import { ref, reactive, onMounted } from 'vue'; import { ref, reactive, onMounted, computed } from 'vue';
import { message, Modal } from 'ant-design-vue'; import apis from '@/apis';
import { Modal, message } from 'ant-design-vue';
import dayjs from 'dayjs';
import { config } from '@/config';
import { usePagination } from '@/hooks';
const { listData, paginationState, loading, showLoading, hideLoading, resetPagination, searchFormData } = usePagination();
//
const hasData = computed(() => {
return listData.value && listData.value.length > 0;
});
paginationState.onChange = (page, pageSize) => {
paginationState.current = page
paginationState.pageSize = pageSize
getList()
}
// subOrgList children // subOrgList children
const convertData = (data) => { const convertData = (data) => {
if (!data || data.length === 0) return [];
return data.map(item => { return data.map(item => {
const converted = { const converted = {
...item, ...item,
key: item.orgId, // 使 orgId key key: item.id, // 使 id key id orgId
}; };
if (item.subOrgList && item.subOrgList.length > 0) { if (item.subOrgList && item.subOrgList.length > 0) {
@ -101,122 +119,6 @@ const convertData = (data) => {
}); });
}; };
//
const originalData = ref([
{
"id": 5066,
"orgId": "1813150290069417984",
"name": "南通市通州区互联网+智慧养老居家上门服务项目",
"path": "/0/1813150290069417984",
"parentId": "0",
"status": 0,
"tenantId": "1813150290048446464",
"projectType": "Supervision",
"subOrgList": [
{
"id": 5093,
"orgId": "1813400548804390913",
"name": "东社镇",
"parentId": "1813150290069417984",
"path": "/0/1813150290069417984/1813400548804390913",
"status": 0,
"tenantId": "1813150290048446464",
"projectType": "Supervision",
"createBy": "1694238554834726912",
"createTime": "2024-07-17T10:29:17",
"updateBy": "1694238554834726912",
"updateTime": "2024-07-17T10:29:17",
"subOrgList": [
{
"id": 5094,
"orgId": "1813400640336556032",
"name": "东社镇服务站",
"parentId": "1813400548804390913",
"path": "/0/1813150290069417984/1813400548804390913/1813400640336556032",
"status": 0,
"tenantId": "1813150290048446464",
"projectType": "HomeCareBed",
"createBy": "1694238554834726912",
"createTime": "2024-07-17T10:29:39",
"updateBy": "1694238554834726912",
"updateTime": "2024-07-17T10:29:39",
"subOrgList": [],
"disabled": false
}
],
"disabled": false
},
{
"id": 5071,
"orgId": "1813396942931881985",
"name": "二甲镇",
"parentId": "1813150290069417984",
"path": "/0/1813150290069417984/1813396942931881985",
"status": 0,
"tenantId": "1813150290048446464",
"projectType": "Supervision",
"createBy": "1694238554834726912",
"createTime": "2024-07-17T10:14:57",
"updateBy": "1694238554834726912",
"updateTime": "2024-07-17T10:14:57",
"subOrgList": [
{
"id": 5072,
"orgId": "1813397035642646528",
"name": "二甲镇服务站",
"parentId": "1813396942931881985",
"path": "/0/1813150290069417984/1813396942931881985/1813397035642646528",
"status": 0,
"tenantId": "1813150290048446464",
"projectType": "HomeCareBed",
"createBy": "1694238554834726912",
"createTime": "2024-07-17T10:15:19",
"updateBy": "1694238554834726912",
"updateTime": "2024-07-17T10:15:19",
"subOrgList": [],
"disabled": false
}
],
"disabled": false
},
{
"id": 5091,
"orgId": "1813400338249674753",
"name": "五接镇",
"parentId": "1813150290069417984",
"path": "/0/1813150290069417984/1813400338249674753",
"status": 0,
"tenantId": "1813150290048446464",
"projectType": "Supervision",
"createBy": "1694238554834726912",
"createTime": "2024-07-17T10:28:27",
"updateBy": "1694238554834726912",
"updateTime": "2024-07-17T10:28:27",
"subOrgList": [
{
"id": 5092,
"orgId": "1813400446438469632",
"name": "五接镇服务站",
"parentId": "1813400338249674753",
"path": "/0/1813150290069417984/1813400338249674753/1813400446438469632",
"status": 0,
"tenantId": "1813150290048446464",
"projectType": "HomeCareBed",
"createBy": "1694238554834726912",
"createTime": "2024-07-17T10:28:53",
"updateBy": "1694238554834726912",
"updateTime": "2024-07-17T10:28:53",
"subOrgList": [],
"disabled": false
}
],
"disabled": false
}
],
"disabled": false
}
]);
// //
const dataSource = ref([]); const dataSource = ref([]);
@ -226,52 +128,51 @@ const isEditing = ref(false);
const currentParent = ref(null); const currentParent = ref(null);
const confirmLoading = ref(false); const confirmLoading = ref(false);
// // - false
const formState = reactive({ const formState = reactive({
name: '', name: '',
projectType: 'Supervision', status: false // false
status: 0 });
//
const statusText = computed(() => {
return {
checked: '禁用',
unchecked: '启用'
};
}); });
// //
const rules = { const rules = {
name: [ name: [
{ required: true, message: '请输入节点名称', trigger: 'blur' } { required: true, message: '请输入节点名称', trigger: 'blur' }
],
projectType: [
{ required: true, message: '请选择节点类型', trigger: 'change' }
] ]
}; };
// // - projectType
const columns = [ const columns = [
{ {
title: '组织名称', title: '组织名称',
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
}, width: 200,
{
title: '组织类型',
dataIndex: 'projectType',
key: 'projectType',
width: 150,
}, },
{ {
title: '状态', title: '状态',
dataIndex: 'status', dataIndex: 'disabled',
key: 'status', key: 'disabled',
width: 100, width: 100,
}, },
{ {
title: '创建时间', title: '创建时间',
dataIndex: 'createTime', dataIndex: 'created_at',
key: 'createTime', key: 'created_at',
width: 180, width: 180,
}, },
{ {
title: '更新时间', title: '更新时间',
dataIndex: 'updateTime', dataIndex: 'updated_at',
key: 'updateTime', key: 'updated_at',
width: 180, width: 180,
}, },
{ {
@ -281,49 +182,110 @@ const columns = [
}, },
]; ];
// /**
const initData = () => { * 获取节点的层级
dataSource.value = convertData(originalData.value); * @param {Object} node 节点数据
* @param {Array} data 数据源
* @param {number} level 当前层级
* @returns {number} 节点层级0表示第一层1表示第二层2表示第三层
*/
const getNodeLevel = (node, data = null, level = 0) => {
// 0
if (!node.parentId || node.parentId === "") {
return 0;
}
// data使dataSource
const searchData = data || dataSource.value;
//
const findParentLevel = (nodes, targetId, currentLevel) => {
for (const item of nodes) {
if (item.id === targetId) {
return currentLevel;
}
if (item.children && item.children.length > 0) {
const found = findParentLevel(item.children, targetId, currentLevel + 1);
if (found !== -1) {
return found;
}
}
}
return -1;
};
//
const parentLevel = findParentLevel(searchData, node.parentId, 0);
// + 1
return parentLevel + 1;
}; };
/**
* 获取表格数据
* @returns {Promise<void>}
*/
async function getList() {
try {
showLoading()
const { pageSize, current } = paginationState
const { success, data, total } = await apis.serviceMenu
.getNodeList({
pageSize,
current: current
})
.catch(() => {
throw new Error()
})
hideLoading()
if (config('http.code.success') === success) {
console.log("接口返回数据:", data)
listData.value = data || [];
paginationState.total = total || 0;
//
dataSource.value = convertData(listData.value);
}
} catch (error) {
hideLoading()
console.error('获取数据失败:', error);
message.error('获取数据失败');
}
}
// //
const handleDelete = (record) => { const handleDelete = async (record) => {
Modal.confirm({ Modal.confirm({
title: '确认删除', title: '确认删除',
content: `确定要删除"${record.name}"吗?${record.children && record.children.length > 0 ? '此操作将同时删除所有子节点。' : ''}`, content: `确定要删除"${record.name}"吗?${record.children && record.children.length > 0 ? '此操作将同时删除所有子节点。' : ''}`,
onOk() { async onOk() {
deleteNode(originalData.value, record.orgId); console.log('删除节点:', record.id);
initData(); try {
message.success('删除成功'); //
} const { success } = await apis.serviceMenu.delNode(record.id);
}); if (config('http.code.success') === success) {
}; message.success('删除成功');
//
// await getList();
const deleteNode = (data, orgId) => { } else {
for (let i = 0; i < data.length; i++) { message.error('删除失败');
if (data[i].orgId === orgId) { }
data.splice(i, 1); } catch (error) {
return true; console.error('删除失败:', error);
} message.error('删除失败');
if (data[i].subOrgList && data[i].subOrgList.length > 0) {
if (deleteNode(data[i].subOrgList, orgId)) {
return true;
} }
} }
} });
return false;
}; };
// //
const showAddModal = (parent = null) => { const showAddModal = (parent = null) => {
currentParent.value = parent; currentParent.value = parent;
isEditing.value = false; isEditing.value = false;
// // -
Object.assign(formState, { Object.assign(formState, {
name: '', name: '',
projectType: 'Supervision', status: false //
status: 0
}); });
addModalVisible.value = true; addModalVisible.value = true;
}; };
@ -338,38 +300,26 @@ const handleAdd = async () => {
confirmLoading.value = true; confirmLoading.value = true;
try { try {
// // - parentId
await new Promise(resolve => setTimeout(resolve, 500)); const submitData = {
companyId: 'c001',
const newNode = { disabled: formState.status, // falsetrue
id: Date.now(),
orgId: `new_${Date.now()}`,
name: formState.name, name: formState.name,
parentId: currentParent.value ? currentParent.value.orgId : '0', status: "",
path: currentParent.value ? `${currentParent.value.path}/${formState.name}` : `/0/${formState.name}`, parentId: currentParent.value ? currentParent.value.id : "" // 使 id
status: formState.status,
tenantId: "1813150290048446464",
projectType: formState.projectType,
createBy: "system",
createTime: new Date().toISOString().split('T')[0],
updateBy: "system",
updateTime: new Date().toISOString().split('T')[0],
subOrgList: [],
disabled: false
}; };
if (currentParent.value) { //
// subOrgList const { success } = await apis.serviceMenu.createNode(submitData);
addChildNode(originalData.value, currentParent.value.orgId, newNode);
if (config('http.code.success') === success) {
addModalVisible.value = false;
message.success('添加成功');
//
await getList();
} else { } else {
// message.error('添加失败');
originalData.value.push(newNode);
} }
//
initData();
addModalVisible.value = false;
message.success('添加成功');
} catch (error) { } catch (error) {
console.error('添加失败:', error); console.error('添加失败:', error);
message.error('添加失败'); message.error('添加失败');
@ -378,82 +328,12 @@ const handleAdd = async () => {
} }
}; };
//
const addChildNode = (data, parentId, newNode) => {
for (let i = 0; i < data.length; i++) {
if (data[i].orgId === parentId) {
if (!data[i].subOrgList) {
data[i].subOrgList = [];
}
data[i].subOrgList.push(newNode);
return true;
}
if (data[i].subOrgList && data[i].subOrgList.length > 0) {
if (addChildNode(data[i].subOrgList, parentId, newNode)) {
return true;
}
}
}
return false;
};
// //
const handleCancel = () => { const handleCancel = () => {
addModalVisible.value = false; addModalVisible.value = false;
}; };
onMounted(() => { onMounted(() => {
initData(); getList();
}); });
</script> </script>
<style scoped>
.org-management {
margin: 0 auto;
padding: 10px;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding: 0 10px;
}
.org-table {
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.actions {
display: flex;
gap: 8px;
}
.header h1 {
margin: 0;
color: #1f1f1f;
font-size: 24px;
font-weight: 600;
}
:deep(.ant-table-thead > tr > th) {
background-color: #fafafa;
font-weight: 600;
}
:deep(.ant-table-row-level-0) {
font-weight: 600;
}
:deep(.ant-table-row-level-1) {
font-weight: 500;
}
:deep(.ant-table-row-level-2) {
font-weight: 400;
}
</style>

View File

@ -26,9 +26,10 @@
<a-col :span="12"> <a-col :span="12">
<a-form-item :label="'站点类型'" name="type" :required="true"> <a-form-item :label="'站点类型'" name="type" :required="true">
<a-select v-model:value="formData.type" @change="handleChange"> <a-select v-model:value="formData.type" @change="handleChange">
<a-select-option value="type1">社区服务中心</a-select-option> <a-select-option v-for="item in dicsStore.dictOptions.Station_Type" :key="item.dval"
<a-select-option value="type2">养老服务站</a-select-option> :value="item.dval">
<a-select-option value="type3">综合服务中心</a-select-option> {{ item.introduction }}
</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -45,11 +46,10 @@
<a-col :span="12"> <a-col :span="12">
<a-form-item :label="'星级等级'" name="starLevel"> <a-form-item :label="'星级等级'" name="starLevel">
<a-select v-model:value="formData.starLevel"> <a-select v-model:value="formData.starLevel">
<a-select-option value="1">一星</a-select-option> <a-select-option v-for="item in dicsStore.dictOptions.Level" :key="item.dval"
<a-select-option value="2">二星</a-select-option> :value="item.dval">
<a-select-option value="3">三星</a-select-option> {{ item.introduction }}
<a-select-option value="4">四星</a-select-option> </a-select-option>
<a-select-option value="5">五星</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -63,12 +63,11 @@
</a-card> </a-card>
<!-- 地址信息区域 --> <!-- 地址信息区域 -->
<a-card class="mb-4" title="地址信息"> <a-card class="mb-4" title="地址信息" style="margin-top: 20px" >
<a-row :gutter="16"> <a-row :gutter="16">
<a-col :span="24"> <a-col :span="24">
<a-form-item :label="'服务中心地址'" name="address"> <a-form-item :label="'服务中心地址'" name="address">
<a-cascader v-model:value="formData.address" :options="addressOptions" <AreaCascader v-model:value="formData.address" @change="onAreaChange" />
placeholder="请选择省/市/区" style="width: 100%"></a-cascader>
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="24"> <a-col :span="24">
@ -92,7 +91,7 @@
</a-card> </a-card>
<!-- 站点信息区域 --> <!-- 站点信息区域 -->
<a-card class="mb-4" title="站点信息"> <a-card class="mb-4" title="站点信息" style="margin-top: 20px">
<a-row :gutter="16"> <a-row :gutter="16">
<a-col :span="12"> <a-col :span="12">
<a-form-item :label="'建成时间'" name="buildTime"> <a-form-item :label="'建成时间'" name="buildTime">
@ -116,7 +115,7 @@
</a-card> </a-card>
<!-- 服务信息区域 --> <!-- 服务信息区域 -->
<a-card class="mb-4" title="服务信息"> <a-card class="mb-4" title="服务信息" style="margin-top: 20px">
<a-row :gutter="16"> <a-row :gutter="16">
<a-col :span="12"> <a-col :span="12">
<a-form-item :label="'开始营业时间'" name="openTime"> <a-form-item :label="'开始营业时间'" name="openTime">
@ -130,9 +129,10 @@
<a-col :span="12"> <a-col :span="12">
<a-form-item :label="'营业状态'" name="businessStatus"> <a-form-item :label="'营业状态'" name="businessStatus">
<a-select v-model:value="formData.businessStatus"> <a-select v-model:value="formData.businessStatus">
<a-select-option value="open">营业中</a-select-option> <a-select-option v-for="item in dicsStore.dictOptions.Business_Status" :key="item.dval"
<a-select-option value="closed">已关闭</a-select-option> :value="item.dval">
<a-select-option value="suspended">暂停营业</a-select-option> {{ item.introduction }}
</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
</a-col> </a-col>
@ -162,7 +162,7 @@
</a-form-item> </a-form-item>
</a-col> </a-col>
<a-col :span="12"> <!-- <a-col :span="12">
<a-form-item :label="'是否有厨房'" name="hasKitchen"> <a-form-item :label="'是否有厨房'" name="hasKitchen">
<a-select v-model:value="formData.hasKitchen"> <a-select v-model:value="formData.hasKitchen">
<a-select-option value="yes"></a-select-option> <a-select-option value="yes"></a-select-option>
@ -201,12 +201,12 @@
<a-form-item :label="'日间照料中心名称'" name="daycareCenterName"> <a-form-item :label="'日间照料中心名称'" name="daycareCenterName">
<a-input v-model:value="formData.daycareCenterName" placeholder="请输入日间照料中心名称"></a-input> <a-input v-model:value="formData.daycareCenterName" placeholder="请输入日间照料中心名称"></a-input>
</a-form-item> </a-form-item>
</a-col> </a-col> -->
</a-row> </a-row>
</a-card> </a-card>
<!-- 图片上传区域 --> <!-- 图片上传区域 -->
<a-card class="mb-4" title="图片上传"> <a-card class="mb-4" title="图片上传" style="margin-top: 20px">
<a-row :gutter="16"> <a-row :gutter="16">
<a-col :span="12"> <a-col :span="12">
<a-form-item :label="'资质附件'" name="qualificationFiles"> <a-form-item :label="'资质附件'" name="qualificationFiles">
@ -240,11 +240,6 @@
@update:open="mapVisible = $event" @update:open="mapVisible = $event"
@handleGetLng="handleLocationChange" @handleGetLng="handleLocationChange"
@select="handleLocationSelect" /> @select="handleLocationSelect" />
<div v-if="selectedLocation">
<p>经纬度: {{ selectedLocation.lnglat }}</p>
<p>地址: {{ selectedLocation.address }}</p>
<p>名称: {{ selectedLocation.placeName }}</p>
</div>
</a-modal> </a-modal>
</template> </template>
@ -260,6 +255,8 @@ import { useI18n } from 'vue-i18n'
import storage from '@/utils/storage' import storage from '@/utils/storage'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import MapPickerModal from '@/components/Map/index.vue' import MapPickerModal from '@/components/Map/index.vue'
import { useDicsStore } from '@/store'
import AreaCascader from '@/components/AreaCascader/index.vue'
const emit = defineEmits(['ok']) const emit = defineEmits(['ok'])
const { t } = useI18n() // t const { t } = useI18n() // t
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal() const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
@ -378,6 +375,7 @@ const okText = ref(t('button.confirm'))
const platform = ref('') const platform = ref('')
const showMapPicker = ref(false) const showMapPicker = ref(false)
const location = ref('') const location = ref('')
const dicsStore = useDicsStore()
const handleLocationSelect = (lngLat) => { const handleLocationSelect = (lngLat) => {
console.log('确认选择:', lngLat) console.log('确认选择:', lngLat)