服务指令bug

This commit is contained in:
1378012178@qq.com 2025-08-07 16:24:07 +08:00
parent d473bd2220
commit 970d42f2ea
23 changed files with 334 additions and 128 deletions

View File

@ -20,6 +20,8 @@ VITE_GLOB_API_URL_PREFIX=
#微前端qiankun应用,命名必须以VITE_APP_SUB_开头,jeecg-app-1为子应用的项目名称,也是子应用的路由父路径
VITE_APP_SUB_jeecg-app-1 = '//localhost:8091'
# 业务平台所在服务器nginx中静态资源media对应的路径 开头结尾都要带斜杠
VITE_NGINX_MEDIA_LOCATION = '/media101/upFiles101/'
# 填写后将作为乾坤子应用启动主应用注册时AppName需保持一致放开 VITE_GLOB_QIANKUN_MICRO_APP_NAME 参数表示jeecg-vue3将以乾坤子应用模式启动
#VITE_GLOB_QIANKUN_MICRO_APP_NAME=jeecg-vue3

View File

@ -20,6 +20,8 @@ VITE_GLOB_API_URL_PREFIX=
#微前端qiankun应用,命名必须以VITE_APP_SUB_开头,jeecg-app-1为子应用的项目名称,也是子应用的路由父路径
VITE_APP_SUB_jeecg-app-1 = '//localhost:8092'
# 业务平台所在服务器nginx中静态资源media对应的路径 开头结尾都要带斜杠
VITE_NGINX_MEDIA_LOCATION = '/media102/upFiles102/'
# 填写后将作为乾坤子应用启动主应用注册时AppName需保持一致放开 VITE_GLOB_QIANKUN_MICRO_APP_NAME 参数表示jeecg-vue3将以乾坤子应用模式启动
#VITE_GLOB_QIANKUN_MICRO_APP_NAME=jeecg-vue3

View File

@ -20,6 +20,8 @@ VITE_GLOB_API_URL_PREFIX=
#微前端qiankun应用,命名必须以VITE_APP_SUB_开头,jeecg-app-1为子应用的项目名称,也是子应用的路由父路径
VITE_APP_SUB_jeecg-app-1 = '//localhost:8092'
# 业务平台所在服务器nginx中静态资源media对应的路径 开头结尾都要带斜杠
VITE_NGINX_MEDIA_LOCATION = '/media103/upFiles103/'
# 填写后将作为乾坤子应用启动主应用注册时AppName需保持一致放开 VITE_GLOB_QIANKUN_MICRO_APP_NAME 参数表示jeecg-vue3将以乾坤子应用模式启动
#VITE_GLOB_QIANKUN_MICRO_APP_NAME=jeecg-vue3

View File

@ -21,6 +21,8 @@ VITE_GLOB_DOMAIN_URL=https://www.focusnu.com/nursingunit103
# 接口父路径前缀
VITE_GLOB_API_URL_PREFIX=
# 业务平台所在服务器nginx中静态资源media对应的路径 开头结尾都要带斜杠
VITE_NGINX_MEDIA_LOCATION = '/media103/upFiles103/'
# 填写后将作为乾坤子应用启动主应用注册时AppName需保持一致放开 VITE_GLOB_QIANKUN_MICRO_APP_NAME 参数表示jeecg-vue3将以乾坤子应用模式启动
#VITE_GLOB_QIANKUN_MICRO_APP_NAME=jeecg-vue3

View File

@ -17,6 +17,8 @@ enum Api {
getCategoryData = '/sys/category/loadAllData',
getNuList = '/iot/tplink/cameraInfo/nuList',
getOrgInfo = '/sys/api/getOrgInfo',
getApiAddressByOrgCode = '/sys/api/getApiAddressByOrgCode',
getOrgUrlByOrgCode = '/sys/api/getOrgUrlByOrgCode',
}
/**
@ -27,6 +29,20 @@ export const getNuList = (params) => {
return defHttp.get({ url: Api.getNuList, params });
};
/**
* api接口地址
* @param params
*/
export const getApiAddressByOrgCode = (params) => {
return defHttp.get({ url: Api.getApiAddressByOrgCode, params });
};
/**
*
* @param params
*/
export const getOrgUrlByOrgCode = (params) => {
return defHttp.get({ url: Api.getOrgUrlByOrgCode, params });
};
/**
*
*/

View File

@ -9,7 +9,7 @@
<a-form-item label="服务类别" v-bind="validateInfos.categoryId" id="ConfigServiceDirectiveForm-categoryId"
name="categoryId">
<j-dict-select-tag type="list" v-model:value="formData.categoryId"
:dictCode="`nu_config_service_category,category_name,id,del_flag = 0 order by sort asc`"
:dictCode="`nu_config_service_category,category_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`"
placeholder="请选择服务类别" allow-clear />
</a-form-item>
</a-col>
@ -251,9 +251,9 @@ watch(
(newCategoryId) => {
if (!newCategoryId) {
formData.typeId = '';
typeDictCode.value = 'nu_config_service_type,type_name,id,del_flag = 99 order by sort asc';
typeDictCode.value = 'nu_config_service_type,type_name,id,1=2';
} else {
typeDictCode.value = `nu_config_service_type,type_name,id,del_flag = 0 and category_id = '${newCategoryId}' order by sort asc`;
typeDictCode.value = `nu_config_service_type,type_name,id,del_flag = 0 and iz_enabled = 0 and category_id = '${newCategoryId}' order by sort asc`;
}
}
);

