Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
2299ae271f
|
@ -4,8 +4,6 @@ import type { CascadeItem } from '@/views/media/Cascade/typings'
|
|||
export default {
|
||||
// 列表
|
||||
list: (data: any) => server.post<any>(`/media/gb28181-cascade/_query`, data),
|
||||
// 列表字段通道数量, 来自下面接口的total
|
||||
queryCount: (id: string) => server.post<any>(`/media/gb28181-cascade/${id}/bindings/_query`),
|
||||
// 详情
|
||||
detail: (id: string): any => server.get(`/media/gb28181-cascade/${id}`),
|
||||
// 新增
|
||||
|
@ -26,4 +24,17 @@ export default {
|
|||
// SIP本地地址
|
||||
all: () => server.get<any>(`/network/resources/alive/_all`),
|
||||
|
||||
// 查询已绑定的通道, list列表字段通道数量, 来自下面接口的total
|
||||
queryBindChannel: (id: string, data: any) => server.post<any>(`/media/gb28181-cascade/${id}/bindings/_query`, data),
|
||||
// 绑定通道
|
||||
bindChannel: (id: string, data: string[]) => server.post<any>(`/media/gb28181-cascade/${id}/_bind`, data),
|
||||
// 解绑
|
||||
unbindChannel: (id: string, data: string[]) => server.post<any>(`/media/gb28181-cascade/${id}/_unbind`, data),
|
||||
// 验证国标ID是否存在
|
||||
validateField: (id: string, data: string[]): any => server.post(`/media/gb28181-cascade/${id}/gbChannelId/_validate`, data),
|
||||
// 更改国标ID
|
||||
updateGbChannelId: (id: string, data: any): any => server.post(`/media/gb28181-cascade/binding/${id}`, data),
|
||||
// 查询通道分页列表
|
||||
queryChannelList: (data: any): any => server.post(`media/channel/_query`, data),
|
||||
|
||||
}
|
|
@ -75,7 +75,7 @@ watchEffect(() => {
|
|||
});
|
||||
|
||||
const insert = (val) => {
|
||||
if (!instance) return
|
||||
if (!instance) return;
|
||||
const position = instance.getPosition();
|
||||
instance.executeEdits(instance.getValue(), [
|
||||
{
|
||||
|
@ -88,17 +88,19 @@ const insert = (val) => {
|
|||
text: val,
|
||||
},
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
watch(() => props.modelValue,
|
||||
(val) => {
|
||||
instance.setValue(val)
|
||||
})
|
||||
// watch(
|
||||
// () => props.modelValue,
|
||||
// (val) => {
|
||||
// instance.setValue(val);
|
||||
// },
|
||||
// );
|
||||
|
||||
defineExpose({
|
||||
editorFormat,
|
||||
insert,
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -87,11 +87,11 @@ watchEffect(() => {
|
|||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import 'ant-design-vue/es/style/themes/default.less';
|
||||
// @import 'ant-design-vue/es/style/themes/default.less';
|
||||
|
||||
:root {
|
||||
--dialog-primary-color: @primary-color;
|
||||
}
|
||||
// :root {
|
||||
// --dialog-primary-color: @primary-color;
|
||||
// }
|
||||
|
||||
.dialog-item {
|
||||
display: flex;
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
<!-- 国标级联-绑定通道 -->
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:visible="_vis"
|
||||
title="绑定通道"
|
||||
cancelText="取消"
|
||||
okText="确定"
|
||||
width="80%"
|
||||
@ok="handleSave"
|
||||
@cancel="_vis = false"
|
||||
:confirmLoading="loading"
|
||||
>
|
||||
<Search
|
||||
type="simple"
|
||||
:columns="columns"
|
||||
target="media"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
|
||||
<JTable
|
||||
ref="listRef"
|
||||
model="table"
|
||||
:columns="columns"
|
||||
:request="CascadeApi.queryChannelList"
|
||||
:defaultParams="{
|
||||
sorts: [{ name: 'name', order: 'desc' }],
|
||||
terms: [
|
||||
{
|
||||
column: 'id',
|
||||
termType: 'cascade_channel$not',
|
||||
type: 'and',
|
||||
value: route.query.id,
|
||||
},
|
||||
{
|
||||
column: 'catalogType',
|
||||
termType: 'eq',
|
||||
type: 'and',
|
||||
value: 'device',
|
||||
},
|
||||
],
|
||||
}"
|
||||
:params="params"
|
||||
:rowSelection="{
|
||||
selectedRowKeys: _selectedRowKeys,
|
||||
onSelect: onSelectChange,
|
||||
onSelectAll: onSelectAllChange,
|
||||
}"
|
||||
@cancelSelect="_selectedRowKeys = []"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<h3>通道列表</h3>
|
||||
</template>
|
||||
<template #status="slotProps">
|
||||
<a-space>
|
||||
<a-badge
|
||||
:status="
|
||||
slotProps.status.value === 'online'
|
||||
? 'success'
|
||||
: 'error'
|
||||
"
|
||||
:text="slotProps.status.text"
|
||||
></a-badge>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import CascadeApi from '@/api/media/cascade';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { PropType } from 'vue';
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
type Emits = {
|
||||
(e: 'update:visible', data: boolean): void;
|
||||
(e: 'submit'): void;
|
||||
};
|
||||
const emit = defineEmits<Emits>();
|
||||
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, default: false },
|
||||
data: {
|
||||
type: Object as PropType<Partial<Record<string, any>>>,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
||||
const _vis = computed({
|
||||
get: () => props.visible,
|
||||
set: (val) => emit('update:visible', val),
|
||||
});
|
||||
|
||||
watch(
|
||||
() => _vis.value,
|
||||
(val) => {
|
||||
if (val) handleSearch({ terms: [] });
|
||||
},
|
||||
);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '设备名称',
|
||||
dataIndex: 'deviceName',
|
||||
key: 'deviceName',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '通道名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '安装地址',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '厂商',
|
||||
dataIndex: 'manufacturer',
|
||||
key: 'manufacturer',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '已连接', value: 'online' },
|
||||
{ label: '未连接', value: 'offline' },
|
||||
],
|
||||
handleValue: (v: any) => {
|
||||
return v;
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const params = ref<Record<string, any>>({});
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
* @param params
|
||||
*/
|
||||
const handleSearch = (e: any) => {
|
||||
params.value = e;
|
||||
console.log('params.value: ', params.value);
|
||||
};
|
||||
|
||||
const listRef = ref();
|
||||
const _selectedRowKeys = ref<string[]>([]);
|
||||
|
||||
const onSelectChange = (
|
||||
record: any[],
|
||||
selected: boolean,
|
||||
selectedRows: any[],
|
||||
) => {
|
||||
_selectedRowKeys.value = selected
|
||||
? [...getSetRowKey(selectedRows)]
|
||||
: _selectedRowKeys.value.filter((item: any) => item !== record?.id);
|
||||
};
|
||||
const onSelectAllChange = (
|
||||
selected: boolean,
|
||||
selectedRows: any[],
|
||||
changeRows: any[],
|
||||
) => {
|
||||
const unRowsKeys = getSelectedRowsKey(changeRows);
|
||||
_selectedRowKeys.value = selected
|
||||
? [...getSetRowKey(selectedRows)]
|
||||
: _selectedRowKeys.value
|
||||
.concat(unRowsKeys)
|
||||
.filter((item) => !unRowsKeys.includes(item));
|
||||
};
|
||||
const getSelectedRowsKey = (selectedRows: any[]) =>
|
||||
selectedRows.map((item) => item?.id).filter((i) => !!i);
|
||||
|
||||
const getSetRowKey = (selectedRows: any[]) =>
|
||||
new Set([..._selectedRowKeys.value, ...getSelectedRowsKey(selectedRows)]);
|
||||
|
||||
const loading = ref(false);
|
||||
const handleSave = async () => {
|
||||
if (!_selectedRowKeys.value.length) message.error('请勾选数据');
|
||||
loading.value = true;
|
||||
const resp = await CascadeApi.bindChannel(
|
||||
route.query.id as string,
|
||||
_selectedRowKeys.value,
|
||||
);
|
||||
loading.value = false;
|
||||
if (resp.success) {
|
||||
message.success('操作成功!');
|
||||
_vis.value = false;
|
||||
emit('submit');
|
||||
} else {
|
||||
message.error('操作失败!');
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,267 @@
|
|||
<!-- 国标级联-通道列表 -->
|
||||
<template>
|
||||
<page-container>
|
||||
<Search
|
||||
type="simple"
|
||||
:columns="columns"
|
||||
target="media"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
|
||||
<JTable
|
||||
ref="listRef"
|
||||
model="table"
|
||||
:columns="columns"
|
||||
:request="(e:any) => CascadeApi.queryBindChannel(route?.query.id as string, e)"
|
||||
:defaultParams="{
|
||||
sorts: [{ name: 'name', order: 'desc' }],
|
||||
}"
|
||||
:params="params"
|
||||
:rowSelection="{
|
||||
selectedRowKeys: _selectedRowKeys,
|
||||
onSelect: onSelectChange,
|
||||
onSelectAll: onSelectAllChange,
|
||||
}"
|
||||
@cancelSelect="_selectedRowKeys = []"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<h3>通道列表</h3>
|
||||
</template>
|
||||
<template #rightExtraRender>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="bindVis = true">
|
||||
绑定通道
|
||||
</a-button>
|
||||
<a-popconfirm
|
||||
title="确认解绑?"
|
||||
@confirm="handleMultipleUnbind"
|
||||
>
|
||||
<a-button> 批量解绑 </a-button>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #status="slotProps">
|
||||
<a-space>
|
||||
<a-badge
|
||||
:status="
|
||||
slotProps.status.value === 'online'
|
||||
? 'success'
|
||||
: 'error'
|
||||
"
|
||||
:text="slotProps.status.text"
|
||||
></a-badge>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
v-for="i in getActions(slotProps, 'table')"
|
||||
:key="i.key"
|
||||
v-bind="i.tooltip"
|
||||
>
|
||||
<a-popconfirm
|
||||
v-if="i.popConfirm"
|
||||
v-bind="i.popConfirm"
|
||||
:disabled="i.disabled"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-popconfirm>
|
||||
<a-button
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
v-else
|
||||
@click="i.onClick && i.onClick(slotProps)"
|
||||
>
|
||||
<a-button
|
||||
:disabled="i.disabled"
|
||||
style="padding: 0"
|
||||
type="link"
|
||||
><AIcon :type="i.icon"
|
||||
/></a-button>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
|
||||
<BindChannel v-model:visible="bindVis" @submit="listRef.reload()" />
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import CascadeApi from '@/api/media/cascade';
|
||||
import type { ActionsType } from '@/components/Table/index.vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import BindChannel from './BindChannel/index.vue';
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '设备名称',
|
||||
dataIndex: 'deviceName',
|
||||
key: 'deviceName',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '通道名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '国标ID',
|
||||
dataIndex: 'gbChannelId',
|
||||
key: 'gbChannelId',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '安装地址',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '厂商',
|
||||
dataIndex: 'manufacturer',
|
||||
key: 'manufacturer',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{ label: '已连接', value: 'online' },
|
||||
{ label: '未连接', value: 'offline' },
|
||||
],
|
||||
handleValue: (v: any) => {
|
||||
return v;
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
scopedSlots: true,
|
||||
},
|
||||
];
|
||||
|
||||
const params = ref<Record<string, any>>({});
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
* @param params
|
||||
*/
|
||||
const handleSearch = (e: any) => {
|
||||
params.value = e;
|
||||
console.log('params.value: ', params.value);
|
||||
};
|
||||
|
||||
const listRef = ref();
|
||||
const _selectedRowKeys = ref<string[]>([]);
|
||||
const bindVis = ref(false);
|
||||
|
||||
const onSelectChange = (
|
||||
record: any[],
|
||||
selected: boolean,
|
||||
selectedRows: any[],
|
||||
) => {
|
||||
_selectedRowKeys.value = selected
|
||||
? [...getSetRowKey(selectedRows)]
|
||||
: _selectedRowKeys.value.filter((item: any) => item !== record?.id);
|
||||
};
|
||||
const onSelectAllChange = (
|
||||
selected: boolean,
|
||||
selectedRows: any[],
|
||||
changeRows: any[],
|
||||
) => {
|
||||
const unRowsKeys = getSelectedRowsKey(changeRows);
|
||||
_selectedRowKeys.value = selected
|
||||
? [...getSetRowKey(selectedRows)]
|
||||
: _selectedRowKeys.value
|
||||
.concat(unRowsKeys)
|
||||
.filter((item) => !unRowsKeys.includes(item));
|
||||
};
|
||||
const getSelectedRowsKey = (selectedRows: any[]) =>
|
||||
selectedRows.map((item) => item?.id).filter((i) => !!i);
|
||||
|
||||
const getSetRowKey = (selectedRows: any[]) =>
|
||||
new Set([..._selectedRowKeys.value, ...getSelectedRowsKey(selectedRows)]);
|
||||
|
||||
/**
|
||||
* 表格操作按钮
|
||||
* @param data 表格数据项
|
||||
* @param type 表格展示类型
|
||||
*/
|
||||
const getActions = (
|
||||
data: Partial<Record<string, any>>,
|
||||
type: 'card' | 'table',
|
||||
): ActionsType[] => {
|
||||
if (!data) return [];
|
||||
const actions = [
|
||||
{
|
||||
key: 'delete',
|
||||
text: '解绑',
|
||||
tooltip: {
|
||||
title: '解绑',
|
||||
},
|
||||
icon: 'DisconnectOutlined',
|
||||
popConfirm: {
|
||||
title: '确认解绑?',
|
||||
onConfirm: async () => {
|
||||
const resp = await CascadeApi.unbindChannel(
|
||||
route.query.id as string,
|
||||
[data.channelId],
|
||||
);
|
||||
if (resp.success) {
|
||||
message.success('操作成功!');
|
||||
listRef.value?.reload();
|
||||
} else {
|
||||
message.error('操作失败!');
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
return actions;
|
||||
};
|
||||
|
||||
/**
|
||||
* 批量解绑
|
||||
*/
|
||||
const handleMultipleUnbind = async () => {
|
||||
const channelIds = listRef.value?._dataSource
|
||||
.filter((f: any) => _selectedRowKeys.value.includes(f.id))
|
||||
.map((m: any) => m.channelId);
|
||||
const resp = await CascadeApi.unbindChannel(
|
||||
route.query.id as string,
|
||||
channelIds,
|
||||
);
|
||||
if (resp.success) {
|
||||
message.success('操作成功!');
|
||||
listRef.value?.reload();
|
||||
} else {
|
||||
message.error('操作失败!');
|
||||
}
|
||||
};
|
||||
</script>
|
|
@ -197,12 +197,10 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import DeviceApi from '@/api/media/device';
|
||||
import CascadeApi from '@/api/media/cascade';
|
||||
import type { ActionsType } from '@/components/Table/index.vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import { PROVIDER_OPTIONS } from '@/views/media/Device/const';
|
||||
|
||||
import { useMenuStore } from 'store/menu';
|
||||
|
||||
|
@ -295,7 +293,7 @@ const handleSearch = (e: any) => {
|
|||
const lastValueFrom = async (params: any) => {
|
||||
const res = await CascadeApi.list(params);
|
||||
res.result.data.forEach(async (item: any) => {
|
||||
const resp = await queryBindChannel(item.id);
|
||||
const resp = await queryChannelCount(item.id);
|
||||
item.count = resp.result.total;
|
||||
});
|
||||
return res;
|
||||
|
@ -305,8 +303,8 @@ const lastValueFrom = async (params: any) => {
|
|||
* 查询通道数量
|
||||
* @param id
|
||||
*/
|
||||
const queryBindChannel = async (id: string) => {
|
||||
return await CascadeApi.queryCount(id);
|
||||
const queryChannelCount = async (id: string) => {
|
||||
return await CascadeApi.queryBindChannel(id, {});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -63,7 +63,7 @@ const handleClick = (type: string) => {
|
|||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
@import 'ant-design-vue/es/style/themes/default.less';
|
||||
// @import 'ant-design-vue/es/style/themes/default.less';
|
||||
|
||||
.scene-trigger-way-warp {display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
|
Loading…
Reference in New Issue