hldy_yunwei_vue/src/views/synchronization/nuBaseInfo/index.vue

297 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!--
selectedSize已选择条数
topTipText机构信息卡片收起时提示文字
showAddBtn:是否展示新增按钮
showSelectedArea:是否展示全部已选择未选择区域
hasSearchConditions是否存在搜索条件
viewTypeChanged源数据全部已选择未选择变更时的钩子函数
orgChanged机构变更钩子
handleAsync同步数据按钮
handleBatchAdd批量新增
-->
<SyncComponent ref="syncComRef" :syncType="'nuBaseInfo'" :selectedSize="listComRef?.getDataSource()?.length"
:syncTipText="'同步(全部)'" :leftTableML="'1px'" :rightTableML="'22px'" :batchRemoveText="'移除选中'"
:showBatchAddBtn="true" :leftListTipText="'已同步'" :rightListTipText="'待同步'" :showAddAllBtn="false"
:showAddBtn="true" :showResetDataBtn="false" :hasSearchConditions="hasSearchConditions" :topTipText="'点击展开机构详情'"
:screenModeTip_left="'已同步'" :screenModeTip_right="'待同步'" :showSelectedArea="false"
@viewTypeChanged="viewTypeChanged" @orgChanged="orgChanged" @handleAdd="handleAdd"
@handleBatchAdd="handleBatchAdd" @handleRemoveAll="handleRemoveAll" @handleAsync="handleAsync"
@handleReload="handleReload">
<!-- 业务机构数据列表 -->
<template #sourceTableSlot>
<a-table style="margin-top: 8px;" size="small" :columns="selectedColumns"
:dataSource="Array.from(selectedItems.values())" :pagination="false" :scroll="{ y: '55vh' }">
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'action'">
<a-popconfirm placement="left" ok-text="确认" cancel-text="取消"
@confirm="handleRemoveFromRight(record.id)">
<template #title>
<span>是否确认移除</span>
</template>
<a-button type="link" danger size="small"
:disabled="initialDataIds.includes(record.id)">移除</a-button>
</a-popconfirm>
</template>
<template v-else-if="column.dataIndex === 'mp3File'">
<span v-if="!record.mp3File" style="font-size: 12px;font-style: italic;">无文件</span>
<audio controls v-else style="width: 100%; max-width: 300px; height: 40px;">
<source :src="getFileAccessHttpUrl(record.mp3File)">
</audio>
</template>
<template v-else-if="column.dataIndex === 'mp4File'">
<span v-if="!record.mp4File" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button v-else type="primary" size="small" @click="openVideoModal(record.mp4File)">
播放视频
</a-button>
</template>
<template v-else-if="column.dataIndex === 'bodyTagList'">
<span v-if="!record.bodyTagList || record.bodyTagList.length === 0"
style="font-size: 12px;font-style: italic;">-</span>
<template v-else>
{{record.bodyTagList.map(item => item.tagName).join('、')}}
</template>
</template>
<template v-else-if="column.dataIndex === 'emotionTagList'">
<span v-if="!record.emotionTagList || record.emotionTagList.length === 0"
style="font-size: 12px;font-style: italic;">-</span>
<template v-else>
{{record.emotionTagList.map(item => item.tagName).join('、')}}
</template>
</template>
<template v-else-if="column.dataIndex === 'previewFileMedia'">
<span v-if="!record.previewFileMedia" style="font-size: 12px;font-style: italic;">无图片</span>
<img v-else :src="testOrgInfo.url + record.previewFileMedia"
style="max-width: 50px; max-height: 50px;" />
</template>
<template v-else-if="column.dataIndex === 'immediateFileMedia'">
<span v-if="!record.immediateFileMedia" style="font-size: 12px;font-style: italic;">无图片</span>
<img v-else :src="testOrgInfo.url + record.immediateFileMedia"
style="max-width: 50px; max-height: 50px;" />
</template>
</template>
</a-table>
</template>
<!-- 业务平台数据列表 -->
<template #businessTableSlot>
<NuBaseInfoList style="margin-top: -18px;" ref="listComRef" v-if="syncComRef?.orgData?.orgCode"
:key="syncComRef?.orgData?.orgCode" :orgCode="syncComRef?.orgData?.orgCode"></NuBaseInfoList>
</template>
</SyncComponent>
<a-modal v-model:visible="showVideoModal" title="视频播放" :footer="null" @cancel="closeVideoModal"
:bodyStyle="{ padding: '0', maxHeight: '80vh', overflow: 'auto' }">
<video controls style="width: 100%; max-height: '70vh'; display: block; margin: 0 auto;">
<source :src="videoUrl">
您的浏览器不支持视频播放
</video>
</a-modal>
</template>
<script setup name="synchronization-nubaseinfo" lang="ts">
/**
*说明
* 如何获取当前机构信息 syncComRef?.value?.orgData
*/
import { ref, reactive, computed, onBeforeMount } from 'vue'
import SyncComponent from '/@/components/Sync/SyncComponent.vue'
import { useMessage } from "/@/hooks/web/useMessage";
import { getOrgInfo } from '/@/api/common/api';
// 以下为护理单元引用:
import { list, asyncFunc, listByOrgCode } from './NuBaseInfo.api';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils'
import { selectedColumns } from './NuBaseInfo.data'
import NuBaseInfoList from './NuBaseInfoList.vue'
// >>>>>>>>>>>>>组件:无需处理代码
const { createMessage } = useMessage();
const syncComRef = ref(null)
const sourceOrgCode = import.meta.env.VITE_SYTJGBM
const labelCol = reactive({
xs: 24,
sm: 4,
xl: 6,
xxl: 5
});
const wrapperCol = reactive({
xs: 24,
sm: 20,
});
const testOrgInfo = ref({})
// <<<<<<<<<<<<<组件:无需处理代码
// >>>>>>>>>>>>>需要处理代码
const listComRef = ref();
const initialDataIds = ref<string[]>([]);//已到机构运营时候后,会记录初始化数据(业务系统已分配数据)
const selectedItems = ref(new Map<string | number, any>());//已选择数据
const queryParam = ref({ viewType: 'all' })//源数据查询参数
const showVideoModal = ref(false);
const videoUrl = ref('');
// 计算当前是否存在搜索条件
const hasSearchConditions = computed(() => {
return Object.keys(queryParam.value).some(key =>
key !== 'viewType' && queryParam.value[key] !== undefined && queryParam.value[key] !== ''
);
});
/**
* 机构变更
*/
const orgChanged = async (org) => {
// 清空当前选择
selectedItems.value.clear();
// 清空初始化数据
initialDataIds.value = [];
try {
// 加载新机构数据
const res = await listByOrgCode({ dataSourceCode: org.orgCode, pageNo: 1, pageSize: -1 });
// 如果有数据,更新右侧列表
if (res.records && res.records.length > 0) {
const newRecords = res.records;
newRecords.forEach(record => {
selectedItems.value.set(record.id, record);
if (!syncComRef?.value?.orgData?.operationStartTime || new Date() >= new Date(syncComRef?.value?.orgData?.operationStartTime)) {
initialDataIds.value.push(record.id);
}
});
// 更新左侧列表的选中状态
listComRef.value?.updateSelection?.(newRecords);
} else {
// 没有数据时也确保清空
selectedItems.value.clear();
listComRef.value?.updateSelection?.([]);
}
// 切换视图
syncComRef?.value?.resetOrgSelectedCon(false);
} catch (err) {
createMessage.error('机构数据查询失败');
// 失败时也确保清空状态
selectedItems.value.clear();
listComRef.value?.updateSelection?.([]);
}
}
/**
* 查询
*/
function searchQuery() {
listComRef.value.reload();
}
/**
* 重置
* 子组件代码会自动触发reload方法
* watch(() => props.queryParams, (newParams) => {
reload();
}, { deep: true });
*/
function searchReset() {
let vt = queryParam.value.viewType
queryParam.value = { viewType: vt }
}
/**
* 源数据的全部、已选择、未选择变更时触发
* @param v_ all、selected、unselected
*/
const viewTypeChanged = (v_) => {
queryParam.value.viewType = v_
//组件内部监听了queryParam值的变化自动刷新
}
const handleSelectChange = (items: Map<string | number, any>) => {
selectedItems.value = new Map(items);
};
const handleRemoveFromRight = (key: string | number) => {
selectedItems.value.delete(key);
listComRef.value?.removeSelectedItem?.(key);
};
const openVideoModal = (url: string) => {
videoUrl.value = getFileAccessHttpUrl(url);
showVideoModal.value = true;
};
const closeVideoModal = () => {
showVideoModal.value = false;
videoUrl.value = '';
};
//刷新数据
const handleReload = () => {
listComRef?.value?.reload();
orgChanged(syncComRef?.value?.orgData)
}
// 同步数据
const handleAsync = async () => {
await asyncFunc({ orgCode: syncComRef?.value?.orgData?.orgCode });
//刷新历史数据
syncComRef?.value?.refreshHistory()
createMessage.success("同步结果请在同步历史中查看!");
};
//新增
const handleAdd = () => {
listComRef.value.handleAdd();
}
//批量新增
const handleBatchAdd = () => {
listComRef.value.handleBatchAdd();
}
// 全部移除
const handleRemoveAll = () => {
listComRef?.value?.batchHandleDelete()
}
// <<<<<<<<<<<<<需要处理代码
onBeforeMount(() => {
getOrgInfo({ orgCode: import.meta.env.VITE_SYTJGBM }).then(res => {
testOrgInfo.value = res
})
})
</script>
<style lang="less" scoped>
.jeecg-basic-table-form-container {
padding: 0;
.table-page-search-submitButtons {
display: block;
margin-bottom: 24px;
white-space: nowrap;
}
.query-group-cust {
min-width: 100px !important;
}
.query-group-split-cust {
width: 30px;
display: inline-block;
text-align: center
}
.ant-form-item:not(.ant-form-item-with-help) {
margin-bottom: 16px;
height: 32px;
}
:deep(.ant-picker),
:deep(.ant-input-number) {
width: 100%;
}
}
.selected-list-container {
:deep(.ant-table) {
width: 100% !important;
max-width: 100%;
}
}
</style>