View File

@ -17,7 +17,7 @@
<a-form-item name="categoryId">
<template #label><span title="服务类别">服务类别</span></template>
<j-dict-select-tag type="list" v-model:value="queryParam.categoryId"
:dictCode="`nu_config_service_category,category_name,id,del_flag = 0 order by sort asc`"
:dictCode="`nu_config_service_category,category_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`"
:ignoreDisabled="true" placeholder="请选择服务类别" allow-clear />
</a-form-item>
</a-col>
@ -25,8 +25,8 @@
<a-form-item name="typeId">
<template #label><span title="服务类型">服务类型</span></template>
<j-dict-select-tag type="list" v-model:value="queryParam.typeId"
:dictCode="`nu_config_service_type,type_name,id,del_flag = 0 and category_id = ${queryParam.categoryId || -1} order by sort asc`" placeholder="请选择服务类型"
:ignoreDisabled="true" allowClear />
:dictCode="`nu_config_service_type,type_name,id,del_flag = 0 and iz_enabled = 0 and category_id = ${queryParam.categoryId || -1} order by sort asc`"
placeholder="请选择服务类型" :ignoreDisabled="true" allowClear />
</a-form-item>
</a-col>
<a-col :lg="4">

View File

@ -77,18 +77,20 @@ function handleCancel() {
visible.value = false;
}
function usingOrStop(id, izEnabled) {
function usingOrStop(id, izEnabled,refresh = false) {
let params = {
id,
izEnabled
}
saveOrUpdate(params, true).then((res) => {
if(refresh){
if (res.success) {
createMessage.success(res.message);
} else {
createMessage.warning(res.message);
}
emit('success')
}
})
}

View File

@ -1,5 +1,5 @@
import { defHttp } from '/@/utils/http/axios';
import { useMessage } from "/@/hooks/web/useMessage";
import { useMessage } from '/@/hooks/web/useMessage';
const { createConfirm } = useMessage();
@ -11,6 +11,7 @@ enum Api {
deleteBatch = '/services/serviceCategory/configServiceCategory/deleteBatch',
importExcel = '/services/serviceCategory/configServiceCategory/importExcel',
exportXls = '/services/serviceCategory/configServiceCategory/exportXls',
useOrStopCascade = '/services/serviceCategory/configServiceCategory/useOrStopCascade',
}
/**
@ -39,7 +40,7 @@ export const deleteOne = (params,handleSuccess) => {
return defHttp.delete({ url: Api.deleteOne, params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
}
};
/**
*
@ -57,9 +58,9 @@ export const batchDelete = (params, handleSuccess) => {
return defHttp.delete({ url: Api.deleteBatch, data: params }, { joinParamsToUrl: true }).then(() => {
handleSuccess();
});
}
},
});
}
};
/**
*
@ -69,4 +70,12 @@ export const batchDelete = (params, handleSuccess) => {
export const saveOrUpdate = (params, isUpdate) => {
let url = isUpdate ? Api.edit : Api.save;
return defHttp.post({ url: url, params }, { isTransformResponse: false });
}
};
/**
* /
* @param params
*/
export const useOrStopCascade = (params) => {
return defHttp.post({ url: Api.useOrStopCascade, params });
};

View File

@ -9,7 +9,7 @@
<a-form-item name="instructionId">
<template #label><span title="分类标签">分类标签</span></template>
<j-dict-select-tag type='list' v-model:value="queryParam.instructionId"
:dictCode="`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 order by sort asc`"
:dictCode="`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`"
:ignoreDisabled="true" placeholder="请选择服务类别" allowClear />
</a-form-item>
</a-col>

View File

@ -9,7 +9,7 @@
<a-form-item label="分类标签" v-bind="validateInfos.instructionId" id="ConfigServiceTypeForm-instructionId"
name="instructionId">
<j-dict-select-tag type='list' v-model:value="formData.instructionId"
:dictCode="`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 order by sort asc`"
:dictCode="`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`"
placeholder="请选择分类标签" allowClear />
</a-form-item>
</a-col>

View File

@ -22,7 +22,7 @@ import { ref, nextTick, defineExpose } from 'vue';
import ConfigServiceCategoryForm from './ConfigServiceCategoryForm.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { saveOrUpdate } from '../ConfigServiceCategory.api';
import { saveOrUpdate,useOrStopCascade } from '../ConfigServiceCategory.api';
const { createMessage } = useMessage();
const title = ref<string>('');
@ -77,7 +77,7 @@ function handleCancel() {
visible.value = false;
}
function usingOrStop(id, izEnabled) {
function usingOrStop(id, izEnabled,refresh = true) {
let params = {
id,
izEnabled
@ -88,7 +88,24 @@ function usingOrStop(id, izEnabled) {
} else {
createMessage.warning(res.message);
}
if(refresh){
emit('success')
}
})
}
function usingOrStopByCascade(instructionId, izEnabled,refresh = true) {
let params = {
instructionId,
izEnabled
}
useOrStopCascade(params).then((res) => {
if(refresh){
createMessage.success('操作成功');
emit('success')
}
}).catch(()=>{
createMessage.success('操作失败');
})
}
@ -97,6 +114,7 @@ defineExpose({
edit,
disableSubmit,
usingOrStop,
usingOrStopByCascade,
});
</script>

View File

@ -20,6 +20,7 @@ enum Api {
listByDS = '/services/serviceDirective/listByDS',
idListByDS = '/services/serviceDirective/idListByDS',
syncDirective = '/services/serviceDirective/syncDirective',
useOrStopCascade = '/services/serviceDirective/useOrStopCascade',
}
/**
@ -133,3 +134,11 @@ export const syncMediaForAllBiz = (params) => {
export const syncDirective = (dataSourceCode: string, params: any) => {
return defHttp.post({ url: `${Api.syncDirective}?sourceOrgCode=${encodeURIComponent(dataSourceCode)}`, params });
};
/**
* /
* @param params
*/
export const useOrStopCascade = (params) => {
return defHttp.post({ url: Api.useOrStopCascade, params });
};

View File

@ -9,7 +9,7 @@
<a-form-item name="instructionTagId">
<template #label><span title="分类标签">分类标签</span></template>
<j-dict-select-tag v-model:value="queryParam.instructionTagId"
:dictCode="`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 order by sort asc`"
:dictCode="`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`"
placeholder="请选择分类标签" allowClear :ignoreDisabled="true" />
</a-form-item>
</a-col>
@ -18,7 +18,7 @@
<a-form-item name="categoryId">
<template #label><span title="服务类别">服务类别</span></template>
<j-dict-select-tag type="list" v-model:value="queryParam.categoryId"
:dictCode="`nu_config_service_category,category_name,id,del_flag = 0 and instruction_id = '${queryParam.instructionTagId || ''}' order by sort asc`"
:dictCode="`nu_config_service_category,category_name,id,del_flag = 0 and iz_enabled = 0 and instruction_id = '${queryParam.instructionTagId || ''}' order by sort asc`"
placeholder="请选择服务类别" allowClear :ignoreDisabled="true" />
</a-form-item>
</a-col>
@ -27,7 +27,7 @@
<a-form-item name="typeId">
<template #label><span title="服务类型">服务类型</span></template>
<j-dict-select-tag type="list" v-model:value="queryParam.typeId"
:dictCode="`nu_config_service_type,type_name,id,del_flag = 0 and category_id = '${queryParam.categoryId || ''}' order by sort asc`"
:dictCode="`nu_config_service_type,type_name,id,del_flag = 0 and iz_enabled = 0 and category_id = '${queryParam.categoryId || ''}' order by sort asc`"
placeholder="请选择服务类型" allowClear :ignoreDisabled="true" />
</a-form-item>
</a-col> -->
@ -41,16 +41,16 @@
<a-form-item name="bodyTags">
<template #label><span title="体型标签">体型标签</span></template>
<j-dict-select-tag type='list' v-model:value="queryParam.bodyTags"
:dictCode="`nu_config_body_tag,tag_name,id,del_flag = '0' and iz_enabled = 0 order by sort asc`" :ignoreDisabled="true"
placeholder="请选择体型标签" allowClear />
:dictCode="`nu_config_body_tag,tag_name,id,del_flag = '0' and iz_enabled = 0 order by sort asc`"
:ignoreDisabled="true" placeholder="请选择体型标签" allowClear />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="emotionTags">
<template #label><span title="情绪标签">情绪标签</span></template>
<j-dict-select-tag type="list" v-model:value="queryParam.emotionTags"
:dictCode="`nu_config_emotion_tag,tag_name,id,del_flag = '0' and iz_enabled = 0 order by sort asc`" :ignoreDisabled="true"
placeholder="请选择情绪标签" allowClear />
:dictCode="`nu_config_emotion_tag,tag_name,id,del_flag = '0' and iz_enabled = 0 order by sort asc`"
:ignoreDisabled="true" placeholder="请选择情绪标签" allowClear />
</a-form-item>
</a-col>
<!-- <a-col :lg="6">
@ -98,13 +98,13 @@
</div>
<span v-else-if="data.level == 4">{{ data?.title + '(' + data?.cycleTypeName + ')' }}</span>
<span v-else>{{ data?.title }}</span>
<span v-if="data?.izEnabled == '1'" style="color:red;">(已停用)</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"
<a-menu-item v-for="item in menuItems(data)" :key="item.key" :disabled="!item.canAdd"
@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>
@ -288,8 +288,9 @@ import ConfigServiceCategoryModal from '/@/views/services/serviceCategory/compon
import ConfigServiceTypeModal from '/@/views/services/serviceType/components//ConfigServiceTypeModal.vue'
import { queryByKey } from '/@/views/admin/sysconfig/SysConfig.api'
import { getOrgInfo } from '@/api/common/api'
import { CompassOutlined } from '@ant-design/icons-vue';
import { useMessage } from '/@/hooks/web/useMessage';
const { createMessage, createConfirm } = useMessage();
const insRegisterModal = ref();
const catRegisterModal = ref();
const typRegisterModal = ref();
@ -798,11 +799,35 @@ function addInstruction() {
}
//
function usingInstruction(data) {
insRegisterModal.value.usingOrStop(data.instructionId, '0')
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) {
insRegisterModal.value.usingOrStop(data.instructionId, '1')
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 addCategory(data) {
@ -811,11 +836,33 @@ function addCategory(data) {
}
//
function usingCategory(data) {
catRegisterModal.value.usingOrStop(data.categoryId, '0')
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) {
catRegisterModal.value.usingOrStop(data.categoryId, '1')
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) {
@ -824,11 +871,31 @@ function addType(data) {
}
//
function usingType(data) {
typRegisterModal.value.usingOrStop(data.typeId, '0')
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) {
typRegisterModal.value.usingOrStop(data.typeId, '1')
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) {
@ -850,11 +917,11 @@ function editMedia(data) {
}
//
function usingDirective(data) {
registerModal.value.usingOrStop(data.key, '0');
registerModal.value.usingOrStop(data.key, '0', true);
}
//
function stopDirective(data) {
registerModal.value.usingOrStop(data.key, '1');
registerModal.value.usingOrStop(data.key, '1', true);
}
//
function bodyTagsDetail(data) {
@ -868,64 +935,64 @@ function emotionTagsDetail(data) {
function menuItems(data) {
if (data.level === 1) {
const items = [
{ key: 'addIns', label: '新增分类标签', icon: 'ant-design:plus-outlined', action: addInstruction },
{ key: 'addIns', label: '新增分类标签', icon: 'ant-design:plus-outlined', canAdd: true, action: addInstruction },
]
if (data.canAdd) {
items.push({ key: 'addCat', label: '新增服务类别', icon: 'ant-design:plus-outlined', action: addCategory })
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', action: usingInstruction })
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', action: stopInstruction })
items.push({ key: 'stopIns', label: '停用分类标签', icon: 'ant-design:stop-outlined', canAdd: true, action: stopInstruction })
}
return items
}
else if (data.level === 2) {
const items = [
{ key: 'addCat', label: '新增服务类别', icon: 'ant-design:plus-outlined', action: addCategory },
{ key: 'addCat', label: '新增服务类别', icon: 'ant-design:plus-outlined', canAdd: data.canAdd, action: addCategory },
]
if (data.canAdd) {
items.push({ key: 'addTyp', label: '新增服务类型', icon: 'ant-design:plus-outlined', action: addType })
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', action: usingCategory })
items.push({ key: 'usingCat', label: '启用服务类别', icon: 'ant-design:check-circle-outlined', canAdd: data.canAdd, action: usingCategory })
} else if (data.izEnabled === '0') {
items.push({ key: 'stopCat', label: '停用服务类别', icon: 'ant-design:stop-outlined', action: stopCategory })
items.push({ key: 'stopCat', label: '停用服务类别', icon: 'ant-design:stop-outlined', canAdd: data.canAdd, action: stopCategory })
}
return items
}
else if (data.level === 3) {
const items = [
{ key: 'addTyp', label: '新增服务类型', icon: 'ant-design:plus-outlined', action: addType },
{ key: 'addTyp', label: '新增服务类型', icon: 'ant-design:plus-outlined', canAdd: data.canAdd, action: addType },
]
if (data.canAdd) {
items.push({ key: 'addDir', label: '新增服务指令', icon: 'ant-design:plus-outlined', action: addDirective })
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', action: usingType })
items.push({ key: 'usingTyp', label: '启用服务类型', icon: 'ant-design:check-circle-outlined', canAdd: data.canAdd, action: usingType })
} else if (data.izEnabled === '0') {
items.push({ key: 'stopTyp', label: '停用服务类型', icon: 'ant-design:stop-outlined', action: stopType })
items.push({ key: 'stopTyp', label: '停用服务类型', icon: 'ant-design:stop-outlined', canAdd: data.canAdd, action: stopType })
}
return items
}
else if (data.level === 4) {
const items = [
{ key: 'editDir', label: '编辑服务指令', icon: 'ant-design:edit-outlined', action: editDirective },
{ key: 'editMedia', label: '编辑指令资源', icon: 'ant-design:edit-outlined', action: editMedia },
{ 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', action: editMedia },
]
// if (data.canAdd) {
// items.push({ key: 'addDir', label: '', icon: 'ant-design:plus-outlined', action: addDirective })
// 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', action: usingDirective })
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', action: stopDirective })
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', action: bodyTagsDetail })
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', action: emotionTagsDetail })
items.push({ key: 'emotionTagsDetail', label: '查看情绪标签', icon: 'ant-design:stop-outlined', canAdd: true, action: emotionTagsDetail })
}
return items
}
@ -935,9 +1002,9 @@ function menuItems(data) {
// 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)
// 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)

View File

@ -9,7 +9,7 @@
<a-form-item label="分类标签" v-bind="validateInfos.instructionTagId"
id="ConfigServiceDirectiveForm-instructionTagId" name="instructionTagId">
<j-dict-select-tag v-model:value="formData.instructionTagId" :orgCode="mainOrgCode"
:dictCode="`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 order by sort asc`"
:dictCode="`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`"
placeholder="请选择分类标签" allowClear @upDictCode="upInstructionDictCode" :disabled="!!formData.id" />
</a-form-item>
</a-col>
@ -107,7 +107,10 @@
<a-col :span="12" v-show="showMedia">
<a-form-item label="服务指令图片" v-bind="validateInfos.previewFile">
<span v-if="disabled && !formData.previewFile">暂无文件</span>
<JImageUpload v-else :fileMax="1" v-model:value="formData.previewFile">
<JImageUpload v-else-if="!mediaApiAddress" :fileMax="1" v-model:value="formData.previewFile"
</JImageUpload>
<JImageUpload v-else :fileMax="1" v-model:value="formData.previewFile"
:value="mediaApiAddress + mediaPath + formData.previewFile">
</JImageUpload>
</a-form-item>
</a-col>
@ -142,7 +145,8 @@
<a-col :span="12" v-if="!!formData.mp3File">
<a-form-item label="指令音频预览" id="ConfigServiceDirectiveForm-mp3File">
<audio controls disabled="false">
<source :src="getFileAccessHttpUrl(formData.mp3File)">
<source
:src="!!mediaApiAddress ? mediaApiAddress + mediaPath + formData.mp3File : getFileAccessHttpUrl(formData.mp3File)">
</audio>
</a-form-item>
</a-col>
@ -154,7 +158,8 @@
<a-col :span="12" v-if="!!formData.mp4File" :push="!!formData.mp3File ? 0 : 12">
<a-form-item label="指令视频预览" id="ConfigServiceDirectiveForm-mp4File">
<video controls>
<source :src="getFileAccessHttpUrl(formData.mp4File)">
<source
:src="!!mediaApiAddress ? mediaApiAddress + mediaPath + formData.mp4File : getFileAccessHttpUrl(formData.mp4File)">
</video>
</a-form-item>
</a-col>
@ -163,10 +168,15 @@
<span>暂无文件</span>
</a-form-item>
</a-col>
</a-row>
<a-row>
<a-col :span="12">
<a-form-item label="即时指令图标" v-bind="validateInfos.immediateFile">
<span v-if="disabled && !formData.immediateFile">暂无文件</span>
<JImageUpload v-else :fileMax="1" v-model:value="formData.immediateFile">
<JImageUpload v-else-if="!mediaApiAddress" :fileMax="1" v-model:value="formData.immediateFile"
</JImageUpload>
<JImageUpload v-else :fileMax="1" v-model:value="formData.immediateFile"
:value="mediaApiAddress + mediaPath + formData.immediateFile">
</JImageUpload>
</a-form-item>
</a-col>
@ -190,6 +200,7 @@ import { saveOrUpdate, syncMediaForBiz, syncMediaForAllBiz } from '../ConfigServ
import { Form } from 'ant-design-vue';
import JFormContainer from '/@/components/Form/src/container/JFormContainer.vue';
import { getFileAccessHttpUrl } from '/@/utils/common/compUtils';
import { env } from 'process';
const onPriceKeydown = (e: KeyboardEvent) => {
const key = e.key;
@ -213,6 +224,7 @@ const props = defineProps({
formData: { type: Object, default: () => ({}) },
formBpm: { type: Boolean, default: true },
mainOrgCode: '',
mediaApiAddress: '',//
});
const bodyTagDictCode = ref(`nu_config_body_tag,tag_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`)
const emotionTagDictCode = ref(`nu_config_emotion_tag,tag_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`)
@ -256,6 +268,7 @@ const instructionTagName = ref('')
const categoryName = ref('')
const typeName = ref('')
const cycleTypeName = ref('')
const mediaPath = ref(import.meta.env.VITE_NGINX_MEDIA_LOCATION)
//
const validatorRules = reactive({
categoryId: [{ required: true, message: '请选择服务类别!' },],
@ -393,7 +406,7 @@ watch(
if (!newInstructionTagId) {
categoryDictCode.value = 'nu_config_service_category,category_name,id,1=2';
} else {
categoryDictCode.value = `nu_config_service_category,category_name,id,del_flag = 0 and instruction_id = '${newInstructionTagId}' order by sort asc`;
categoryDictCode.value = `nu_config_service_category,category_name,id,del_flag = 0 and iz_enabled = 0 and instruction_id = '${newInstructionTagId}' order by sort asc`;
}
}
);
@ -405,9 +418,9 @@ watch(
formData.cycleType = ''
}
if (!newCategoryId) {
typeDictCode.value = 'nu_config_service_type,type_name,id,del_flag = 99 order by sort asc';
typeDictCode.value = 'nu_config_service_type,type_name,id,1=2';
} else {
typeDictCode.value = `nu_config_service_type,type_name,id,del_flag = 0 and category_id = '${newCategoryId}' order by sort asc`;
typeDictCode.value = `nu_config_service_type,type_name,id,del_flag = 0 and iz_enabled = 0 and category_id = '${newCategoryId}' order by sort asc`;
}
}
);
@ -565,6 +578,9 @@ function syncMediaForAllBizFunc() {
});
}
onMounted(() => {
})
defineExpose({
add,

View File

@ -19,7 +19,8 @@
:footer-style="{ textAlign: 'right' }" @close="handleCancel">
<a-spin :spinning="loading">
<ConfigServiceDirectiveForm ref="registerForm" v-if="visible" @ok="submitCallback" :formDisabled="disableSubmit"
:formBpm="false" :mainOrgCode="mainOrgCode"></ConfigServiceDirectiveForm>
:formBpm="false" :mainOrgCode="mainOrgCode" :mediaApiAddress="opeType == 'dmlook' ? mediaApiAddress : ''">
</ConfigServiceDirectiveForm>
</a-spin>
<template #footer>
<a-button @click="handleCancel" style="margin-right: 8px;">关闭</a-button>
@ -40,7 +41,7 @@
<DirectiveRespositoryList ref="dmRef" :mainOrgCode="mainOrgCode"></DirectiveRespositoryList>
</j-modal> -->
<a-drawer :title="'指令库'" width="80vw" v-model:visible="dmVisible" :closable="true"
:footer-style="{ textAlign: 'right' }" @close="handleCancelDM" :maskClosable="false">
:footer-style="{ textAlign: 'right' }" @close="handleCancelDM" :maskClosable="true">
<a-spin :spinning="loading">
<DirectiveRespositoryList ref="dmRef" :mainOrgCode="mainOrgCode"></DirectiveRespositoryList>
</a-spin>
@ -56,7 +57,7 @@ import { ref, nextTick, defineExpose, defineProps } from 'vue';
import ConfigServiceDirectiveForm from './ConfigServiceDirectiveForm.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { saveOrUpdate, queryById, syncDirective } from '../ConfigServiceDirective.api';
import { saveOrUpdate, useOrStopCascade, queryById, syncDirective } from '../ConfigServiceDirective.api';
import DirectiveRespositoryList from './DirectiveRespositoryList.vue'
import { clearCache } from '/@/utils/cache/cacheUtil'
@ -65,13 +66,14 @@ const dmRef = ref()
const loading = ref(false)
const { createMessage, createConfirm } = useMessage();
const props = defineProps({
mediaApiAddress: '',//
});
const title = ref<string>('');
const visible = ref<boolean>(false);
const disableSubmit = ref<boolean>(false);
const registerForm = ref();
const emit = defineEmits(['register', 'success']);
const opeType = ref('')// add edit editMedia- look audit auditMedia-
const opeType = ref('')// add edit editMedia- look dmlook audit auditMedia-
const dmVisible = ref(false)
function handleCancelDM() {
@ -176,18 +178,20 @@ function handleCancel() {
visible.value = false;
}
function usingOrStop(id, izEnabled) {
function usingOrStop(id, izEnabled, refresh = false) {
let params = {
id,
izEnabled
}
saveOrUpdate(params, true).then((res) => {
if (refresh) {
if (res.success) {
createMessage.success(res.message);
} else {
createMessage.warning(res.message);
}
emit('success')
}
})
}
@ -232,12 +236,30 @@ function handlePullDM() {
});
}
function usingOrStopByCascade(instructionTagId, categoryId, typeId, izEnabled, refresh = true) {
let params = {
instructionTagId,
categoryId,
typeId,
izEnabled
}
useOrStopCascade(params).then((res) => {
if (refresh) {
createMessage.success('操作成功');
emit('success')
}
}).catch(() => {
createMessage.success('操作失败');
})
}
defineExpose({
add,
edit,
editMedia,
disableSubmit,
usingOrStop,
usingOrStopByCascade,
queryByIdFunc,
opeType,
queryAndEditMedia,

View File

@ -9,7 +9,7 @@
<a-form-item name="instructionTagId">
<template #label><span title="分类标签">分类标签</span></template>
<j-dict-select-tag v-model:value="queryParam.instructionTagId" :orgCode="mainOrgCode"
:dictCode="`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 order by sort asc`"
:dictCode="`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`"
placeholder="请选择分类标签" allowClear :ignoreDisabled="true" />
</a-form-item>
</a-col>
@ -18,7 +18,7 @@
<a-form-item name="categoryId">
<template #label><span title="服务类别">服务类别</span></template>
<j-dict-select-tag type="list" v-model:value="queryParam.categoryId" :orgCode="mainOrgCode"
:dictCode="`nu_config_service_category,category_name,id,del_flag = 0 and instruction_id = '${queryParam.instructionTagId || ''}' order by sort asc`"
:dictCode="`nu_config_service_category,category_name,id,del_flag = 0 and iz_enabled = 0 and instruction_id = '${queryParam.instructionTagId || ''}' order by sort asc`"
placeholder="请选择服务类别" allowClear :ignoreDisabled="true" />
</a-form-item>
</a-col>
@ -27,7 +27,7 @@
<a-form-item name="typeId">
<template #label><span title="服务类型">服务类型</span></template>
<j-dict-select-tag type="list" v-model:value="queryParam.typeId" :orgCode="mainOrgCode"
:dictCode="`nu_config_service_type,type_name,id,del_flag = 0 and category_id = '${queryParam.categoryId || ''}' order by sort asc`"
:dictCode="`nu_config_service_type,type_name,id,del_flag = 0 and iz_enabled = 0 and category_id = '${queryParam.categoryId || ''}' order by sort asc`"
placeholder="请选择服务类型" allowClear :ignoreDisabled="true" />
</a-form-item>
</a-col>
@ -41,25 +41,25 @@
<a-form-item name="bodyTags">
<template #label><span title="体型标签">体型标签</span></template>
<j-dict-select-tag type='list' v-model:value="queryParam.bodyTags" :orgCode="mainOrgCode"
:dictCode="`nu_config_body_tag,tag_name,id,del_flag = '0' and iz_enabled = 0 order by sort asc`" :ignoreDisabled="true"
placeholder="请选择体型标签" allowClear />
:dictCode="`nu_config_body_tag,tag_name,id,del_flag = '0' and iz_enabled = 0 order by sort asc`"
:ignoreDisabled="true" placeholder="请选择体型标签" allowClear />
</a-form-item>
</a-col>
<a-col :lg="6">
<a-form-item name="emotionTags">
<template #label><span title="情绪标签">情绪标签</span></template>
<j-dict-select-tag type="list" v-model:value="queryParam.emotionTags" :orgCode="mainOrgCode"
:dictCode="`nu_config_emotion_tag,tag_name,id,del_flag = '0' and iz_enabled = 0 order by sort asc`" :ignoreDisabled="true"
placeholder="请选择情绪标签" allowClear />
:dictCode="`nu_config_emotion_tag,tag_name,id,del_flag = '0' and iz_enabled = 0 order by sort asc`"
:ignoreDisabled="true" placeholder="请选择情绪标签" allowClear />
</a-form-item>
</a-col>
<a-col :lg="6">
<!-- <a-col :lg="6">
<a-form-item name="izEnabled">
<template #label><span title="是否启用">是否启用</span></template>
<j-dict-select-tag type='list' v-model:value="queryParam.izEnabled" dictCode="iz_enabled"
:ignoreDisabled="true" placeholder="请选择是否启用" allowClear />
</a-form-item>
</a-col>
</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">
@ -87,7 +87,8 @@
</BasicTable>
</div>
<!-- 表单区域 -->
<ConfigServiceDirectiveModal ref="registerModal" @success="handleSuccess" :mainOrgCode="mainOrgCode">
<ConfigServiceDirectiveModal ref="registerModal" :mediaApiAddress="mediaApiAddress" @success="handleSuccess"
:mainOrgCode="mainOrgCode">
</ConfigServiceDirectiveModal>
</div>
</template>
@ -102,10 +103,13 @@ import ConfigServiceDirectiveModal from './ConfigServiceDirectiveModal.vue'
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 { getOrgInfo, getOrgUrlByOrgCode } from '@/api/common/api'
const props = defineProps({
mainOrgCode: '',
});
const mediaApiAddress = ref()//
const orgName = ref('')
const formRef = ref();
const queryParam = reactive<any>({
instructionTagId: '',
@ -150,7 +154,9 @@ const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
beforeFetch: async (params) => {
// let res = await idListByDS({ dataSourceCode: 'master' })
params.dataSourceCode = props.mainOrgCode
if (excludeIds.value.length) {
params.excludeIds = excludeIds.value.join(',')
}
params.izEnabled = '0'
let rangerQuery = await setRangeQuery();
return Object.assign(params, rangerQuery);
@ -171,11 +177,11 @@ const labelCol = reactive({
xs: 24,
sm: 4,
xl: 6,
xxl: 4
xxl: 5
});
const wrapperCol = reactive({
xs: 24,
sm: 20,
sm: 19,
});
/**
@ -183,9 +189,9 @@ const wrapperCol = reactive({
*/
function handleDetail(record: Recordable) {
registerModal.value.disableSubmit = true;
registerModal.value.opeType = 'look';
registerModal.value.opeType = 'dmlook';
record.orgCode_ = props.mainOrgCode
registerModal.value.edit(record, false, false);
registerModal.value.edit(record, false, true);
}
@ -312,6 +318,12 @@ function getSelectedIds() {
//
onMounted(() => {
getOrgInfo().then(res => {
orgName.value = res.orgName
})
getOrgUrlByOrgCode({ orgCode: props.mainOrgCode }).then(res => {
mediaApiAddress.value = res.url
})
});
defineExpose({

View File

@ -9,7 +9,7 @@
<a-form-item label="服务类别" v-bind="validateInfos.categoryId" id="ConfigServiceDirectiveForm-categoryId"
name="categoryId">
<j-dict-select-tag type="list" v-model:value="formData.categoryId"
:dictCode="`nu_config_service_category,category_name,id,del_flag = 0 order by sort asc`"
:dictCode="`nu_config_service_category,category_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`"
placeholder="请选择服务类别" allow-clear />
</a-form-item>
</a-col>
@ -258,9 +258,9 @@ watch(
(newCategoryId) => {
if (!newCategoryId) {
formData.typeId = '';
typeDictCode.value = 'nu_config_service_type,type_name,id,del_flag = 99 order by sort asc';
typeDictCode.value = 'nu_config_service_type,type_name,id,1=2';
} else {
typeDictCode.value = `nu_config_service_type,type_name,id,del_flag = 0 and category_id = '${newCategoryId}' order by sort asc`;
typeDictCode.value = `nu_config_service_type,type_name,id,del_flag = 0 and iz_enabled = 0 and category_id = '${newCategoryId}' order by sort asc`;
}
}
);

View File

@ -9,7 +9,7 @@
<a-form-item name="categoryId">
<template #label><span title="服务类别">服务类别</span></template>
<j-dict-select-tag type="list" v-model:value="queryParam.categoryId"
:dictCode="`nu_config_service_category,category_name,id,del_flag = 0 order by sort asc`"
:dictCode="`nu_config_service_category,category_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`"
:ignoreDisabled="true" placeholder="请选择服务类别" allow-clear />
</a-form-item>
</a-col>
@ -17,7 +17,7 @@
<a-form-item name="typeId">
<template #label><span title="服务类型">服务类型</span></template>
<j-dict-select-tag type="list" v-model:value="queryParam.typeId"
:dictCode="`nu_config_service_type,type_name,id,del_flag = 0 and category_id = ${queryParam.categoryId || -1} order by sort asc`" placeholder="请选择服务类型"
:dictCode="`nu_config_service_type,type_name,id,del_flag = 0 and iz_enabled = 0 and category_id = ${queryParam.categoryId || -1} order by sort asc`" placeholder="请选择服务类型"
:ignoreDisabled="true" allowClear />
</a-form-item>
</a-col>

View File

@ -10,7 +10,8 @@ enum Api {
deleteOne = '/services/ServiceType/configServiceType/delete',
deleteBatch = '/services/ServiceType/configServiceType/deleteBatch',
importExcel = '/services/ServiceType/configServiceType/importExcel',
exportXls = '/services/ServiceType/configServiceType/exportXls'
exportXls = '/services/ServiceType/configServiceType/exportXls',
useOrStopCascade='/services/ServiceType/configServiceType/useOrStopCascade',
}
/**
@ -72,3 +73,10 @@ export const saveOrUpdate = (params, isUpdate) => {
}
/**
* /
* @param params
*/
export const useOrStopCascade = (params) => {
return defHttp.post({ url: Api.useOrStopCascade, params });
};

View File

@ -141,12 +141,12 @@ const wrapperCol = reactive({
});
// dictCode
const instructionDictCode = 'nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 order by sort asc';
const instructionDictCode = 'nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc';
const categoryDictCode = computed(() => {
if (!queryParam.instructionId) {
return 'nu_config_service_category,category_name,id,del_flag = 0';
return 'nu_config_service_category,category_name,id,del_flag = 0 and iz_enabled = 0';
}
return `nu_config_service_category,category_name,id,del_flag = 0 and instruction_id = ${queryParam.instructionId} order by sort asc`;
return `nu_config_service_category,category_name,id,del_flag = 0 and iz_enabled = 0 and instruction_id = ${queryParam.instructionId} order by sort asc`;
});
// instructionId

View File

@ -9,7 +9,7 @@
<a-form-item label="分类标签" v-bind="validateInfos.instructionId" id="ConfigServiceTypeForm-instructionId"
name="instructionId">
<j-dict-select-tag type='list' v-model:value="formData.instructionId"
:dictCode="`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 order by sort asc`"
:dictCode="`nu_config_service_instruction_tag,instruction_name,id,del_flag = 0 and iz_enabled = 0 order by sort asc`"
placeholder="请选择分类标签" allowClear />
</a-form-item>
</a-col>
@ -92,7 +92,7 @@ const categoryDictCode = computed(() => {
if (!formData.instructionId) {
return 'nu_config_service_category,category_name,id,1=2';
}
return `nu_config_service_category,category_name,id,del_flag = 0 and instruction_id = '${formData.instructionId}' order by sort asc`;
return `nu_config_service_category,category_name,id,del_flag = 0 and iz_enabled = 0 and instruction_id = '${formData.instructionId}' order by sort asc`;
});
// instructionId categoryId

View File

@ -20,7 +20,7 @@ import { ref, nextTick, defineExpose } from 'vue';
import ConfigServiceTypeForm from './ConfigServiceTypeForm.vue'
import JModal from '/@/components/Modal/src/JModal/JModal.vue';
import { useMessage } from '/@/hooks/web/useMessage';
import { saveOrUpdate } from '../ConfigServiceType.api';
import { saveOrUpdate ,useOrStopCascade } from '../ConfigServiceType.api';
const { createMessage } = useMessage();
const title = ref<string>('');
@ -76,18 +76,36 @@ function handleCancel() {
visible.value = false;
}
function usingOrStop(id, izEnabled) {
function usingOrStop(id, izEnabled,refresh = true) {
let params = {
id,
izEnabled
}
saveOrUpdate(params, true).then((res) => {
if(refresh){
if (res.success) {
createMessage.success(res.message);
} else {
createMessage.warning(res.message);
}
emit('success')
}
})
}
function usingOrStopByCascade(instructionId,categoryId, izEnabled,refresh = true) {
let params = {
instructionId,
categoryId,
izEnabled
}
useOrStopCascade(params).then((res) => {
if(refresh){
createMessage.success('操作成功');
emit('success')
}
}).catch(()=>{
createMessage.success('操作失败');
})
}
@ -96,6 +114,7 @@ defineExpose({
edit,
disableSubmit,
usingOrStop,
usingOrStopByCascade,
});
</script>