feat: 区域管理
This commit is contained in:
parent
c5b4c69b82
commit
97be31a587
|
@ -91,5 +91,9 @@ export default [
|
||||||
path: VideoSharePath,
|
path: VideoSharePath,
|
||||||
component: () => import('@/views/media/Device/Channel/Share/index.vue')
|
component: () => import('@/views/media/Device/Channel/Share/index.vue')
|
||||||
},
|
},
|
||||||
AccountMenu
|
AccountMenu,
|
||||||
|
{
|
||||||
|
path: '/system/region',
|
||||||
|
component: () => import('@/views/system/Region/index.vue')
|
||||||
|
},
|
||||||
]
|
]
|
|
@ -0,0 +1,92 @@
|
||||||
|
<template>
|
||||||
|
<j-tree
|
||||||
|
class="draggable-tree"
|
||||||
|
draggable
|
||||||
|
block-node
|
||||||
|
v-if="treeData.length"
|
||||||
|
:tree-data="treeData"
|
||||||
|
@dragenter="onDragEnter"
|
||||||
|
@drop="onDrop"
|
||||||
|
/>
|
||||||
|
<j-empty v-else style="margin-top: 150px" />
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
const treeData = ref([]);
|
||||||
|
|
||||||
|
const onDragEnter = (info) => {
|
||||||
|
// console.log(info);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDrop = (info) => {
|
||||||
|
// console.log(info);
|
||||||
|
// const dropKey = info.node.key;
|
||||||
|
// const dragKey = info.dragNode.key;
|
||||||
|
// const dropPos = info.node.pos.split('-');
|
||||||
|
// const dropPosition =
|
||||||
|
// info.dropPosition - Number(dropPos[dropPos.length - 1]);
|
||||||
|
// const loop = (data: any, key: string | number, callback: any) => {
|
||||||
|
// data.forEach((item, index) => {
|
||||||
|
// if (item.key === key) {
|
||||||
|
// return callback(item, index, data);
|
||||||
|
// }
|
||||||
|
// if (item.children) {
|
||||||
|
// return loop(item.children, key, callback);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
// const data = [...gData.value];
|
||||||
|
// // Find dragObject
|
||||||
|
// let dragObj: TreeDataItem;
|
||||||
|
// loop(
|
||||||
|
// data,
|
||||||
|
// dragKey,
|
||||||
|
// (item: TreeDataItem, index: number, arr: TreeProps['treeData']) => {
|
||||||
|
// arr.splice(index, 1);
|
||||||
|
// dragObj = item;
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
// if (!info.dropToGap) {
|
||||||
|
// // Drop on the content
|
||||||
|
// loop(data, dropKey, (item: TreeDataItem) => {
|
||||||
|
// item.children = item.children || [];
|
||||||
|
// /// where to insert 示例添加到头部,可以是随意位置
|
||||||
|
// item.children.unshift(dragObj);
|
||||||
|
// });
|
||||||
|
// } else if (
|
||||||
|
// (info.node.children || []).length > 0 && // Has children
|
||||||
|
// info.node.expanded && // Is expanded
|
||||||
|
// dropPosition === 1 // On the bottom gap
|
||||||
|
// ) {
|
||||||
|
// loop(data, dropKey, (item: TreeDataItem) => {
|
||||||
|
// item.children = item.children || [];
|
||||||
|
// // where to insert 示例添加到头部,可以是随意位置
|
||||||
|
// item.children.unshift(dragObj);
|
||||||
|
// });
|
||||||
|
// } else {
|
||||||
|
// let ar: TreeProps['treeData'] = [];
|
||||||
|
// let i = 0;
|
||||||
|
// loop(
|
||||||
|
// data,
|
||||||
|
// dropKey,
|
||||||
|
// (
|
||||||
|
// _item: TreeDataItem,
|
||||||
|
// index: number,
|
||||||
|
// arr: TreeProps['treeData'],
|
||||||
|
// ) => {
|
||||||
|
// ar = arr;
|
||||||
|
// i = index;
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
// if (dropPosition === -1) {
|
||||||
|
// ar.splice(i, 0, dragObj);
|
||||||
|
// } else {
|
||||||
|
// ar.splice(i + 1, 0, dragObj);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// gData.value = data;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
<template>
|
||||||
|
<j-modal
|
||||||
|
:maskClosable="false"
|
||||||
|
width="650px"
|
||||||
|
:visible="true"
|
||||||
|
:title="!!data?.id ? '编辑区域' : '新增区域'"
|
||||||
|
@ok="handleSave"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
:confirmLoading="loading"
|
||||||
|
>
|
||||||
|
<div style="margin-top: 10px">
|
||||||
|
<j-form :layout="'vertical'" ref="formRef" :model="modelRef">
|
||||||
|
<j-form-item name="productId" label="上级区域">
|
||||||
|
<j-select
|
||||||
|
showSearch
|
||||||
|
v-model:value="modelRef.productId"
|
||||||
|
placeholder="1级区域不需要选择"
|
||||||
|
>
|
||||||
|
<j-select-option
|
||||||
|
:value="item.id"
|
||||||
|
v-for="item in productList"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
>{{ item.name }}</j-select-option
|
||||||
|
>
|
||||||
|
</j-select>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item name="type" label="添加方式">
|
||||||
|
<j-radio-group
|
||||||
|
v-model:value="modelRef.type"
|
||||||
|
button-style="solid"
|
||||||
|
>
|
||||||
|
<a-radio-button value="a">内置行政区</a-radio-button>
|
||||||
|
<a-radio-button value="b">自定义数据</a-radio-button>
|
||||||
|
</j-radio-group>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item>
|
||||||
|
<j-select
|
||||||
|
showSearch
|
||||||
|
v-model:value="modelRef.productId"
|
||||||
|
placeholder="1级区域不需要选择"
|
||||||
|
>
|
||||||
|
<j-select-option
|
||||||
|
:value="item.id"
|
||||||
|
v-for="item in productList"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
>{{ item.name }}</j-select-option
|
||||||
|
>
|
||||||
|
</j-select>
|
||||||
|
<j-checkbox v-model:checked="modelRef.productId">同步添加下一级区域</j-checkbox>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item
|
||||||
|
label="区域名称"
|
||||||
|
name="name"
|
||||||
|
:rules="[
|
||||||
|
{
|
||||||
|
max: 200,
|
||||||
|
message: '最多输入200个字符',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<j-textarea
|
||||||
|
v-model:value="modelRef.describe"
|
||||||
|
placeholder="请输入说明"
|
||||||
|
showCount
|
||||||
|
:maxlength="200"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</j-form>
|
||||||
|
</div>
|
||||||
|
</j-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, watch, reactive } from 'vue';
|
||||||
|
|
||||||
|
const emit = defineEmits(['close', 'save']);
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: undefined,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const productList = ref<Record<string, any>[]>([]);
|
||||||
|
const loading = ref<boolean>(false);
|
||||||
|
|
||||||
|
const formRef = ref();
|
||||||
|
|
||||||
|
const modelRef = reactive({
|
||||||
|
productId: undefined,
|
||||||
|
id: undefined,
|
||||||
|
name: '',
|
||||||
|
describe: '',
|
||||||
|
type: 'a',
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.data,
|
||||||
|
(newValue) => {
|
||||||
|
Object.assign(modelRef, newValue);
|
||||||
|
},
|
||||||
|
{ immediate: true, deep: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('close');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSave = () => {
|
||||||
|
formRef.value
|
||||||
|
.validate()
|
||||||
|
.then(async (_data: any) => {
|
||||||
|
loading.value = true;
|
||||||
|
})
|
||||||
|
.catch((err: any) => {
|
||||||
|
console.log('error', err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,64 @@
|
||||||
|
<template>
|
||||||
|
<page-container>
|
||||||
|
<div class="region">
|
||||||
|
<div class="left">
|
||||||
|
<j-input-search
|
||||||
|
v-model:value="searchValue"
|
||||||
|
placeholder="请输入区域名称或行政区划代码"
|
||||||
|
@search="onSearch"
|
||||||
|
/>
|
||||||
|
<j-button @click="onAdd" type="primary" class="btn">新增区域</j-button>
|
||||||
|
<LeftTree />
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
地图
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Save v-if="visible" :data="current" @save="onSave" @close="onClose" />
|
||||||
|
</page-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="RegionMange">
|
||||||
|
import LeftTree from './LeftTree/index.vue'
|
||||||
|
import Save from './Save/index.vue'
|
||||||
|
|
||||||
|
const searchValue = ref()
|
||||||
|
const visible = ref<boolean>(false)
|
||||||
|
const current = ref<any>({})
|
||||||
|
|
||||||
|
const onSearch = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const onAdd = () => {
|
||||||
|
visible.value = true
|
||||||
|
current.value = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSave = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const onClose = () => {
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.region {
|
||||||
|
display: flex;
|
||||||
|
gap: 24px;
|
||||||
|
|
||||||
|
.left {
|
||||||
|
width: 300px;
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
width: 100%;
|
||||||
|
margin: 18px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.right {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue