nursing_unit_vue/src/views/services/serviceDirective/ConfigServiceDirectiveList.vue

1545 lines
59 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>
<div class="p-2">
<!--查询区域-->
<div class="jeecg-basic-table-form-container">
<a-form ref="formRef" @keyup.enter.native="searchQuery" :model="queryParam" :label-col="labelCol"
:wrapper-col="wrapperCol">
<a-row :gutter="24">
<a-col :lg="6">
<a-form-item name="directiveName">
<template #label><span title="服务指令">服务指令</span></template>
<JInput v-model:value="queryParam.directiveName" placeholder="请输入服务指令名称" allowClear />
</a-form-item>
</a-col>
<a-col :xl="6" :lg="7" :md="8" :sm="24">
<span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
<a-col :lg="6">
<a-button type="primary" preIcon="ant-design:search-outlined" @click="searchQuery">查询</a-button>
<a-button type="primary" preIcon="ant-design:reload-outlined" @click="searchReset"
style="margin-left: 8px">重置</a-button>
</a-col>
</span>
</a-col>
</a-row>
</a-form>
</div>
<div>
<div
style="width:350px;float: left;height:80vh; background: white; overflow:auto;position: relative;margin-right: 14px;border-radius: 8px;">
<div
style="position: absolute; top: 8px; right: 8px; z-index: 1; background: white; padding: 0px; border-radius: 4px;">
<a-radio-group v-model:value="filterIzEnabled" @change="searchQuery">
<a-radio-button value="all">全部</a-radio-button>
<a-radio-button value="enabled">启用</a-radio-button>
</a-radio-group>
</div>
<!-- <div v-if="treeLoading"
style="width: 350px; height: 20vh; display: flex; justify-content: center; align-items: center;">
<a-spin tip="加载中..."></a-spin>
</div> -->
<a-empty v-if="!treeLoading && treeLoading" />
<a-button v-if="!treeLoading && treeData.length < 1" type="link" class="btnPrivate" @click="addInstruction"
v-show="mainOrgCode == ownOrgCode" preIcon="ant-design:plus-outlined">新增分类标签</a-button>
<a-menu v-model:openKeys="openKeys" v-model:selectedKeys="selectedKeys" style="width: 100%;margin-top: 50px;"
mode="inline" @openChange="onOpenChange">
<template v-for="item in treeData">
<!-- 第一层判断是否有下级 -->
<a-sub-menu v-if="item.children && item.children.length > 0" :key="item.key"
@titleClick="handleTreeSelect([], { node: item })">
<template #icon>
<Icon :icon="item.icon" :size="20" v-if="item.icon" />
<Icon icon="ant-design:appstore-add-outlined" :size="20" v-else />
</template>
<template #title>
<span @mouseenter="item.showContent = true" @mouseleave="item.showContent = false">{{ item?.title }}
<span v-if="item?.izEnabled == '1' && item.level != 5" style="color:red;">(已停用)</span>
<span v-show="item.showContent">
<!-- 下拉菜单 -->
<a-dropdown :open="menuState[item?.key]?.open" @openChange="onMenuOpenChange(item.key, $event)">
<template #overlay>
<a-menu>
<a-menu-item v-for="itemMenu in menuItems(item)" :key="itemMenu.key"
:disabled="!itemMenu.canAdd" class="nu-menu-item"
@click="() => { closeAllMenus(); itemMenu.action(item) }">
<Icon style="color:#1890FF;" :icon="itemMenu.icon" class="action-icon"></Icon>
<span style=" color:#1890FF;margin-left: 5px;">{{ itemMenu.label }}</span>
</a-menu-item>
</a-menu>
</template>
<!-- 图标 -->
<Icon v-show="item.showContent" style="color:#1890FF;" :icon="iconClass(item.level)"
class="action-icon" @mouseenter="onNodeIconEnter(item, item.children)"
@mouseleave="onNodeIconLeave(item)" />
</a-dropdown>
</span>
</span>
</template>
<!-- 第二层判断是否有下级 -->
<template v-for="child in item.children">
<a-sub-menu :key="child.key" v-if="child.children && child.children.length > 0"
@titleClick="handleTreeSelect([], { node: child })">
<!-- <template #icon>
<Icon icon="ant-design:border-verticle-outlined" :size="20" />
</template> -->
<template #title>
<span @mouseenter="child.showContent = true" @mouseleave="child.showContent = false">{{ child?.title
}}
<span v-if="child?.izEnabled == '1' && child.level != 5" style="color:red;">(已停用)</span>
<span v-show="child.showContent">
<!-- 下拉菜单 -->
<a-dropdown :open="menuState[child?.key]?.open"
@openChange="onMenuOpenChange(child.key, $event)">
<template #overlay>
<a-menu>
<a-menu-item v-for="itemMenu in menuItems(child)" :key="itemMenu.key"
:disabled="!itemMenu.canAdd" class="nu-menu-item"
@click="() => { closeAllMenus(); itemMenu.action(child) }">
<Icon style="color:#1890FF;" :icon="itemMenu.icon" class="action-icon"></Icon>
<span style=" color:#1890FF;margin-left: 5px;">{{ itemMenu.label }}</span>
</a-menu-item>
</a-menu>
</template>
<!-- 图标 -->
<Icon style="color:#1890FF;" :icon="iconClass(child.level)" class="action-icon"
@mouseenter="onNodeIconEnter(child, child.children)" @mouseleave="onNodeIconLeave(child)" />
</a-dropdown>
</span>
</span>
</template>
<!-- 第三层判断是否有下级 -->
<template v-for="childThree in child.children">
<a-sub-menu :key="childThree.key" v-if="childThree.children && childThree.children.length > 0"
@titleClick="handleTreeSelect([], { node: childThree })">
<!-- <template #icon>
<Icon icon="ant-design:border-bottom-outlined" :size="20" />
</template> -->
<template #title>
<span @mouseenter="childThree.showContent = true"
@mouseleave="childThree.showContent = false">{{ childThree?.title }}
<span v-if="childThree?.izEnabled == '1' && childThree.level != 5"
style="color:red;">(已停用)</span>
<span v-show="childThree.showContent">
<!-- 下拉菜单 -->
<a-dropdown :open="menuState[childThree?.key]?.open"
@openChange="onMenuOpenChange(childThree.key, $event)">
<template #overlay>
<a-menu>
<a-menu-item v-for="itemMenu in menuItems(childThree)" :key="itemMenu.key"
:disabled="!itemMenu.canAdd" class="nu-menu-item"
@click="() => { closeAllMenus(); itemMenu.action(childThree) }">
<Icon style="color:#1890FF;" :icon="itemMenu.icon" class="action-icon"></Icon>
<span style=" color:#1890FF;margin-left: 5px;">{{ itemMenu.label }}</span>
</a-menu-item>
</a-menu>
</template>
<!-- 图标 -->
<Icon style="color:#1890FF;" :icon="iconClass(childThree.level)" class="action-icon"
@mouseenter="onNodeIconEnter(childThree, childThree.children)"
@mouseleave="onNodeIconLeave(childThree)" />
</a-dropdown>
</span>
</span>
</template>
<!-- 第四层判断是否有下级 -->
<a-menu-item :key="childFour.key" v-for="childFour in childThree.children"
@click="handleTreeSelect([], { node: childFour })">
<span @mouseenter="childFour.showContent = true" @mouseleave="childFour.showContent = false"
class="auto-wrap">{{ childFour?.title + '(' + childFour?.cycleTypeName + ')' }}
<span v-if="childFour?.izEnabled == '1' && childFour.level != 5"
style="color:red;">(已停用)</span>
<span v-show="childFour.showContent">
<!-- 下拉菜单 -->
<a-dropdown :open="menuState[childFour?.key]?.open"
@openChange="onMenuOpenChange(childFour.key, $event)">
<template #overlay>
<a-menu>
<a-menu-item v-for="itemMenu in menuItems(childFour)" :key="itemMenu.key"
:disabled="!itemMenu.canAdd" class="nu-menu-item"
@click="() => { closeAllMenus(); itemMenu.action(childFour) }">
<Icon style="color:#1890FF;" :icon="itemMenu.icon" class="action-icon"></Icon>
<span style=" color:#1890FF;margin-left: 5px;">{{ itemMenu.label }}</span>
</a-menu-item>
</a-menu>
</template>
<!-- 图标 -->
<Icon style="color:#1890FF;" :icon="iconClass(childFour.level)" class="action-icon"
@mouseenter="onNodeIconEnter(childFour, childFour.children)"
@mouseleave="onNodeIconLeave(childFour)" />
</a-dropdown>
</span>
</span>
</a-menu-item>
</a-sub-menu>
<a-menu-item :key="childThree.key" v-if="!childThree.children || childThree.children.length < 1"
@click="handleTreeSelect([], { node: childThree })">
<!-- <template #icon>
<Icon icon="ant-design:border-bottom-outlined" :size="20" />
</template> -->
<span @mouseenter="childThree.showContent = true" @mouseleave="childThree.showContent = false">{{
childThree?.title }}
<span v-if="childThree?.izEnabled == '1' && childThree.level != 5"
style="color:red;">(已停用)</span>
<span v-show="childThree.showContent">
<!-- 下拉菜单 -->
<a-dropdown :open="menuState[childThree?.key]?.open"
@openChange="onMenuOpenChange(childThree.key, $event)">
<template #overlay>
<a-menu>
<a-menu-item v-for="itemMenu in menuItems(childThree)" :key="itemMenu.key"
:disabled="!itemMenu.canAdd" class="nu-menu-item"
@click="() => { closeAllMenus(); itemMenu.action(childThree) }">
<Icon style="color:#1890FF;" :icon="itemMenu.icon" class="action-icon"></Icon>
<span style=" color:#1890FF;margin-left: 5px;">{{ itemMenu.label }}</span>
</a-menu-item>
</a-menu>
</template>
<!-- 图标 -->
<Icon style="color:#1890FF;" :icon="iconClass(childThree.level)" class="action-icon"
@mouseenter="onNodeIconEnter(childThree, childThree.children)"
@mouseleave="onNodeIconLeave(childThree)" />
</a-dropdown>
</span>
</span>
</a-menu-item>
</template>
</a-sub-menu>
<a-menu-item :key="child.key" v-if="!child.children || child.children.length < 1"
@click="handleTreeSelect([], { node: child })">
<!-- <template #icon>
<Icon icon="ant-design:border-verticle-outlined" :size="20" />
</template> -->
<span @mouseenter="child.showContent = true" @mouseleave="child.showContent = false">{{ child?.title
}}
<span v-if="child?.izEnabled == '1' && child.level != 5" style="color:red;">(已停用)</span>
<span v-show="child.showContent">
<!-- 下拉菜单 -->
<a-dropdown :open="menuState[child?.key]?.open" @openChange="onMenuOpenChange(child.key, $event)">
<template #overlay>
<a-menu>
<a-menu-item v-for="itemMenu in menuItems(child)" :key="itemMenu.key"
:disabled="!itemMenu.canAdd" class="nu-menu-item"
@click="() => { closeAllMenus(); itemMenu.action(child) }">
<Icon style="color:#1890FF;" :icon="itemMenu.icon" class="action-icon"></Icon>
<span style=" color:#1890FF;margin-left: 5px;">{{ itemMenu.label }}</span>
</a-menu-item>
</a-menu>
</template>
<!-- 图标 -->
<Icon style="color:#1890FF;" :icon="iconClass(child.level)" class="action-icon"
@mouseenter="onNodeIconEnter(child, child.children)" @mouseleave="onNodeIconLeave(child)" />
</a-dropdown>
</span>
</span>
</a-menu-item>
</template>
</a-sub-menu>
<a-menu-item :key="item.key" v-if="!item.children || item.children.length < 1"
@click="handleTreeSelect([], { node: item })">
<template #icon>
<Icon :icon="item.icon" :size="20" v-if="item.icon" />
<Icon icon="ant-design:appstore-add-outlined" :size="20" v-else />
</template>
<span @mouseenter="item.showContent = true" @mouseleave="item.showContent = false">{{ item?.title }}
<span v-if="item?.izEnabled == '1' && item.level != 5" style="color:red;">(已停用)</span>
<span v-show="item.showContent">
<!-- 下拉菜单 -->
<a-dropdown :open="menuState[item?.key]?.open" @openChange="onMenuOpenChange(item.key, $event)">
<template #overlay>
<a-menu>
<a-menu-item v-for="itemMenu in menuItems(item)" :key="itemMenu.key"
:disabled="!itemMenu.canAdd" class="nu-menu-item"
@click="() => { closeAllMenus(); itemMenu.action(item) }">
<Icon style="color:#1890FF;" :icon="itemMenu.icon" class="action-icon"></Icon>
<span style=" color:#1890FF;margin-left: 5px;">{{ itemMenu.label }}</span>
</a-menu-item>
</a-menu>
</template>
<!-- 图标 -->
<Icon v-show="item.showContent" style="color:#1890FF;" :icon="iconClass(item.level)"
class="action-icon" @mouseenter="onNodeIconEnter(item, item.children)"
@mouseleave="onNodeIconLeave(item)" />
</a-dropdown>
</span>
</span>
</a-menu-item>
</template>
</a-menu>
<!-- <a-tree class="container-height" style="padding-top: 40px;" v-if="!treeLoading && treeData.length > 0"
:tree-data="treeData" v-model:expandedKeys="expandedKeys" expandAction="click" @select="handleTreeSelect">
<template #title="{ data }">
<span class="node-title" @mouseenter="onNodeEnter(data, data.children, $event)"
@mouseleave="onNodeLeave(data)">
<Icon icon="ant-design:appstore-add-outlined" :size="20" v-if="data.level == 1" style="margin-right: 5px;"/>
<span v-if="data.level == 4">{{ data?.title + '(' + data?.cycleTypeName + ')' }}</span>
<span v-else>{{ data?.title }}</span>
<span v-if="data?.izEnabled == '1' && data.level != 5" style="color:red;">(已停用)</span>
<a-dropdown :open="menuState[data?.key]?.open" @openChange="onMenuOpenChange(data.key, $event)">
<template #overlay>
<a-menu>
<a-menu-item v-for="item in menuItems(data)" :key="item.key" :disabled="!item.canAdd"
class="nu-menu-item" @click="() => { closeAllMenus(); item.action(data) }">
<Icon style="color:#1890FF;" :icon="item.icon" class="action-icon"></Icon>
<span style=" color:#1890FF;margin-left: 5px;">{{ item.label }}</span>
</a-menu-item>
</a-menu>
</template>
<Icon v-show="data.showIcon && data.level != 5" style="color:#1890FF;" :icon="iconClass(data.level)"
class="action-icon" @mouseenter="onNodeIconEnter(data, data.children)"
@mouseleave="onNodeIconLeave(data)" />
</a-dropdown>
</span>
</template>
</a-tree> -->
</div>
<div style="width:calc(100% - 370px);float: left; background-color: white;border-radius: 8px;"
class="container-height">
<!--引用表格-->
<BasicTable @register="registerTable">
<!--插槽:table标题-->
<template #tableTitle>
<!-- <a-button type="primary" class="btnPrivate" @click="handleinstructionTag"
preIcon="tabler:settings">配置分类标签</a-button>
<a-button type="primary" class="btnPrivate" @click="handleCategory"
preIcon="tabler:settings">配置服务类别</a-button>
<a-button type="primary" class="btnPrivate" @click="handleType" preIcon="tabler:settings">配置服务类型</a-button> -->
<!-- <a-button type="primary" class="btnPrivate" @click="handleBodyTag"
preIcon="tabler:settings">配置体型标签</a-button>
<a-button type="primary" class="btnPrivate" @click="handleEmotionTag"
preIcon="tabler:settings">配置情绪标签</a-button> -->
<!-- <a-button type="primary" class="btnPrivate" @click="handleAdd"
preIcon="ant-design:plus-outlined">新增服务指令</a-button> -->
<a-button type="primary" @click="handleDirectiveMainOpen" v-show="isShowDM"
preIcon="ant-design:profile-outlined">标准指令库</a-button>
<a-button type="primary" preIcon="ant-design:eye-outlined" v-show="ownOrgCode == mainOrgCode"
@click="handleCompare">差异比对</a-button>
<a-button type="primary" preIcon="ant-design:eye-outlined" v-show="ownOrgCode == mainOrgCode"
@click="handleLookNewDirectives">差异指令</a-button>
<!-- <a-button type="primary" @click="handleBatchAdd" preIcon="ant-design:plus-outlined">批量新增</a-button>
<a-button type="primary" @click="onAbnormalListOpen" preIcon="ant-design:edit-twotone">停用指令</a-button> -->
</template>
<!--操作栏-->
<template #action="{ record }">
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
</template>
<template v-slot:bodyCell="{ column, record, index, text }">
<!-- 音频播放控制 -->
<template v-if="column.dataIndex === 'mp3File'">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button v-else type="link" class="btnPrivate" @click="openAudioModal(text)">播放</a-button>
</template>
<!-- <template v-if="column.dataIndex === 'previewFile'">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<img v-else :src="getFileAccessHttpUrl(text)" alt="图片不存在" class="cellIamge" />
</template> -->
<!-- <template v-if="column.dataIndex === 'mp3File'">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<div v-else style="display: flex; align-items: center; gap: 8px;">
<audio ref="audioPlayer" :src="getFileAccessHttpUrl(text)" hidden></audio>
<a-button v-if="!currentPlayingAudio || currentPlayingAudio !== text" type="link" @click="playAudio(text)"
preIcon="ant-design:play-circle-outlined">
播放
</a-button>
<template v-else>
<a-button v-if="isPlaying" type="link" @click="pauseAudio" preIcon="ant-design:pause-circle-outlined">
暂停
</a-button>
<a-button v-else type="link" @click="resumeAudio" preIcon="ant-design:play-circle-outlined">
播放
</a-button>
<a-button type="link" @click="restartAudio" preIcon="ant-design:reload-outlined">
重播
</a-button>
<a-button type="link" @click="stopAudio" preIcon="ant-design:stop-outlined">
停止
</a-button>
</template>
</div>
</template> -->
<template v-if="column.dataIndex === 'mp4File'">
<span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
<a-button v-else type="link" class="btnPrivate" @click="openVideoModal(text)">播放</a-button>
</template>
<template v-if="column.dataIndex === 'bodyTagList'">
<span :title="text.map((item) => item.tagName).join('、')">{{text.map((item) =>
item.tagName).join('、')}}</span>
</template>
<template v-if="column.dataIndex === 'emotionTagList'">
<span :title="text.map((item) => item.tagName).join('、')">{{text.map((item) =>
item.tagName).join('、')}}</span>
</template>
</template>
</BasicTable>
</div>
</div>
<!-- 表单区域 -->
<ConfigServiceDirectiveModal ref="registerModal" @success="handleSuccess"
:isMain="!!mainOrgCode && !!ownOrgCode && mainOrgCode == ownOrgCode">
</ConfigServiceDirectiveModal>
</div>
<!-- 分类标签 -->
<a-drawer title="分类标签" width="60vw" :open="insTagOpen" @close="onInsTagClose">
<template #footer>
<a-button type="primary" @click="onInsTagClose" style="float: right;">关闭</a-button>
</template>
<InstructionTag v-if="insTagOpen"></InstructionTag>
</a-drawer>
<!-- 服务类别 -->
<a-drawer title="服务类别" width="60vw" :open="categoryOpen" @close="onCategoryClose">
<template #footer>
<a-button type="primary" @click="onCategoryClose" style="float: right;">关闭</a-button>
</template>
<ConfigServiceCategoryList v-if="categoryOpen"></ConfigServiceCategoryList>
</a-drawer>
<!-- 服务类型 -->
<a-drawer title="服务类型" width="60vw" :open="typeOpen" @close="onTypeClose">
<template #footer>
<a-button type="primary" @click="onTypeClose" style="float: right;">关闭</a-button>
</template>
<ConfigServiceTypeList v-if="typeOpen"></ConfigServiceTypeList>
</a-drawer>
<!-- 体型标签 -->
<!-- <a-drawer title="体型标签" width="60vw" :open="bodyTagOpen" @close="onBodyTagClose">
<template #footer>
<a-button type="primary" @click="onBodyTagClose" style="float: right;">关闭</a-button>
</template>
<BodyTagList v-if="bodyTagOpen"></BodyTagList>
</a-drawer> -->
<!-- 情绪标签 -->
<!-- <a-drawer title="情绪标签" width="60vw" :open="emotionTagOpen" @close="onEmotionTagClose">
<template #footer>
<a-button type="primary" @click="onEmotionTagClose" style="float: right;">关闭</a-button>
</template>
<EmotionTagList v-if="emotionTagOpen"></EmotionTagList>
</a-drawer> -->
<!-- 差异比对 -->
<a-drawer title="差异比对" width="80vw" :open="compareListOpen" @close="onCompareListClose"
:footer-style="{ textAlign: 'right' }" :bodyStyle="{ padding: '0' }">
<template #footer>
<a-button type="primary" @click="onCompareListClose" style="margin-right: 10px;">关闭</a-button>
</template>
<CompareDirectiveList ref="compareListRef" v-if="compareListOpen" :ownOrgCode="ownOrgCode" :ownOrgName="ownOrgName">
</CompareDirectiveList>
</a-drawer>
<!-- 批量新增 -->
<a-drawer title="批量新增" width="80vw" :open="batchAddOpen" @close="onBatchAddClose"
:footer-style="{ textAlign: 'right' }" :bodyStyle="{ padding: '0' }">
<template #footer>
<a-button type="primary" @click="onBatchAddClose" style="margin-right: 10px;">关闭</a-button>
<a-button type="primary" @click="onBatchAddSubmit">确认</a-button>
</template>
<DirectiveMediaList ref="dmRef" :ownOrgCode="ownOrgCode" v-if="batchAddOpen"></DirectiveMediaList>
</a-drawer>
<!-- 停用指令 -->
<a-drawer title="停用指令" width="85vw" :open="abnormalListOpen" @close="onAbnormalListClose"
:footer-style="{ textAlign: 'right' }" :bodyStyle="{ padding: '0' }">
<template #footer>
<a-button type="primary" @click="onAbnormalListClose" style="margin-right: 10px;">关闭</a-button>
</template>
<AbnormalDirectiveList ref="abnormalListRef" v-if="abnormalListOpen"></AbnormalDirectiveList>
</a-drawer>
<!-- 差异指令 -->
<a-drawer v-model:visible="newDirectiveVisible" title="差异指令" width="85vw" :footer-style="{ textAlign: 'right' }"
:bodyStyle="{ height: '80vh', display: 'flex', padding: '0', flexDirection: 'column', overflow: 'auto' }"
wrapClassName="org-list-modal" @cancel="handleCancelNewDirective">
<template #footer>
<a-button @click="handleCancelNewDirective" type="primary">关闭</a-button>
<!-- <a-button @click="handleAsyncNewDirective" type="primary">同步</a-button> -->
</template>
<div style="padding:0px 8px;">
<CanAddDirectiveList ref="canAddDirectiveRef" :directiveMainOrgInfo="directiveMainOrgInfo"
:existDirectiveIds="existDirectiveIds" @refreshExistIds="refreshDMExistedIds"></CanAddDirectiveList>
</div>
</a-drawer>
<!-- 音频播放 -->
<a-modal v-model:visible="showAudioModal" title="音频播放" :footer="null" @cancel="closeAudioModal"
:bodyStyle="{ padding: '0', maxHeight: '80vh', overflow: 'auto' }" :keyboard="true">
<audio ref="audioPlayer" controls style="width: 100%; display: block; margin: 20px auto;">
<source :src="audioUrl">
您的浏览器不支持音频播放。
</audio>
</a-modal>
<!-- 视频播放 -->
<a-modal v-model:visible="showVideoModal" title="视频播放" :footer="null" @cancel="closeVideoModal"
:bodyStyle="{ padding: '0', maxHeight: '80vh', overflow: 'auto' }">
<video ref="videoPlayer" controls style="width: 100%; max-height: 70vh; display: block; margin: 0 auto;">
<source :src="videoUrl">
您的浏览器不支持视频播放
</video>
</a-modal>
<!-- 分类标签 -->
<InstructionTagModal ref="insRegisterModal" @success="reloadTree"></InstructionTagModal>
<ConfigServiceCategoryModal ref="catRegisterModal" @success="reloadTree"></ConfigServiceCategoryModal>
<ConfigServiceTypeModal ref="typRegisterModal" @success="reloadTree"></ConfigServiceTypeModal>
</template>
<script lang="ts" name="serviceDirective-configServiceDirective" setup>
import { ref, reactive, watch, onMounted, computed, nextTick } from 'vue';
import { BasicTable, TableAction } from '/@/components/Table';
import { useListPage } from '/@/hooks/system/useListPage';
import { columns, superQuerySchema } from './ConfigServiceDirective.data';
import { list, batchAdd, deleteOne, batchDelete, getImportUrl, getExportUrl, tree } from './ConfigServiceDirective.api';
import ConfigServiceDirectiveModal from './components/ConfigServiceDirectiveModal.vue'
import { useUserStore } from '/@/store/modules/user';
import JInput from "/@/components/Form/src/jeecg/components/JInput.vue";
import JDictSelectTag from '/@/components/Form/src/jeecg/components/JDictSelectTag.vue';
import { cloneDeep } from "lodash-es";
import ConfigServiceCategoryList from '../serviceCategory/ConfigServiceCategoryList.vue';
import InstructionTag from '../instructiontag/InstructionTag.vue';
import ConfigServiceTypeList from '../serviceType/ConfigServiceTypeList.vue';
import BodyTagList from '/@/views/services/directivetag/bodytag/BodyTagList.vue';
import EmotionTagList from '/@/views/services/directivetag/emotiontag/EmotionTagList.vue';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { Empty } from 'ant-design-vue';
import InstructionTagModal from '/@/views/services/InstructionTag/components/InstructionTagModal.vue'
import ConfigServiceCategoryModal from '/@/views/services/serviceCategory/components//ConfigServiceCategoryModal.vue'
import ConfigServiceTypeModal from '/@/views/services/serviceType/components//ConfigServiceTypeModal.vue'
import DirectiveMediaList from '/@/views/services/directivemedia/DirectiveMediaList.vue'
import { queryByKey } from '/@/views/admin/sysconfig/SysConfig.api'
import { getOrgInfo } from '@/api/common/api'
import { useMessage } from '/@/hooks/web/useMessage';
import AbnormalDirectiveList from './components/AbnormalDirectiveList.vue'
import CompareDirectiveList from './components/CompareDirectiveList.vue'
import { idListByDS } from './ConfigServiceDirective.api';
import CanAddDirectiveList from '/@/views/services/canadddirective/CanAddDirectiveList.vue'
const { createMessage, createConfirm } = useMessage();
const opeMediaAddress = import.meta.env.VITE_OPE_MEDIA_ADDRESS
const canAddDirectiveRef = ref()
const existDirectiveIds = ref([])//指令库已存在指令id
const insRegisterModal = ref();
const catRegisterModal = ref();
const typRegisterModal = ref();
const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE;
const formRef = ref();
const batchAddOpen = ref(false)
const dmRef = ref()
const abnormalListOpen = ref(false)
const abnormalListRef = ref()
const newDirectiveVisible = ref(false)
const compareListRef = ref()
const compareListOpen = ref(false)
const queryParam = reactive<any>({
instructionTagId: '',
categoryId: '',
typeId: '',
izEnabled: '0',
});
watch(
() => queryParam.instructionTagId,
() => {
queryParam.categoryId = ''
queryParam.typeId = ''
}
)
// 当服务类别变动,清空服务类型
watch(
() => queryParam.categoryId,
() => {
queryParam.typeId = ''
}
)
const toggleSearchStatus = ref<boolean>(false);
const registerModal = ref();
const treeData = ref<any>([]);
const userStore = useUserStore();
const isShowDM = ref(false)//是否展示指令库功能
const selectedKeys = ref<any>([]);
const openKeys = ref<any>([]);
//注册table数据
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: {
title: '服务指令',
api: list,
columns,
canResize: false,
useSearchForm: false,
showIndexColumn: true,
scroll: { y: '58vh' },
pagination: {
current: 1,
pageSize: 15,
pageSizeOptions: ['15', '50', '70', '100'],
},
actionColumn: {
width: 70,
fixed: 'right',
},
beforeFetch: async (params) => {
params.column = 'createTime'
params.order = 'desc'
let rangerQuery = await setRangeQuery();
return Object.assign(params, rangerQuery);
},
},
exportConfig: {
name: "服务指令",
url: getExportUrl,
params: queryParam,
},
importConfig: {
url: getImportUrl,
success: handleSuccess
},
});
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] = tableContext;
const labelCol = reactive({
xs: 24,
sm: 4,
xl: 6,
xxl: 4
});
const wrapperCol = reactive({
xs: 24,
sm: 20,
});
// 高级查询配置
const superQueryConfig = reactive(superQuerySchema);
const insTagOpen = ref(false)//分类标签抽屉
const categoryOpen = ref(false)//服务类别抽屉
const typeOpen = ref(false)//服务类型抽屉
const bodyTagOpen = ref(false)//体型标签抽屉
const emotionTagOpen = ref(false)//情绪标签抽屉
const mainOrgCode = ref()//指令库编码
const ownOrgCode = ref('') //本机构编码
const ownOrgName = ref('') //本机构名称
const filterIzEnabled = ref('enabled')//筛选全部/已启用
const directiveMainOrgInfo = ref()
function onOpenChange(record: string[]) {
console.log("🚀 ~ onOpenChange ~ record:", record)
selectedKeys.value = record
// const latestOpenKey = record.find(key => state.openKeys.indexOf(key) === -1);
// if (state.rootSubmenuKeys.indexOf(latestOpenKey!) === -1) {
// state.openKeys = openKeys;
// } else {
// state.openKeys = latestOpenKey ? [latestOpenKey] : [];
// }
}
/**
* 高级查询事件
*/
function handleSuperQuery(params) {
Object.keys(params).map((k) => {
queryParam[k] = params[k];
});
searchQuery();
}
/**
* 新增事件
*/
function handleAdd() {
registerModal.value.disableSubmit = false;
registerModal.value.opeType = 'add';
registerModal.value.add();
}
/**
* 编辑事件
*/
function handleEdit(record: Recordable) {
registerModal.value.disableSubmit = false;
registerModal.value.opeType = 'edit';
registerModal.value.edit(record);
}
/**
* 编辑指令资源
*/
function handleMedia(record: Recordable) {
registerModal.value.disableSubmit = false;
registerModal.value.opeType = 'editMedia';
registerModal.value.editMedia(record);
}
/**
* 详情
*/
function handleDetail(record: Recordable) {
registerModal.value.disableSubmit = true;
registerModal.value.opeType = 'look';
registerModal.value.edit(record);
}
/**
* 成功回调
*/
function handleSuccess() {
(selectedRowKeys.value = []) && reload();
reloadTree()
}
/**
* 操作栏
*/
function getTableAction(record) {
return [
{
label: '详情',
onClick: handleDetail.bind(null, record),
},
// {
// label: '编辑',
// onClick: handleEdit.bind(null, record)
// },
// {
// label: '指令资源',
// onClick: handleMedia.bind(null, record)
// },
];
}
/**
* 下拉操作栏
*/
function getDropDownAction(record) {
return [
]
}
function expandTreeNodeToLevel4(directiveData: any) {
console.log("🚀 ~ expandTreeNodeToLevel4 ~ directiveData:", directiveData)
selectedKeys.value = [directiveData.instructionTagId, directiveData.categoryId, directiveData.typeId, directiveData.id]
openKeys.value = [directiveData.instructionTagId, directiveData.categoryId, directiveData.typeId, directiveData.id]
// // 清空之前展开的节点
// expandedKeys.value = [];
// // 递归查找并展开相应的节点
// const findAndExpandNode = (nodes: any[], level: number, directiveData: any) => {
// for (const node of nodes) {
// // 判断当前节点的 level 是否与 directiveData 的级别匹配
// if (level === 1 && node.instructionId === directiveData.instructionTagId) {
// expandedKeys.value.push(node.key);
// if (node.children && node.children.length > 0) {
// findAndExpandNode(node.children, 2, directiveData);
// }
// } else if (level === 2 && node.categoryId === directiveData.categoryId) {
// expandedKeys.value.push(node.key);
// if (node.children && node.children.length > 0) {
// findAndExpandNode(node.children, 3, directiveData);
// }
// } else if (level === 3 && node.typeId === directiveData.typeId) {
// expandedKeys.value.push(node.key);
// if (node.children && node.children.length > 0) {
// findAndExpandNode(node.children, 4, directiveData);
// }
// } else if (level === 4 && node.key === directiveData.id) {
// expandedKeys.value.push(node.key);
// }
// }
// };
// // 调用递归方法,从树的根节点开始查找
// findAndExpandNode(treeData.value, 1, directiveData);
}
/**
* 查询
*/
function searchQuery(reloadTree = true, resetId = true) {
if (!!queryParam.directiveName || !!queryParam.bodyTags || !!queryParam.emotionTags) {
queryParam.instructionTagId = '';
queryParam.categoryId = '';
queryParam.typeId = '';
}
if (resetId) {
queryParam.id = ''
}
if (filterIzEnabled.value == 'enabled') {
queryParam.izEnabled = '0'
} else {
queryParam.izEnabled = ''
}
reload().then(async res => {
if (reloadTree) {
await initTree();
}
if (res.length == 1) {
expandTreeNodeToLevel4(res[0])
}
})
}
/**
* 重置
*/
function searchReset() {
formRef.value.resetFields(); // 重置表单字段
selectedRowKeys.value = []; // 清空选中的行
// 清空 queryParam 中相关字段
queryParam.instructionTagId = '';
queryParam.categoryId = '';
queryParam.typeId = '';
queryParam.directiveName = ''; // 如果你有其他需要清除的字段,也可以加到这里
queryParam.bodyTags = '';
queryParam.emotionTags = '';
queryParam.id = '';
// queryParam.izEnabled = '';
// 刷新数据
reload().then(() => {
initTree();
});
}
let rangeField = 'tollPrice,comPrice,'
/**
* 设置范围查询条件
*/
async function setRangeQuery() {
let queryParamClone = cloneDeep(queryParam);
if (rangeField) {
let fieldsValue = rangeField.split(',');
fieldsValue.forEach(item => {
if (queryParamClone[item]) {
let range = queryParamClone[item];
queryParamClone[item + '_begin'] = range[0];
queryParamClone[item + '_end'] = range[1];
delete queryParamClone[item];
} else {
queryParamClone[item + '_begin'] = '';
queryParamClone[item + '_end'] = '';
}
})
}
return queryParamClone;
}
//分类标签抽屉打开
function handleinstructionTag() {
insTagOpen.value = true
}
//服务类别抽屉打开
function handleCategory() {
categoryOpen.value = true
}
//服务类型抽屉打开
function handleType() {
typeOpen.value = true
}
//体型标签抽屉打开
function handleBodyTag() {
bodyTagOpen.value = true
}
//情绪标签抽屉打开
function handleEmotionTag() {
emotionTagOpen.value = true
}
//分类标签抽屉关闭
function onInsTagClose() {
insTagOpen.value = false
}
//服务类别抽屉关闭
function onCategoryClose() {
categoryOpen.value = false
}
//服务类型抽屉关闭
function onTypeClose() {
typeOpen.value = false
}
//体型标签抽屉关闭
function onBodyTagClose() {
bodyTagOpen.value = false
}
//体型标签抽屉关闭
function onEmotionTagClose() {
emotionTagOpen.value = false
}
const showAudioModal = ref(false); // 控制音频模态框显示
const audioUrl = ref(''); // 音频 URL
const audioPlayer = ref(null);
// 打开音频模态框
const openAudioModal = (url) => {
audioUrl.value = opeMediaAddress + url;
showAudioModal.value = true;
};
// 关闭音频模态框
const closeAudioModal = () => {
if (audioPlayer.value) {
audioPlayer.value.pause(); // 暂停音频播放
audioPlayer.value.currentTime = 0; // 可选:重置播放进度
}
showAudioModal.value = false;
audioUrl.value = '';
};
const showVideoModal = ref(false); // 控制模态框显示
const videoUrl = ref(''); // 视频 URL
const videoPlayer = ref(null);
// 打开视频模态框
const openVideoModal = (url) => {
videoUrl.value = opeMediaAddress + url;
showVideoModal.value = true;
};
// 关闭视频模态框
const closeVideoModal = () => {
if (videoPlayer.value) {
videoPlayer.value.pause(); // 暂停视频播放
videoPlayer.value.currentTime = 0; // 可选:将播放进度重置到开始
}
showVideoModal.value = false;
videoUrl.value = '';
};
// 添加以下响应式变量
const currentPlayingAudio = ref<string | null>(null);
const isPlaying = ref(false);
// 添加音频控制方法
const playAudio = (url: string) => {
if (currentPlayingAudio.value && currentPlayingAudio.value !== url) {
// 如果正在播放其他音频,先停止
stopAudio();
}
currentPlayingAudio.value = url;
isPlaying.value = true;
// 确保audio元素存在
if (audioPlayer.value) {
audioPlayer.value.src = getFileAccessHttpUrl(url);
audioPlayer.value.play().catch(e => {
isPlaying.value = false;
currentPlayingAudio.value = null;
});
}
};
const pauseAudio = () => {
if (audioPlayer.value) {
audioPlayer.value.pause();
isPlaying.value = false;
}
};
const resumeAudio = () => {
if (audioPlayer.value) {
audioPlayer.value.play().catch(e => {
});
isPlaying.value = true;
}
};
const restartAudio = () => {
if (audioPlayer.value) {
audioPlayer.value.currentTime = 0;
audioPlayer.value.play().catch(e => {
});
isPlaying.value = true;
}
};
const stopAudio = () => {
if (audioPlayer.value) {
audioPlayer.value.pause();
audioPlayer.value.currentTime = 0;
isPlaying.value = false;
currentPlayingAudio.value = null;
}
};
const clickCount = ref(0);
const treeChildData = ref<any>([]);
const expandedKeys = ref<string[]>([]);
// 为每个 node 维护一个菜单状态和 hover 定时器
const menuState = reactive<Record<string, { timer?: number, openedByClick: boolean, open: boolean }>>({
})
function onNodeEnter(node, level, event) {
node.showIcon = true
}
function onNodeLeave(node) {
node.showIcon = false
}
function onNodeIconEnter(node, level) {
// 检查当前节点是否已经展开,如果是,则跳过关闭所有菜单的操作
const key = node.key;
const currentMenuState = menuState[key];
if (currentMenuState?.open) {
// 当前菜单已经展开,直接返回
return;
}
// 如果没有菜单状态,则初始化
if (!menuState[key]) {
menuState[key] = { openedByClick: false, open: false };
}
// 只有前三级需要自动展开
if (level <= 3 && !menuState[key].openedByClick) {
menuState[key].timer = window.setTimeout(() => {
menuState[key].open = true;
}, 2000);
}
}
function onNodeIconLeave(node) {
const s = menuState[node.key]
if (s?.timer) {
clearTimeout(s.timer)
delete s.timer
}
}
// 用户点击图标手动打开
function openMenu(node, level, ev) {
closeAllMenus();
const key = node.key
if (!menuState[key]) menuState[key] = { openedByClick: false, open: false }
menuState[key].openedByClick = true
menuState[key].open = true
}
// 当 Dropdown 自身触发 openChange比如点击外部关闭同步状态
function onMenuOpenChange(key: string, open: boolean) {
if (!menuState[key]) menuState[key] = { open: false, openedByClick: false }
menuState[key].open = open
// 如果是外部关闭,则重置 clicked 状态
if (!open) menuState[key].openedByClick = false
}
// 关闭所有菜单工具函数
function closeAllMenus() {
Object.keys(menuState).forEach(k => {
menuState[k].open = false
menuState[k].openedByClick = false
})
}
// 根据层级返回图标 class
function iconClass(level: number) {
switch (level) {
case 1: return 'ant-design:setting-twotone'
case 2: return 'ant-design:setting-twotone'
case 3: return 'ant-design:setting-twotone'
case 4: return 'ant-design:setting-outlined'
default: return 'ant-design:setting-outlined'
}
}
//新增分类标签
function addInstruction() {
insRegisterModal.value.disableSubmit = false;
insRegisterModal.value.add();
}
//启用分类标签
function usingInstruction(data) {
createConfirm({
iconType: 'warning',
title: '操作确认',
content: '此操作会同时启用分类标签“' + data.title + '”下所有服务类别、服务类型、服务指令!' + '是否确认启用分类标签“' + data.title + '”!',
okText: '启用',
cancelText: '取消',
onOk: () => {
insRegisterModal.value.usingOrStop(data.instructionId, '0', false)
catRegisterModal.value.usingOrStopByCascade(data.instructionId, '0', false)
typRegisterModal.value.usingOrStopByCascade(data.instructionId, '', '0', false)
registerModal.value.usingOrStopByCascade(data.instructionId, '', '', '0', true)
}
});
}
//停用分类标签
function stopInstruction(data) {
createConfirm({
iconType: 'warning',
title: '操作确认',
content: '此操作会同时停用分类标签“' + data.title + '”下所有服务类别、服务类型、服务指令!' + '是否确认停用分类标签“' + data.title + '”!',
okText: '停用',
cancelText: '取消',
onOk: () => {
insRegisterModal.value.usingOrStop(data.instructionId, '1', false)
catRegisterModal.value.usingOrStopByCascade(data.instructionId, '1', false)
typRegisterModal.value.usingOrStopByCascade(data.instructionId, '', '1', false)
registerModal.value.usingOrStopByCascade(data.instructionId, '', '', '1', true)
}
});
}
function editInstruction(data) {
insRegisterModal.value.disableSubmit = false;
insRegisterModal.value.edit(data);
}
//新增服务类别
function addCategory(data) {
catRegisterModal.value.disableSubmit = false;
catRegisterModal.value.edit({ instructionId: data.instructionId });
}
//启用服务类别
function usingCategory(data) {
createConfirm({
iconType: 'warning',
title: '操作确认',
content: '此操作会同时启用服务类别“' + data.title + '”下所有服务类型、服务指令!' + '是否确认启用服务类别“' + data.title + '”!',
okText: '启用',
cancelText: '取消',
onOk: () => {
catRegisterModal.value.usingOrStop(data.categoryId, '0', false)
typRegisterModal.value.usingOrStopByCascade('', data.categoryId, '0', false)
registerModal.value.usingOrStopByCascade('', data.categoryId, '', '0', true)
}
});
}
//停用服务类别
function stopCategory(data) {
createConfirm({
iconType: 'warning',
title: '操作确认',
content: '此操作会同时停用服务类别“' + data.title + '”下所有服务类型、服务指令!' + '是否确认停用服务类别“' + data.title + '”!',
okText: '停用',
cancelText: '取消',
onOk: () => {
catRegisterModal.value.usingOrStop(data.categoryId, '1', false)
typRegisterModal.value.usingOrStopByCascade('', data.categoryId, '1', false)
registerModal.value.usingOrStopByCascade('', data.categoryId, '', '1', true)
}
});
}
//新增服务类型
function addType(data) {
typRegisterModal.value.disableSubmit = false;
typRegisterModal.value.edit({ instructionId: data.instructionId, categoryId: data.categoryId });
}
//启用服务类型
function usingType(data) {
createConfirm({
iconType: 'warning',
title: '操作确认',
content: '此操作会同时启用服务类型“' + data.title + '”下所有服务指令!' + '是否确认启用服务类型“' + data.title + '”!',
okText: '启用',
cancelText: '取消',
onOk: () => {
typRegisterModal.value.usingOrStop(data.typeId, '0', false)
registerModal.value.usingOrStopByCascade('', '', data.typeId, '0', true)
}
});
}
//停用服务类型
function stopType(data) {
createConfirm({
iconType: 'warning',
title: '操作确认',
content: '此操作会同时停用服务类型“' + data.title + '”下所有服务指令!' + '是否确认停用服务类型“' + data.title + '”!',
okText: '停用',
cancelText: '取消',
onOk: () => {
typRegisterModal.value.usingOrStop(data.typeId, '1', false)
registerModal.value.usingOrStopByCascade('', '', data.typeId, '1', true)
}
});
}
//新增服务指令
function addDirective(data) {
registerModal.value.disableSubmit = false;
registerModal.value.opeType = 'add';
registerModal.value.edit({ instructionTagId: data.instructionId, categoryId: data.categoryId, typeId: data.typeId });
}
//编辑务指令
function editDirective(data) {
registerModal.value.disableSubmit = false;
registerModal.value.opeType = 'edit';
registerModal.value.queryByIdFunc(data.key);
}
//指令资源
function editMedia(data) {
registerModal.value.disableSubmit = false;
registerModal.value.opeType = 'editMedia';
registerModal.value.queryAndEditMedia(data.key);
}
//启用服务指令
function usingDirective(data) {
registerModal.value.usingOrStop(data.key, '0', true);
}
//停用服务指令
function stopDirective(data) {
registerModal.value.usingOrStop(data.key, '1', true);
}
//查看体型标签
function bodyTagsDetail(data) {
}
//查看情绪标签
function emotionTagsDetail(data) {
}
// 根据层级返回菜单项
function menuItems(data) {
if (data.level === 1) {
const items = [
]
if (!!mainOrgCode.value && mainOrgCode.value == ownOrgCode.value) {
items.push({ key: 'addIns', label: '新增分类标签', icon: 'ant-design:plus-outlined', canAdd: true && !!mainOrgCode.value && mainOrgCode.value == ownOrgCode.value, action: addInstruction },)
}
if (data.canAdd) {
items.push({ key: 'addCat', label: '新增服务类别', icon: 'ant-design:plus-outlined', canAdd: data.canAdd, action: addCategory })
}
if (data.izEnabled === '1') {
items.push({ key: 'usingIns', label: '启用分类标签', icon: 'ant-design:check-circle-outlined', canAdd: true, action: usingInstruction })
} else if (data.izEnabled === '0') {
items.push({ key: 'stopIns', label: '停用分类标签', icon: 'ant-design:stop-outlined', canAdd: true, action: stopInstruction })
}
items.push({ key: 'editIns', label: '修改图标', icon: 'ant-design:edit-outlined', canAdd: true, action: editInstruction },)
return items
}
else if (data.level === 2) {
const items = [
{ key: 'addCat', label: '新增服务类别', icon: 'ant-design:plus-outlined', canAdd: data.parentLevelEnabled, action: addCategory },
]
if (data.canAdd) {
items.push({ key: 'addTyp', label: '新增服务类型', icon: 'ant-design:plus-outlined', canAdd: data.canAdd, action: addType })
}
if (data.izEnabled === '1') {
items.push({ key: 'usingCat', label: '启用服务类别', icon: 'ant-design:check-circle-outlined', canAdd: data.parentLevelEnabled, action: usingCategory })
} else if (data.izEnabled === '0') {
items.push({ key: 'stopCat', label: '停用服务类别', icon: 'ant-design:stop-outlined', canAdd: data.parentLevelEnabled, action: stopCategory })
}
return items
}
else if (data.level === 3) {
const items = [
{ key: 'addTyp', label: '新增服务类型', icon: 'ant-design:plus-outlined', canAdd: data.parentLevelEnabled, action: addType },
]
if (data.canAdd) {
items.push({ key: 'addDir', label: '新增服务指令', icon: 'ant-design:plus-outlined', canAdd: data.canAdd, action: addDirective })
}
if (data.izEnabled === '1') {
items.push({ key: 'usingTyp', label: '启用服务类型', icon: 'ant-design:check-circle-outlined', canAdd: data.parentLevelEnabled, action: usingType })
} else if (data.izEnabled === '0') {
items.push({ key: 'stopTyp', label: '停用服务类型', icon: 'ant-design:stop-outlined', canAdd: data.parentLevelEnabled, action: stopType })
}
return items
}
else if (data.level === 4) {
const items = [
{ key: 'editDir', label: '编辑服务指令', icon: 'ant-design:edit-outlined', canAdd: data.canAdd && data.izEnabled == '0', action: editDirective },
{ key: 'editMedia', label: '编辑指令资源', icon: 'ant-design:edit-outlined', canAdd: data.canAdd && data.izEnabled == '0' && mainOrgCode.value == ownOrgCode.value, action: editMedia },
]
// if (data.canAdd) {
// items.push({ key: 'addDir', label: '新增服务指令', icon: 'ant-design:plus-outlined', canAdd: data.canAdd , action: addDirective })
// }
if (data.izEnabled === '1') {
items.push({ key: 'usingDir', label: '启用服务指令', icon: 'ant-design:check-circle-outlined', canAdd: data.canAdd, action: usingDirective })
} else if (data.izEnabled === '0') {
items.push({ key: 'stopDir', label: '停用服务指令', icon: 'ant-design:stop-outlined', canAdd: data.canAdd, action: stopDirective })
}
if (data?.bodyTagList?.length > 0) {
items.push({ key: 'bodyTagsDetail', label: '查看体型标签', icon: 'ant-design:stop-outlined', canAdd: true, action: bodyTagsDetail })
}
if (data?.emotionTagList?.length > 0) {
items.push({ key: 'emotionTagsDetail', label: '查看情绪标签', icon: 'ant-design:stop-outlined', canAdd: true, action: emotionTagsDetail })
}
return items
}
return []
}
// 递归取每级第一个 key
function setDefaultExpanded(nodes: any[]) {
// expandedKeys.value.push(nodes[0].key)
// expandedKeys.value.push(nodes[0]?.children?.[0]?.key)
// expandedKeys.value.push(nodes[0]?.children?.[0]?.children?.[0]?.key)
}
const treeLoading = ref(false)
function reloadTree() {
tree({ filterIzEnabled: filterIzEnabled.value }).then(res => {
treeData.value = res;
})
}
function handleTreeSelect(selectedKeys: string[], { node }: any) {
const level = node.level;
// 清空不必要的查询条件
queryParam.directiveName = '';
queryParam.bodyTags = '';
queryParam.emotionTags = '';
queryParam.id = ''
// queryParam.izEnabled = '';
// 根据节点级别设置查询条件
switch (level) {
case 1: // 分类标签
queryParam.instructionTagId = node.instructionId;
queryParam.categoryId = '';
queryParam.typeId = '';
break;
case 2: // 服务类别
queryParam.instructionTagId = node.instructionId;
queryParam.categoryId = node.categoryId;
queryParam.typeId = '';
break;
case 3: // 服务类型
queryParam.instructionTagId = node.instructionId;
queryParam.categoryId = node.categoryId;
queryParam.typeId = node.typeId;
break;
case 4: // 服务指令
// 四级节点特殊处理:设置指令名称
queryParam.instructionTagId = node.instructionId;
queryParam.categoryId = node.categoryId;
queryParam.typeId = node.typeId;
queryParam.directiveName = node.title;
queryParam.id = node.key
break;
}
if (level == 5) return
// 触发查询
searchQuery(false, level != 4);
}
async function initTree() {
treeLoading.value = true;
try {
const res = await tree({ filterIzEnabled: filterIzEnabled.value });
treeData.value = res;
expandedKeys.value = [];
// 默认展开每级第一个
// setDefaultExpanded(res);
} finally {
treeLoading.value = false;
}
}
/**
* 查看指令库
*/
function handleDirectiveMainOpen() {
registerModal.value?.openDM(mainOrgCode.value)
}
async function getDirectiveMainOrgCode() {
let { orgCode, orgName } = await getOrgInfo()
ownOrgCode.value = orgCode
ownOrgName.value = orgName
let { configValue } = await queryByKey({ key: 'directive_main_org_code' })
mainOrgCode.value = configValue
if (orgCode != configValue) isShowDM.value = true
}
function handleBatchAdd() {
batchAddOpen.value = true
nextTick(() => {
dmRef.value?.init()
})
}
function onBatchAddClose() {
batchAddOpen.value = false
}
function onBatchAddSubmit() {
batchAdd(dmRef.value?.selectedRows).then(res => {
createMessage.success('操作成功')
// filterIzEnabled.value = 'all'
searchQuery(true, true)
onBatchAddClose()
})
}
function onAbnormalListOpen() {
abnormalListOpen.value = true
nextTick(() => {
abnormalListRef.value?.reload()
})
}
function onAbnormalListClose() {
abnormalListOpen.value = false
searchQuery(true, true)
}
//刷新已有指令库
async function refreshDMExistedIds(dmOrgInfo, izReset = false, izQuery = true) {
let res = await idListByDS({ dataSourceCode: 'master' })
existDirectiveIds.value = res.records
if (izReset) {
canAddDirectiveRef.value?.searchReset()
} else {
canAddDirectiveRef.value?.reload()
}
}
async function handleLookNewDirectives() {
await refreshDMExistedIds(directiveMainOrgInfo.value, true)
newDirectiveVisible.value = true
}
/**
* 关闭新增指令
*/
function handleCancelNewDirective() {
newDirectiveVisible.value = false
}
/**
* 差异比对
*/
function handleCompare() {
compareListOpen.value = true
}
function onCompareListClose() {
compareListOpen.value = false
}
// 添加音频结束监听
onMounted(() => {
if (audioPlayer.value) {
audioPlayer.value.addEventListener('ended', () => {
isPlaying.value = false;
});
}
initTree()
getDirectiveMainOrgCode()
});
</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%;
}
}
audio::-webkit-media-controls-timeline {
display: none;
}
audio::-webkit-media-controls-current-time-display,
audio::-webkit-media-controls-time-remaining-display {
display: none;
}
.btnPrivate {
height: 40px;
margin-left: 4px;
}
.node-title {
display: inline-flex;
align-items: center;
}
.action-icon {
margin-left: 4px;
cursor: pointer;
}
:deep(.centered-dropdown) {
position: fixed;
left: 50% !important;
top: 50% !important;
transform: translate(-50%, -50%) !important;
max-height: 80vh;
overflow-y: auto;
.ant-dropdown-menu {
max-height: 70vh;
overflow-y: auto;
}
}
.container-height {
height: 77vh;
}
@media screen and (min-width: 1600px) and (min-height: 900px) {
.container-height {
height: 81.5vh;
}
}
:deep(.ant-menu-item-selected) {
color: #4b4b4b !important;
}
:deep(.ant-menu-submenu-title) {
color: #4b4b4b !important;
}
.auto-wrap {
word-wrap: break-word;
/* 长单词/URL换行 */
word-break: break-all;
/* 更激进的换行策略 */
white-space: normal;
/* 默认换行行为 */
line-height: 20px !important;
display: inline flow-root;
padding-top: 10px;
}
</style>